< 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.

*** 112,10 ***
--- 114,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");

*** 129,10 ***
--- 132,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");
      }
  
      /** Switches
       */
      private final boolean lineDebugInfo;

*** 172,10 ***
--- 177,12 ---
      List<LocalItem> stackBeforeSwitchExpression;
      LocalItem switchResult;
      Set<JCMethodInvocation> invocationsWithPatternMatchingCatch = Set.of();
      ListBuffer<int[]> patternMatchingInvocationRanges;
  
+     boolean allowPrimitiveClasses;
+ 
      /** Generate code to load an integer constant.
       *  @param n     The integer to be loaded.
       */
      void loadIntConst(int n) {
          items.makeImmediateItem(syms.intType, n).load();

*** 215,17 ***
          } else {
              code.emitop0(iconst_m1);
          }
      }
  
      /** 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) {
--- 222,31 ---
          } else {
              code.emitop0(iconst_m1);
          }
      }
  
+     /** 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) {

*** 275,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();
      }
  
      /** Is the given method definition an access method
       *  resulting from a qualified super? This is signified by an odd
       *  access code.
--- 296,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, 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.

*** 498,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)) {
              // 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<>();
  
--- 519,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 (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<>();
  

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

*** 941,10 ***
--- 962,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_);

*** 995,21 ***
                                          debugCode,
                                          genCrt ? new CRTable(tree, env.toplevel.endPositions)
                                                 : null,
                                          syms,
                                          types,
!                                         poolWriter);
              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)
                      selfType = UninitializedType.uninitializedThis(selfType);
                  code.setDefined(
                          code.newLocal(
                              new VarSymbol(FINAL, names._this, selfType, meth.owner)));
              }
--- 1019,22 ---
                                          debugCode,
                                          genCrt ? new CRTable(tree, env.toplevel.endPositions)
                                                 : null,
                                          syms,
                                          types,
!                                         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.isInitOrVNew() && selfType != syms.objectType)
                      selfType = UninitializedType.uninitializedThis(selfType);
                  code.setDefined(
                          code.newLocal(
                              new VarSymbol(FINAL, names._this, selfType, meth.owner)));
              }

*** 1044,10 ***
--- 1069,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) {
      }
  

*** 1092,10 ***
--- 1121,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 = types.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 = types.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);

*** 2007,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);
              }
--- 2067,11 ---
                  log.error(pos, Errors.LimitDimensions);
                  nerrs++;
              }
              int elemcode = Code.arraycode(elemtype);
              if (elemcode == 0 || (elemcode == 1 && ndims == 1)) {
!                 code.emitAnewarray(makeRef(pos, elemtype, elemtype.isPrimitiveClass()), type);
              } else if (elemcode == 1) {
                  code.emitMultianewarray(ndims, makeRef(pos, type), type);
              } else {
                  code.emitNewarray(elemcode, type);
              }

*** 2233,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());
--- 2293,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.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());

*** 2298,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 =
--- 2366,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 =

*** 2357,10 ***
--- 2425,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) {

*** 2413,10 ***
--- 2493,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 >