< prev index next >

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

Print this page
@@ -62,10 +62,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;

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

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

@@ -130,10 +133,12 @@
          poolWriter = new PoolWriter(types, names);
  
          // ignore cldc because we cannot have both stackmap formats
          this.stackMap = StackMapFormat.JSR202;
          annotate = Annotate.instance(context);
+         Source source = Source.instance(context);
+         allowPrimitiveClasses = Source.Feature.PRIMITIVE_CLASSES.allowedInSource(source) && options.isSet("enablePrimitiveClasses");
          qualifiedSymbolCache = new HashMap<>();
      }
  
      /** Switches
       */

@@ -174,10 +179,12 @@
      List<LocalItem> stackBeforeSwitchExpression;
      LocalItem switchResult;
      Set<JCMethodInvocation> invocationsWithPatternMatchingCatch = Set.of();
      ListBuffer<int[]> patternMatchingInvocationRanges;
  
+     boolean allowPrimitiveClasses;
+ 
      /** Cache the symbol to reflect the qualifying type.
       *  key: corresponding type
       *  value: qualified symbol
       */
      Map<Type, Symbol> qualifiedSymbolCache;

@@ -263,17 +270,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 poolWriter.putClass(checkDimension(pos, 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) {

@@ -323,11 +344,11 @@
                      Type site, Name name, List<Type> argtypes,
                      boolean isStatic) {
          Symbol msym = rs.
              resolveInternalMethod(pos, attrEnv, site, name, argtypes, null);
          if (isStatic) items.makeStaticItem(msym).invoke();
-         else items.makeMemberItem(msym, name == names.init).invoke();
+         else items.makeMemberItem(msym, names.isInitOrVNew(name)).invoke();
      }
  
      /** Is the given method definition an access method
       *  resulting from a qualified super? This is signified by an odd
       *  access code.

@@ -546,11 +567,11 @@
       *                   constructor's definition.
       *  @param initCode  The list of instance initializer statements.
       *  @param initTAs  Type annotations from the initializer expression.
       */
      void normalizeMethod(JCMethodDecl md, List<JCStatement> initCode, List<TypeCompound> initTAs) {
-         if (md.name == names.init && TreeInfo.isInitialConstructor(md)) {
+         if (names.isInitOrVNew(md.name) && TreeInfo.isInitialConstructor(md)) {
              // We are seeing a constructor that does not call another
              // constructor of the same class.
              List<JCStatement> stats = md.body.stats;
              ListBuffer<JCStatement> newstats = new ListBuffer<>();
  

@@ -949,11 +970,11 @@
           */
          void genMethod(JCMethodDecl tree, Env<GenContext> env, boolean fatcode) {
              MethodSymbol meth = tree.sym;
              int extras = 0;
              // Count up extra parameters
-             if (meth.isConstructor()) {
+             if (meth.isInitOrVNew()) {
                  extras++;
                  if (meth.enclClass().isInner() &&
                      !meth.enclClass().isStatic()) {
                      extras++;
                  }

@@ -989,10 +1010,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.isValueObjectFactory()) {
+                         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_);

@@ -1043,21 +1067,22 @@
                                          debugCode,
                                          genCrt ? new CRTable(tree, env.toplevel.endPositions)
                                                 : null,
                                          syms,
                                          types,
-                                         poolWriter);
+                                         poolWriter,
+                                         allowPrimitiveClasses);
              items = new Items(poolWriter, code, syms, types);
              if (code.debugCode) {
                  System.err.println(meth + " for body " + tree);
              }
  
              // 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)
+                 if (meth.isInitOrVNew() && selfType != syms.objectType)
                      selfType = UninitializedType.uninitializedThis(selfType);
                  code.setDefined(
                          code.newLocal(
                              new VarSymbol(FINAL, names._this, selfType, meth.owner)));
              }

@@ -1092,10 +1117,14 @@
              }
          } else {
              code.newLocal(v);
          }
          checkDimension(tree.pos(), v.type);
+         Type localType = v.erasure(types);
+         if (localType.requiresPreload(env.enclClass.sym)) {
+             poolWriter.enterPreloadClass((ClassSymbol) localType.tsym);
+         }
      }
  
      public void visitSkip(JCSkip tree) {
      }
  

@@ -1140,10 +1169,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);

@@ -2055,11 +2115,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);
+                 code.emitAnewarray(makeRef(pos, elemtype, elemtype.isPrimitiveClass()), type);
              } else if (elemcode == 1) {
                  code.emitMultianewarray(ndims, makeRef(pos, type), type);
              } else {
                  code.emitNewarray(elemcode, type);
              }

@@ -2281,14 +2341,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) &&
-            types.asSuper(tree.expr.type, tree.clazz.type.tsym) == null) {
-             code.emitop2(checkcast, checkDimension(tree.pos(), tree.clazz.type), PoolWriter::putClass);
+             (!tree.clazz.type.isReferenceProjection() || !types.isSameType(tree.clazz.type.valueProjection(), tree.expr.type) || true) &&
+            !types.isSubtype(tree.expr.type, tree.clazz.type)) {
+             checkDimension(tree.pos(), tree.clazz.type);
+             if (tree.clazz.type.isPrimitiveClass()) {
+                 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());

@@ -2346,14 +2414,14 @@
  
      public void visitSelect(JCFieldAccess tree) {
          Symbol sym = tree.sym;
  
          if (tree.name == names._class) {
-             code.emitLdc((LoadableConstant)checkDimension(tree.pos(), tree.selected.type));
+             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 =

@@ -2405,10 +2473,22 @@
                  }
              }
          }
      }
  
+     public void visitDefaultValue(JCDefaultValue tree) {
+         if (tree.type.isValueClass()) {
+             code.emitop2(aconst_init, 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) {

@@ -2461,10 +2541,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 = transValues.translateTopLevelClass(cdef, make);
              generateReferencesToPrunedTree(c);
              Env<GenContext> localEnv = new Env<>(cdef, new GenContext());
              localEnv.toplevel = env.toplevel;
              localEnv.enclClass = cdef;
  
< prev index next >