< prev index next >

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

Print this page
*** 422,10 ***
--- 422,12 ---
       *  @param defs         The list of class member declarations.
       *  @param c            The enclosing class.
       */
      List<JCTree> normalizeDefs(List<JCTree> defs, ClassSymbol c) {
          ListBuffer<JCStatement> initCode = new ListBuffer<>();
+         // only used for value classes
+         ListBuffer<JCStatement> initBlocks = new ListBuffer<>();
          ListBuffer<Attribute.TypeCompound> initTAs = new ListBuffer<>();
          ListBuffer<JCStatement> clinitCode = new ListBuffer<>();
          ListBuffer<Attribute.TypeCompound> clinitTAs = new ListBuffer<>();
          ListBuffer<JCTree> methodDefs = new ListBuffer<>();
          // Sort definitions into three listbuffers:

*** 437,12 ***
              switch (def.getTag()) {
              case BLOCK:
                  JCBlock block = (JCBlock)def;
                  if ((block.flags & STATIC) != 0)
                      clinitCode.append(block);
!                 else if ((block.flags & SYNTHETIC) == 0)
!                     initCode.append(block);
                  break;
              case METHODDEF:
                  methodDefs.append(def);
                  break;
              case VARDEF:
--- 439,17 ---
              switch (def.getTag()) {
              case BLOCK:
                  JCBlock block = (JCBlock)def;
                  if ((block.flags & STATIC) != 0)
                      clinitCode.append(block);
!                 else if ((block.flags & SYNTHETIC) == 0) {
!                     if (c.isValueClass()) {
+                         initBlocks.append(block);
+                     } else {
+                         initCode.append(block);
+                     }
+                 }
                  break;
              case METHODDEF:
                  methodDefs.append(def);
                  break;
              case VARDEF:

*** 477,16 ***
              default:
                  Assert.error();
              }
          }
          // Insert any instance initializers into all constructors.
!         if (initCode.length() != 0) {
-             List<JCStatement> inits = initCode.toList();
              initTAs.addAll(c.getInitTypeAttributes());
              List<Attribute.TypeCompound> initTAlist = initTAs.toList();
              for (JCTree t : methodDefs) {
!                 normalizeMethod((JCMethodDecl)t, inits, initTAlist);
              }
          }
          // If there are class initializers, create a <clinit> method
          // that contains them as its body.
          if (clinitCode.length() != 0) {
--- 484,15 ---
              default:
                  Assert.error();
              }
          }
          // Insert any instance initializers into all constructors.
!         if (initCode.length() != 0 || initBlocks.length() != 0) {
              initTAs.addAll(c.getInitTypeAttributes());
              List<Attribute.TypeCompound> initTAlist = initTAs.toList();
              for (JCTree t : methodDefs) {
!                 normalizeMethod((JCMethodDecl)t, initCode.toList(), initBlocks.toList(), initTAlist);
              }
          }
          // If there are class initializers, create a <clinit> method
          // that contains them as its body.
          if (clinitCode.length() != 0) {

*** 545,23 ***
       *  @param md        The tree potentially representing a
       *                   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 (TreeInfo.isConstructor(md) && TreeInfo.hasConstructorCall(md, names._super)) {
              // We are seeing a constructor that has a super() call.
              // Find the super() invocation and append the given initializer code.
!             TreeInfo.mapSuperCalls(md.body, supercall -> make.Block(0, initCode.prepend(supercall)));
  
              if (md.body.endpos == Position.NOPOS)
                  md.body.endpos = TreeInfo.endPos(md.body.stats.last());
  
              md.sym.appendUniqueTypeAttributes(initTAs);
          }
      }
  
  /* ************************************************************************
   * Traversal methods
   *************************************************************************/
  
      /** Visitor argument: The current environment.
--- 551,62 ---
       *  @param md        The tree potentially representing a
       *                   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<JCStatement> initBlocks,  List<TypeCompound> initTAs) {
          if (TreeInfo.isConstructor(md) && TreeInfo.hasConstructorCall(md, names._super)) {
              // We are seeing a constructor that has a super() call.
              // Find the super() invocation and append the given initializer code.
!             if (md.sym.owner.isValueClass()) {
+                 rewriteInitializersIfNeeded(md, initCode);
+                 TreeInfo.mapSuperCalls(md.body, supercall -> make.Block(0, initCode.append(supercall).appendList(initBlocks)));
+             } else {
+                 TreeInfo.mapSuperCalls(md.body, supercall -> make.Block(0, initCode.prepend(supercall)));
+             }
  
              if (md.body.endpos == Position.NOPOS)
                  md.body.endpos = TreeInfo.endPos(md.body.stats.last());
  
              md.sym.appendUniqueTypeAttributes(initTAs);
          }
      }
  
+     void rewriteInitializersIfNeeded(JCMethodDecl md, List<JCStatement> initCode) {
+         if (lower.initializerOuterThis.containsKey(md.sym.owner)) {
+             InitializerVisitor initializerVisitor = new InitializerVisitor(md, lower.initializerOuterThis.get(md.sym.owner));
+             for (JCStatement init : initCode) {
+                 initializerVisitor.scan(init);
+             }
+         }
+     }
+ 
+     class InitializerVisitor extends TreeScanner {
+         JCMethodDecl md;
+         Set<JCExpression> exprSet;
+ 
+         InitializerVisitor(JCMethodDecl md, Set<JCExpression> exprSet) {
+             this.md = md;
+             this.exprSet = exprSet;
+         }
+ 
+         @Override
+         public void visitTree(JCTree tree) {}
+ 
+         @Override
+         public void visitIdent(JCIdent tree) {
+             if (exprSet.contains(tree)) {
+                 for (JCVariableDecl param: md.params) {
+                     if (param.name == tree.name &&
+                             ((param.sym.flags_field & (MANDATED | NOOUTERTHIS)) == (MANDATED | NOOUTERTHIS))) {
+                         tree.sym = param.sym;
+                     }
+                 }
+             }
+         }
+     }
+ 
  /* ************************************************************************
   * Traversal methods
   *************************************************************************/
  
      /** Visitor argument: The current environment.

*** 2371,11 ***
  
          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 =
--- 2416,11 ---
  
          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 =
< prev index next >