< prev index next >

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java

Print this page
@@ -868,10 +868,13 @@
          if (enclOp == null)
              return AccessCode.DEREF.code;
          else if (enclOp.hasTag(ASSIGN) &&
                   tree == TreeInfo.skipParens(((JCAssign) enclOp).lhs))
              return AccessCode.ASSIGN.code;
+         else if (enclOp.hasTag(WITHFIELD) &&
+                 tree == TreeInfo.skipParens(((JCWithField) enclOp).field))
+             return AccessCode.WITHFIELD.code;
          else if ((enclOp.getTag().isIncOrDecUnaryOp() || enclOp.getTag().isAssignop()) &&
                  tree == TreeInfo.skipParens(((JCOperatorExpression) enclOp).getOperand(LEFT)))
              return (((JCOperatorExpression) enclOp).operator).getAccessCode(enclOp.getTag());
          else
              return AccessCode.DEREF.code;

@@ -978,15 +981,15 @@
                  OperatorSymbol operator = binaryAccessOperator(acode, enclOp.getTag());
                  if (operator.opcode == string_add)
                      argtypes = List.of(syms.objectType);
                  else
                      argtypes = operator.type.getParameterTypes().tail;
-             } else if (acode == AccessCode.ASSIGN.code)
+             } else if (acode == AccessCode.ASSIGN.code || acode == AccessCode.WITHFIELD.code)
                  argtypes = List.of(vsym.erasure(types));
              else
                  argtypes = List.nil();
-             restype = vsym.erasure(types);
+             restype = acode == AccessCode.WITHFIELD.code ? vsym.owner.erasure(types) : vsym.erasure(types);
              thrown = List.nil();
              break;
          case MTH:
              acode = AccessCode.DEREF.code;
              argtypes = vsym.erasure(types).getParameterTypes();

@@ -1128,10 +1131,15 @@
          }
          JCExpression base = (tree.hasTag(SELECT)) ? ((JCFieldAccess) tree).selected : null;
          switch (sym.kind) {
          case TYP:
              if (sym.owner.kind != PCK) {
+                 // Make sure not to lose type fidelity due to symbol sharing between projections
+                 boolean requireReferenceProjection =
+                         tree.hasTag(SELECT) && ((JCFieldAccess) tree).name == names.ref && tree.type.isReferenceProjection();
+                 boolean requireValueProjection =
+                         tree.hasTag(SELECT) && ((JCFieldAccess) tree).name == names.val && tree.type.isValueProjection();
                  // Convert type idents to
                  // <flat name> or <package name> . <flat name>
                  Name flatname = Convert.shortName(sym.flatName());
                  while (base != null &&
                         TreeInfo.symbol(base) != null &&

@@ -1143,13 +1151,23 @@
                  if (tree.hasTag(IDENT)) {
                      ((JCIdent) tree).name = flatname;
                  } else if (base == null) {
                      tree = make.at(tree.pos).Ident(sym);
                      ((JCIdent) tree).name = flatname;
+                     if (requireReferenceProjection) {
+                         tree.setType(tree.type.referenceProjection());
+                     } else if (requireValueProjection) {
+                         tree.setType(tree.type.asValueType());
+                     }
                  } else {
                      ((JCFieldAccess) tree).selected = base;
                      ((JCFieldAccess) tree).name = flatname;
+                     if (requireReferenceProjection) {
+                         tree.setType(tree.type.referenceProjection());
+                     } else if (requireValueProjection) {
+                         tree.setType(tree.type.asValueType());
+                     }
                  }
              }
              break;
          case MTH: case VAR:
              if (sym.owner.kind == TYP) {

@@ -1351,16 +1369,19 @@
                  expr = make.Assign(ref, args.head);
                  break;
              case PREINC: case POSTINC: case PREDEC: case POSTDEC:
                  expr = makeUnary(aCode.tag, ref);
                  break;
+             case WITHFIELD:
+                 expr = make.WithField(ref, args.head);
+                 break;
              default:
                  expr = make.Assignop(
                      treeTag(binaryAccessOperator(acode1, JCTree.Tag.NO_TAG)), ref, args.head);
                  ((JCAssignOp) expr).operator = binaryAccessOperator(acode1, JCTree.Tag.NO_TAG);
              }
-             stat = make.Return(expr.setType(sym.type));
+             stat = make.Return(expr.setType(aCode == AccessCode.WITHFIELD ? sym.owner.type : sym.type));
          } else {
              stat = make.Call(make.App(ref, args));
          }
          md.body = make.Block(0, List.of(stat));
  

@@ -1450,12 +1471,13 @@
              int index = 0;
              Name proxyName;
              do {
                  proxyName = proxyName(v.name, index++);
              } while (!proxyNames.add(proxyName));
+             final Type type = v.erasure(types);
              VarSymbol proxy = new VarSymbol(
-                 flags, proxyName, v.erasure(types), owner);
+                 flags, proxyName, type, owner);
              proxies.put(v, proxy);
              JCVariableDecl vd = make.at(pos).VarDef(proxy, null);
              vd.vartype = access(vd.vartype);
              defs = defs.prepend(vd);
          }

@@ -1514,11 +1536,13 @@
      /** Definition for this$n field.
       *  @param pos        The source code position of the definition.
       *  @param owner      The class in which the definition goes.
       */
      JCVariableDecl outerThisDef(int pos, ClassSymbol owner) {
-         VarSymbol outerThis = makeOuterThisVarSymbol(owner, FINAL | SYNTHETIC);
+         Type target = types.erasure(owner.enclClass().type.getEnclosingType());
+         long flags = FINAL | SYNTHETIC;
+         VarSymbol outerThis = makeOuterThisVarSymbol(owner, flags);
          return makeOuterThisVarDecl(pos, outerThis);
      }
  
      /** Return a list of trees that load the free variables in given list,
       *  in reverse order.

@@ -1697,11 +1721,11 @@
          return newBlock;
      }
  
      private JCStatement makeResourceCloseInvocation(JCExpression resource) {
          // convert to AutoCloseable if needed
-         if (types.asSuper(resource.type, syms.autoCloseableType.tsym) == null) {
+         if (types.asSuper(resource.type.referenceProjectionOrSelf(), syms.autoCloseableType.tsym) == null) {
              resource = convert(resource, syms.autoCloseableType);
          }
  
          // create resource.close() method invocation
          JCExpression resourceClose = makeCall(resource,

@@ -2078,11 +2102,12 @@
      }
  
      /** Visitor method: Translate a single node, boxing or unboxing if needed.
       */
      public <T extends JCExpression> T translate(T tree, Type type) {
-         return (tree == null) ? null : boxIfNeeded(translate(tree), type);
+         return (tree == null) ? null :
+                 applyPrimitiveConversionsAsNeeded(boxIfNeeded(translate(tree), type), type);
      }
  
      /** Visitor method: Translate tree.
       */
      public <T extends JCTree> T translate(T tree, JCExpression enclOp) {

@@ -2499,11 +2524,12 @@
                      List.of(syms.methodHandleLookupType,
                              syms.stringType,
                              syms.typeDescriptorType).appendList(staticArgTypes),
                      staticArgsValues, bootstrapName, name, false);
  
-             VarSymbol _this = new VarSymbol(SYNTHETIC, names._this, tree.sym.type, tree.sym);
+             Type receiverType = tree.sym.type.isPrimitiveReferenceType() ? tree.sym.type.asValueType() : tree.sym.type;
+             VarSymbol _this = new VarSymbol(SYNTHETIC, names._this, receiverType, tree.sym);
  
              JCMethodInvocation proxyCall;
              if (!isEquals) {
                  proxyCall = make.Apply(List.nil(), qualifier, List.of(make.Ident(_this)));
              } else {

@@ -2583,12 +2609,13 @@
              boolean isStatic) {
          Symbol bsm = rs.resolveInternalMethod(tree.pos(), attrEnv, site,
                  bootstrapName, staticArgTypes, List.nil());
  
          MethodType indyType = msym.type.asMethodType();
+         Type receiverType = tree.sym.type.isPrimitiveReferenceType() ? tree.sym.type.asValueType() : tree.sym.type;
          indyType = new MethodType(
-                 isStatic ? List.nil() : indyType.argtypes.prepend(tree.sym.type),
+                 isStatic ? List.nil() : indyType.argtypes.prepend(receiverType),
                  indyType.restype,
                  indyType.thrown,
                  syms.methodClass
          );
          DynamicMethodSymbol dynSym = new DynamicMethodSymbol(argName,

@@ -2829,11 +2856,16 @@
              tree.clazz = access(make_at(tree.clazz.pos()).Ident(tree.def.sym));
              tree.def = null;
          } else {
              tree.clazz = access(c, tree.clazz, enclOp, false);
          }
-         result = tree;
+         if (tree.clazz.type.tsym == syms.objectType.tsym) {
+             Assert.check(tree.def == null && tree.encl == null);
+             result = makeCall(make.Ident(syms.objectsType.tsym), names.newIdentity, List.nil());
+         } else {
+             result = tree;
+         }
      }
  
      // Simplify conditionals with known constant controlling expressions.
      // This allows us to avoid generating supporting declarations for
      // the dead code, which will not be eliminated during code generation.

@@ -3075,10 +3107,24 @@
              if (!anyChanges) return _args;
          }
          return result.toList();
      }
  
+     /** Apply primitive value/reference conversions as needed */
+     @SuppressWarnings("unchecked")
+     <T extends JCExpression> T applyPrimitiveConversionsAsNeeded(T tree, Type type) {
+         boolean haveValue = tree.type.isPrimitiveClass();
+         if (haveValue == type.isPrimitiveClass())
+             return tree;
+         // For narrowing conversion, insert a cast which should trigger a null check
+         // For widening conversions, insert a cast if emitting a unified class file.
+         return (T) make.TypeCast(type, tree);
+ 
+     }
+ 
+ 
+ 
      /** Expand a boxing or unboxing conversion if needed. */
      @SuppressWarnings("unchecked") // XXX unchecked
      <T extends JCExpression> T boxIfNeeded(T tree, Type type) {
          boolean havePrimitive = tree.type.isPrimitive();
          if (havePrimitive == type.isPrimitive())

@@ -3473,11 +3519,11 @@
           * where #i is a freshly named synthetic local variable.
           */
          private void visitIterableForeachLoop(JCEnhancedForLoop tree) {
              make_at(tree.expr.pos());
              Type iteratorTarget = syms.objectType;
-             Type iterableType = types.asSuper(types.cvarUpperBound(tree.expr.type),
+             Type iterableType = types.asSuper(types.cvarUpperBound(tree.expr.type.referenceProjectionOrSelf()),
                                                syms.iterableType.tsym);
              if (iterableType.getTypeArguments().nonEmpty())
                  iteratorTarget = types.erasure(iterableType.getTypeArguments().head);
              Type eType = types.skipTypeVars(tree.expr.type, false);
              tree.expr.type = types.erasure(eType);

@@ -3486,11 +3532,11 @@
              Symbol iterator = lookupMethod(tree.expr.pos(),
                                             names.iterator,
                                             eType,
                                             List.nil());
              VarSymbol itvar = new VarSymbol(SYNTHETIC, names.fromString("i" + target.syntheticNameChar()),
-                                             types.erasure(types.asSuper(iterator.type.getReturnType(), syms.iteratorType.tsym)),
+                                             types.erasure(types.asSuper(iterator.type.getReturnType().referenceProjectionOrSelf(), syms.iteratorType.tsym)),
                                              currentMethodSym);
  
               JCStatement init = make.
                  VarDef(itvar, make.App(make.Select(tree.expr, iterator)
                       .setType(types.erasure(iterator.type))));

@@ -3563,10 +3609,27 @@
          tree.cond = translate(tree.cond, syms.booleanType);
          tree.body = translate(tree.body);
          result = tree;
      }
  
+     public void visitWithField(JCWithField tree) {
+         Type fieldType = tree.field.type;
+         tree.field = translate(tree.field, tree);
+         tree.value = translate(tree.value, fieldType); // important to use pre-translation type.
+ 
+         // If translated field is an Apply, we are
+         // seeing an access method invocation. In this case, append
+         // right hand side as last argument of the access method.
+         if (tree.field.hasTag(APPLY)) {
+             JCMethodInvocation app = (JCMethodInvocation) tree.field;
+             app.args = List.of(tree.value).prependList(app.args);
+             result = app;
+         } else {
+             result = tree;
+         }
+     }
+ 
      public void visitForLoop(JCForLoop tree) {
          tree.init = translate(tree.init);
          if (tree.cond != null)
              tree.cond = translate(tree.cond, syms.booleanType);
          tree.step = translate(tree.step);

@@ -4041,19 +4104,27 @@
          // is a default interface subclassed by the current class.
          boolean qualifiedSuperAccess =
              tree.selected.hasTag(SELECT) &&
              TreeInfo.name(tree.selected) == names._super &&
              !types.isDirectSuperInterface(((JCFieldAccess)tree.selected).selected.type.tsym, currentClass);
+         /* JDK-8269956: Where a reflective (class) literal is needed, the unqualified Point.class is
+          * always the "primary" mirror - representing the primitive reference runtime type - thereby
+          * always matching the behavior of Object::getClass
+          */
+         boolean needPrimaryMirror = tree.name == names._class && tree.selected.type.isPrimitiveReferenceType();
          tree.selected = translate(tree.selected);
+         if (needPrimaryMirror && tree.selected.type.isPrimitiveClass()) {
+             tree.selected.setType(tree.selected.type.referenceProjection());
+         }
          if (tree.name == names._class) {
              result = classOf(tree.selected);
          }
          else if (tree.name == names._super &&
                  types.isDirectSuperInterface(tree.selected.type.tsym, currentClass)) {
              //default super call!! Not a classic qualified super call
              TypeSymbol supSym = tree.selected.type.tsym;
-             Assert.checkNonNull(types.asSuper(currentClass.type, supSym));
+             Assert.checkNonNull(types.asSuper(currentClass.type.referenceProjectionOrSelf(), supSym));
              result = tree;
          }
          else if (tree.name == names._this || tree.name == names._super) {
              result = makeThis(tree.pos(), tree.selected.type.tsym);
          }
< prev index next >