< prev index next >

src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java

Print this page
*** 61,10 ***
--- 61,11 ---
   *  If you write code that depends on this, you do so at your own risk.
   *  This code and its internal interfaces are subject to change or
   *  deletion without notice.</b>
   */
  public class Gen extends JCTree.Visitor {
+     private static final Object[] NO_STATIC_ARGS = new Object[0];
      protected static final Context.Key<Gen> genKey = new Context.Key<>();
  
      private final Log log;
      private final Symtab syms;
      private final Check chk;

*** 75,10 ***
--- 76,11 ---
      private final Name accessDollar;
      private final Types types;
      private final Lower lower;
      private final Annotate annotate;
      private final StringConcat concat;
+     private final TransPrimitiveClass transPrimitiveClass;
  
      /** Format of stackmap tables to be generated. */
      private final Code.StackMapFormat stackMap;
  
      /** A type that serves as the expected type for all method expressions.

*** 111,10 ***
--- 113,11 ---
  
          methodType = new MethodType(null, null, null, syms.methodClass);
          accessDollar = names.
              fromString("access" + target.syntheticNameChar());
          lower = Lower.instance(context);
+         transPrimitiveClass = TransPrimitiveClass.instance(context);
  
          Options options = Options.instance(context);
          lineDebugInfo =
              options.isUnset(G_CUSTOM) ||
              options.isSet(G_CUSTOM, "lines");

*** 259,17 ***
              return sym;
  
          return sym.clone(site.tsym);
      }
  
      /** Insert a reference to given type in the constant pool,
       *  checking for an array with too many dimensions;
       *  return the reference's index.
       *  @param type   The type for which a reference is inserted.
       */
      int makeRef(DiagnosticPosition pos, Type type) {
!         return poolWriter.putClass(checkDimension(pos, type));
      }
  
      /** Check if the given type is an array with too many dimensions.
       */
      private Type checkDimension(DiagnosticPosition pos, Type t) {
--- 262,31 ---
              return sym;
  
          return sym.clone(site.tsym);
      }
  
+     /** Insert a reference to given type in the constant pool,
+      *  checking for an array with too many dimensions;
+      *  return the reference's index.
+      *  @param type   The type for which a reference is inserted.
+      */
+     int makeRef(DiagnosticPosition pos, Type type, boolean emitQtype) {
+         checkDimension(pos, type);
+         if (emitQtype) {
+             return poolWriter.putClass(new ConstantPoolQType(type, types));
+         } else {
+             return poolWriter.putClass(type);
+         }
+     }
+ 
      /** Insert a reference to given type in the constant pool,
       *  checking for an array with too many dimensions;
       *  return the reference's index.
       *  @param type   The type for which a reference is inserted.
       */
      int makeRef(DiagnosticPosition pos, Type type) {
!         return makeRef(pos, type, false);
      }
  
      /** Check if the given type is an array with too many dimensions.
       */
      private Type checkDimension(DiagnosticPosition pos, Type t) {

*** 981,10 ***
--- 998,13 ---
                  if (code.isAlive()) {
                      code.statBegin(TreeInfo.endPos(tree.body));
                      if (env.enclMethod == null ||
                          env.enclMethod.sym.type.getReturnType().hasTag(VOID)) {
                          code.emitop0(return_);
+                     } else if (env.enclMethod.sym.isPrimitiveObjectFactory()) {
+                         items.makeLocalItem(env.enclMethod.factoryProduct).load();
+                         code.emitop0(areturn);
                      } else {
                          // sometime dead code seems alive (4415991);
                          // generate a small loop instead
                          int startpc = code.entryPoint();
                          CondItem c = items.makeCondItem(goto_);

*** 1044,11 ***
              }
  
              // If method is not static, create a new local variable address
              // for `this'.
              if ((tree.mods.flags & STATIC) == 0) {
!                 Type selfType = meth.owner.type;
                  if (meth.isConstructor() && selfType != syms.objectType)
                      selfType = UninitializedType.uninitializedThis(selfType);
                  code.setDefined(
                          code.newLocal(
                              new VarSymbol(FINAL, names._this, selfType, meth.owner)));
--- 1064,11 ---
              }
  
              // If method is not static, create a new local variable address
              // for `this'.
              if ((tree.mods.flags & STATIC) == 0) {
!                 Type selfType = meth.owner.isPrimitiveClass() ? meth.owner.type.asValueType() : meth.owner.type;
                  if (meth.isConstructor() && selfType != syms.objectType)
                      selfType = UninitializedType.uninitializedThis(selfType);
                  code.setDefined(
                          code.newLocal(
                              new VarSymbol(FINAL, names._this, selfType, meth.owner)));

*** 1109,10 ***
--- 1129,41 ---
  
      public void visitWhileLoop(JCWhileLoop tree) {
          genLoop(tree, tree.body, tree.cond, List.nil(), true);
      }
  
+     public void visitWithField(JCWithField tree) {
+         switch(tree.field.getTag()) {
+             case IDENT:
+                 Symbol sym = ((JCIdent) tree.field).sym;
+                 items.makeThisItem().load();
+                 genExpr(tree.value, tree.field.type).load();
+                 sym = binaryQualifier(sym, env.enclClass.type);
+                 code.emitop2(withfield, sym, PoolWriter::putMember);
+                 result = items.makeStackItem(tree.type);
+                 break;
+             case SELECT:
+                 JCFieldAccess fieldAccess = (JCFieldAccess) tree.field;
+                 sym = TreeInfo.symbol(fieldAccess);
+                 // JDK-8207332: To maintain the order of side effects, must compute value ahead of field
+                 genExpr(tree.value, tree.field.type).load();
+                 genExpr(fieldAccess.selected, fieldAccess.selected.type).load();
+                 if (Code.width(tree.field.type) == 2) {
+                     code.emitop0(dup_x2);
+                     code.emitop0(pop);
+                 } else {
+                     code.emitop0(swap);
+                 }
+                 sym = binaryQualifier(sym, fieldAccess.selected.type);
+                 code.emitop2(withfield, sym, PoolWriter::putMember);
+                 result = items.makeStackItem(tree.type);
+                 break;
+             default:
+                 Assert.check(false);
+         }
+     }
+ 
      public void visitForLoop(JCForLoop tree) {
          int limit = code.nextreg;
          genStats(tree.init, env);
          genLoop(tree, tree.body, tree.cond, tree.step, true);
          code.endScopes(limit);

*** 1965,10 ***
--- 2016,11 ---
          // the parameters of the constructor's external type (that is,
          // any implicit outer instance appears as first parameter).
          genArgs(tree.args, tree.constructor.externalType(types).getParameterTypes());
  
          items.makeMemberItem(tree.constructor, true).invoke();
+ 
          result = items.makeStackItem(tree.type);
      }
  
      public void visitNewArray(JCNewArray tree) {
          setTypeAnnotationPositions(tree.pos);

*** 2003,11 ***
                  log.error(pos, Errors.LimitDimensions);
                  nerrs++;
              }
              int elemcode = Code.arraycode(elemtype);
              if (elemcode == 0 || (elemcode == 1 && ndims == 1)) {
!                 code.emitAnewarray(makeRef(pos, elemtype), type);
              } else if (elemcode == 1) {
                  code.emitMultianewarray(ndims, makeRef(pos, type), type);
              } else {
                  code.emitNewarray(elemcode, type);
              }
--- 2055,11 ---
                  log.error(pos, Errors.LimitDimensions);
                  nerrs++;
              }
              int elemcode = Code.arraycode(elemtype);
              if (elemcode == 0 || (elemcode == 1 && ndims == 1)) {
!                 code.emitAnewarray(makeRef(pos, elemtype, types.isPrimitiveClass(elemtype)), type);
              } else if (elemcode == 1) {
                  code.emitMultianewarray(ndims, makeRef(pos, type), type);
              } else {
                  code.emitNewarray(elemcode, type);
              }

*** 2229,14 ***
          setTypeAnnotationPositions(tree.pos);
          // Additional code is only needed if we cast to a reference type
          // which is not statically a supertype of the expression's type.
          // For basic types, the coerce(...) in genExpr(...) will do
          // the conversion.
          if (!tree.clazz.type.isPrimitive() &&
             !types.isSameType(tree.expr.type, tree.clazz.type) &&
!            types.asSuper(tree.expr.type, tree.clazz.type.tsym) == null) {
!             code.emitop2(checkcast, checkDimension(tree.pos(), tree.clazz.type), PoolWriter::putClass);
          }
      }
  
      public void visitWildcard(JCWildcard tree) {
          throw new AssertionError(this.getClass().getName());
--- 2281,22 ---
          setTypeAnnotationPositions(tree.pos);
          // Additional code is only needed if we cast to a reference type
          // which is not statically a supertype of the expression's type.
          // For basic types, the coerce(...) in genExpr(...) will do
          // the conversion.
+         // primitive reference conversion is a nop when we bifurcate the primitive class, as the VM sees a subtyping relationship.
          if (!tree.clazz.type.isPrimitive() &&
             !types.isSameType(tree.expr.type, tree.clazz.type) &&
!             (!tree.clazz.type.isReferenceProjection() || !types.isSameType(tree.clazz.type.asValueType(), tree.expr.type) || true) &&
!            !types.isSubtype(tree.expr.type, tree.clazz.type)) {
+             checkDimension(tree.pos(), tree.clazz.type);
+             if (types.isPrimitiveClass(tree.clazz.type)) {
+                 code.emitop2(checkcast, new ConstantPoolQType(tree.clazz.type, types), PoolWriter::putClass);
+             } else {
+                 code.emitop2(checkcast, tree.clazz.type, PoolWriter::putClass);
+             }
+ 
          }
      }
  
      public void visitWildcard(JCWildcard tree) {
          throw new AssertionError(this.getClass().getName());

*** 2294,14 ***
  
      public void visitSelect(JCFieldAccess tree) {
          Symbol sym = tree.sym;
  
          if (tree.name == names._class) {
!             code.emitLdc((LoadableConstant)checkDimension(tree.pos(), tree.selected.type));
              result = items.makeStackItem(pt);
              return;
!        }
  
          Symbol ssym = TreeInfo.symbol(tree.selected);
  
          // Are we selecting via super?
          boolean selectSuper =
--- 2354,14 ---
  
      public void visitSelect(JCFieldAccess tree) {
          Symbol sym = tree.sym;
  
          if (tree.name == names._class) {
!             code.emitLdc((LoadableConstant) tree.selected.type, makeRef(tree.pos(), tree.selected.type, tree.selected.type.isPrimitiveClass()));
              result = items.makeStackItem(pt);
              return;
!         }
  
          Symbol ssym = TreeInfo.symbol(tree.selected);
  
          // Are we selecting via super?
          boolean selectSuper =

*** 2353,10 ***
--- 2413,22 ---
                  }
              }
          }
      }
  
+     public void visitDefaultValue(JCDefaultValue tree) {
+         if (tree.type.isPrimitiveClass()) {
+             code.emitop2(defaultvalue, checkDimension(tree.pos(), tree.type), PoolWriter::putClass);
+         } else if (tree.type.isReference()) {
+             code.emitop0(aconst_null);
+         } else {
+             code.emitop0(zero(Code.typecode(tree.type)));
+         }
+         result = items.makeStackItem(tree.type);
+         return;
+     }
+ 
      public boolean isInvokeDynamic(Symbol sym) {
          return sym.kind == MTH && ((MethodSymbol)sym).isDynamic();
      }
  
      public void visitLiteral(JCLiteral tree) {

*** 2409,10 ***
--- 2481,11 ---
              this.toplevel = env.toplevel;
              this.endPosTable = toplevel.endPositions;
              /* method normalizeDefs() can add references to external classes into the constant pool
               */
              cdef.defs = normalizeDefs(cdef.defs, c);
+             cdef = transPrimitiveClass.translateTopLevelClass(cdef, make);
              generateReferencesToPrunedTree(c);
              Env<GenContext> localEnv = new Env<>(cdef, new GenContext());
              localEnv.toplevel = env.toplevel;
              localEnv.enclClass = cdef;
  
< prev index next >