< prev index next >

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

Print this page

 407     boolean hasFinally(JCTree target, Env<GenContext> env) {
 408         while (env.tree != target) {
 409             if (env.tree.hasTag(TRY) && env.info.finalize.hasFinalizer())
 410                 return true;
 411             env = env.next;
 412         }
 413         return false;
 414     }
 415 
 416 /* ************************************************************************
 417  * Normalizing class-members.
 418  *************************************************************************/
 419 
 420     /** Distribute member initializer code into constructors and {@code <clinit>}
 421      *  method.
 422      *  @param defs         The list of class member declarations.
 423      *  @param c            The enclosing class.
 424      */
 425     List<JCTree> normalizeDefs(List<JCTree> defs, ClassSymbol c) {
 426         ListBuffer<JCStatement> initCode = new ListBuffer<>();


 427         ListBuffer<Attribute.TypeCompound> initTAs = new ListBuffer<>();
 428         ListBuffer<JCStatement> clinitCode = new ListBuffer<>();
 429         ListBuffer<Attribute.TypeCompound> clinitTAs = new ListBuffer<>();
 430         ListBuffer<JCTree> methodDefs = new ListBuffer<>();
 431         // Sort definitions into three listbuffers:
 432         //  - initCode for instance initializers
 433         //  - clinitCode for class initializers
 434         //  - methodDefs for method definitions
 435         for (List<JCTree> l = defs; l.nonEmpty(); l = l.tail) {
 436             JCTree def = l.head;
 437             switch (def.getTag()) {
 438             case BLOCK:
 439                 JCBlock block = (JCBlock)def;
 440                 if ((block.flags & STATIC) != 0)
 441                     clinitCode.append(block);
 442                 else if ((block.flags & SYNTHETIC) == 0)
 443                     initCode.append(block);





 444                 break;
 445             case METHODDEF:
 446                 methodDefs.append(def);
 447                 break;
 448             case VARDEF:
 449                 JCVariableDecl vdef = (JCVariableDecl) def;
 450                 VarSymbol sym = vdef.sym;
 451                 checkDimension(vdef.pos(), sym.type);
 452                 if (vdef.init != null) {
 453                     if ((sym.flags() & STATIC) == 0) {
 454                         // Always initialize instance variables.
 455                         JCStatement init = make.at(vdef.pos()).
 456                             Assignment(sym, vdef.init);
 457                         initCode.append(init);
 458                         endPosTable.replaceTree(vdef, init);
 459                         initTAs.addAll(getAndRemoveNonFieldTAs(sym));
 460                     } else if (sym.getConstValue() == null) {
 461                         // Initialize class (static) variables only if
 462                         // they are not compile-time constants.
 463                         JCStatement init = make.at(vdef.pos).
 464                             Assignment(sym, vdef.init);
 465                         clinitCode.append(init);
 466                         endPosTable.replaceTree(vdef, init);
 467                         clinitTAs.addAll(getAndRemoveNonFieldTAs(sym));
 468                     } else {
 469                         checkStringConstant(vdef.init.pos(), sym.getConstValue());
 470                         /* if the init contains a reference to an external class, add it to the
 471                          * constant's pool
 472                          */
 473                         vdef.init.accept(classReferenceVisitor);
 474                     }
 475                 }
 476                 break;
 477             default:
 478                 Assert.error();
 479             }
 480         }
 481         // Insert any instance initializers into all constructors.
 482         if (initCode.length() != 0) {
 483             List<JCStatement> inits = initCode.toList();
 484             initTAs.addAll(c.getInitTypeAttributes());
 485             List<Attribute.TypeCompound> initTAlist = initTAs.toList();
 486             for (JCTree t : methodDefs) {
 487                 normalizeMethod((JCMethodDecl)t, inits, initTAlist);
 488             }
 489         }
 490         // If there are class initializers, create a <clinit> method
 491         // that contains them as its body.
 492         if (clinitCode.length() != 0) {
 493             MethodSymbol clinit = new MethodSymbol(
 494                 STATIC | (c.flags() & STRICTFP),
 495                 names.clinit,
 496                 new MethodType(
 497                     List.nil(), syms.voidType,
 498                     List.nil(), syms.methodClass),
 499                 c);
 500             c.members().enter(clinit);
 501             List<JCStatement> clinitStats = clinitCode.toList();
 502             JCBlock block = make.at(clinitStats.head.pos()).Block(0, clinitStats);
 503             block.endpos = TreeInfo.endPos(clinitStats.last());
 504             methodDefs.append(make.MethodDef(clinit, block));
 505 
 506             if (!clinitTAs.isEmpty())
 507                 clinit.appendUniqueTypeAttributes(clinitTAs.toList());

 524                 nonfieldTAs.add(ta);
 525             }
 526         }
 527         sym.setTypeAttributes(fieldTAs.toList());
 528         return nonfieldTAs.toList();
 529     }
 530 
 531     /** Check a constant value and report if it is a string that is
 532      *  too large.
 533      */
 534     private void checkStringConstant(DiagnosticPosition pos, Object constValue) {
 535         if (nerrs != 0 || // only complain about a long string once
 536             constValue == null ||
 537             !(constValue instanceof String str) ||
 538             str.length() < PoolWriter.MAX_STRING_LENGTH)
 539             return;
 540         log.error(pos, Errors.LimitString);
 541         nerrs++;
 542     }
 543 
 544     /** Insert instance initializer code into initial constructor.
 545      *  @param md        The tree potentially representing a
 546      *                   constructor's definition.
 547      *  @param initCode  The list of instance initializer statements.
 548      *  @param initTAs  Type annotations from the initializer expression.
 549      */
 550     void normalizeMethod(JCMethodDecl md, List<JCStatement> initCode, List<TypeCompound> initTAs) {
 551         if (md.name == names.init && TreeInfo.isInitialConstructor(md)) {
 552             // We are seeing a constructor that does not call another
 553             // constructor of the same class.
 554             List<JCStatement> stats = md.body.stats;
 555             ListBuffer<JCStatement> newstats = new ListBuffer<>();
 556 
 557             if (stats.nonEmpty()) {
 558                 // Copy initializers of synthetic variables generated in
 559                 // the translation of inner classes.
 560                 while (TreeInfo.isSyntheticInit(stats.head)) {
 561                     newstats.append(stats.head);
 562                     stats = stats.tail;
 563                 }
 564                 // Copy superclass constructor call
 565                 newstats.append(stats.head);
 566                 stats = stats.tail;
 567                 // Copy remaining synthetic initializers.
 568                 while (stats.nonEmpty() &&
 569                        TreeInfo.isSyntheticInit(stats.head)) {
 570                     newstats.append(stats.head);
 571                     stats = stats.tail;
 572                 }
 573                 // Now insert the initializer code.
 574                 newstats.appendList(initCode);
 575                 // And copy all remaining statements.
 576                 while (stats.nonEmpty()) {
 577                     newstats.append(stats.head);
 578                     stats = stats.tail;
 579                 }
 580             }
 581             md.body.stats = newstats.toList();
 582             if (md.body.endpos == Position.NOPOS)
 583                 md.body.endpos = TreeInfo.endPos(md.body.stats.last());
 584 
 585             md.sym.appendUniqueTypeAttributes(initTAs);
 586         }
 587     }
 588 


































 589 /* ************************************************************************
 590  * Traversal methods
 591  *************************************************************************/
 592 
 593     /** Visitor argument: The current environment.
 594      */
 595     Env<GenContext> env;
 596 
 597     /** Visitor argument: The expected type (prototype).
 598      */
 599     Type pt;
 600 
 601     /** Visitor result: The item representing the computed value.
 602      */
 603     Item result;
 604 
 605     /** Visitor method: generate code for a definition, catching and reporting
 606      *  any completion failures.
 607      *  @param tree    The definition to be visited.
 608      *  @param env     The environment current at the definition.

1077             code.pendingStackMap = false;
1078 
1079             return startpcCrt;
1080         }
1081 
1082     public void visitVarDef(JCVariableDecl tree) {
1083         VarSymbol v = tree.sym;
1084         if (tree.init != null) {
1085             checkStringConstant(tree.init.pos(), v.getConstValue());
1086             if (v.getConstValue() == null || varDebugInfo) {
1087                 Assert.check(code.isStatementStart());
1088                 code.newLocal(v);
1089                 genExpr(tree.init, v.erasure(types)).load();
1090                 items.makeLocalItem(v).store();
1091                 Assert.check(code.isStatementStart());
1092             }
1093         } else {
1094             code.newLocal(v);
1095         }
1096         checkDimension(tree.pos(), v.type);




1097     }
1098 
1099     public void visitSkip(JCSkip tree) {
1100     }
1101 
1102     public void visitBlock(JCBlock tree) {
1103         if (tree.patternMatchingCatch != null) {
1104             Set<JCMethodInvocation> prevInvocationsWithPatternMatchingCatch = invocationsWithPatternMatchingCatch;
1105             ListBuffer<int[]> prevRanges = patternMatchingInvocationRanges;
1106             State startState = code.state.dup();
1107             try {
1108                 invocationsWithPatternMatchingCatch = tree.patternMatchingCatch.calls2Handle();
1109                 patternMatchingInvocationRanges = new ListBuffer<>();
1110                 doVisitBlock(tree);
1111             } finally {
1112                 Chain skipCatch = code.branch(goto_);
1113                 JCCatch handler = tree.patternMatchingCatch.handler();
1114                 code.entryPoint(startState, handler.param.sym.type);
1115                 genPatternMatchingCatch(handler, env, patternMatchingInvocationRanges.toList());
1116                 code.resolve(skipCatch);

2344             items.makeThisItem().load();
2345             sym = binaryQualifier(sym, env.enclClass.type);
2346             result = items.makeMemberItem(sym, nonVirtualForPrivateAccess(sym));
2347         }
2348     }
2349 
2350     //where
2351     private boolean nonVirtualForPrivateAccess(Symbol sym) {
2352         boolean useVirtual = target.hasVirtualPrivateInvoke() &&
2353                              !disableVirtualizedPrivateInvoke;
2354         return !useVirtual && ((sym.flags() & PRIVATE) != 0);
2355     }
2356 
2357     public void visitSelect(JCFieldAccess tree) {
2358         Symbol sym = tree.sym;
2359 
2360         if (tree.name == names._class) {
2361             code.emitLdc((LoadableConstant)checkDimension(tree.pos(), tree.selected.type));
2362             result = items.makeStackItem(pt);
2363             return;
2364        }
2365 
2366         Symbol ssym = TreeInfo.symbol(tree.selected);
2367 
2368         // Are we selecting via super?
2369         boolean selectSuper =
2370             ssym != null && (ssym.kind == TYP || ssym.name == names._super);
2371 
2372         // Are we accessing a member of the superclass in an access method
2373         // resulting from a qualified super?
2374         boolean accessSuper = isAccessSuper(env.enclMethod);
2375 
2376         Item base = (selectSuper)
2377             ? items.makeSuperItem()
2378             : genExpr(tree.selected, tree.selected.type);
2379 
2380         if (sym.kind == VAR && ((VarSymbol) sym).getConstValue() != null) {
2381             // We are seeing a variable that is constant but its selecting
2382             // expression is not.
2383             if ((sym.flags() & STATIC) != 0) {
2384                 if (!selectSuper && (ssym == null || ssym.kind != TYP))

 407     boolean hasFinally(JCTree target, Env<GenContext> env) {
 408         while (env.tree != target) {
 409             if (env.tree.hasTag(TRY) && env.info.finalize.hasFinalizer())
 410                 return true;
 411             env = env.next;
 412         }
 413         return false;
 414     }
 415 
 416 /* ************************************************************************
 417  * Normalizing class-members.
 418  *************************************************************************/
 419 
 420     /** Distribute member initializer code into constructors and {@code <clinit>}
 421      *  method.
 422      *  @param defs         The list of class member declarations.
 423      *  @param c            The enclosing class.
 424      */
 425     List<JCTree> normalizeDefs(List<JCTree> defs, ClassSymbol c) {
 426         ListBuffer<JCStatement> initCode = new ListBuffer<>();
 427         // only used for value classes
 428         ListBuffer<JCStatement> initBlocks = new ListBuffer<>();
 429         ListBuffer<Attribute.TypeCompound> initTAs = new ListBuffer<>();
 430         ListBuffer<JCStatement> clinitCode = new ListBuffer<>();
 431         ListBuffer<Attribute.TypeCompound> clinitTAs = new ListBuffer<>();
 432         ListBuffer<JCTree> methodDefs = new ListBuffer<>();
 433         // Sort definitions into three listbuffers:
 434         //  - initCode for instance initializers
 435         //  - clinitCode for class initializers
 436         //  - methodDefs for method definitions
 437         for (List<JCTree> l = defs; l.nonEmpty(); l = l.tail) {
 438             JCTree def = l.head;
 439             switch (def.getTag()) {
 440             case BLOCK:
 441                 JCBlock block = (JCBlock)def;
 442                 if ((block.flags & STATIC) != 0)
 443                     clinitCode.append(block);
 444                 else if ((block.flags & SYNTHETIC) == 0) {
 445                     if (c.isValueClass()) {
 446                         initBlocks.append(block);
 447                     } else {
 448                         initCode.append(block);
 449                     }
 450                 }
 451                 break;
 452             case METHODDEF:
 453                 methodDefs.append(def);
 454                 break;
 455             case VARDEF:
 456                 JCVariableDecl vdef = (JCVariableDecl) def;
 457                 VarSymbol sym = vdef.sym;
 458                 checkDimension(vdef.pos(), sym.type);
 459                 if (vdef.init != null) {
 460                     if ((sym.flags() & STATIC) == 0) {
 461                         // Always initialize instance variables.
 462                         JCStatement init = make.at(vdef.pos()).
 463                             Assignment(sym, vdef.init);
 464                         initCode.append(init);
 465                         endPosTable.replaceTree(vdef, init);
 466                         initTAs.addAll(getAndRemoveNonFieldTAs(sym));
 467                     } else if (sym.getConstValue() == null) {
 468                         // Initialize class (static) variables only if
 469                         // they are not compile-time constants.
 470                         JCStatement init = make.at(vdef.pos).
 471                             Assignment(sym, vdef.init);
 472                         clinitCode.append(init);
 473                         endPosTable.replaceTree(vdef, init);
 474                         clinitTAs.addAll(getAndRemoveNonFieldTAs(sym));
 475                     } else {
 476                         checkStringConstant(vdef.init.pos(), sym.getConstValue());
 477                         /* if the init contains a reference to an external class, add it to the
 478                          * constant's pool
 479                          */
 480                         vdef.init.accept(classReferenceVisitor);
 481                     }
 482                 }
 483                 break;
 484             default:
 485                 Assert.error();
 486             }
 487         }
 488         // Insert any instance initializers into all constructors.
 489         if (initCode.length() != 0 || initBlocks.length() != 0) {

 490             initTAs.addAll(c.getInitTypeAttributes());
 491             List<Attribute.TypeCompound> initTAlist = initTAs.toList();
 492             for (JCTree t : methodDefs) {
 493                 normalizeMethod((JCMethodDecl)t, initCode.toList(), initBlocks.toList(), initTAlist);
 494             }
 495         }
 496         // If there are class initializers, create a <clinit> method
 497         // that contains them as its body.
 498         if (clinitCode.length() != 0) {
 499             MethodSymbol clinit = new MethodSymbol(
 500                 STATIC | (c.flags() & STRICTFP),
 501                 names.clinit,
 502                 new MethodType(
 503                     List.nil(), syms.voidType,
 504                     List.nil(), syms.methodClass),
 505                 c);
 506             c.members().enter(clinit);
 507             List<JCStatement> clinitStats = clinitCode.toList();
 508             JCBlock block = make.at(clinitStats.head.pos()).Block(0, clinitStats);
 509             block.endpos = TreeInfo.endPos(clinitStats.last());
 510             methodDefs.append(make.MethodDef(clinit, block));
 511 
 512             if (!clinitTAs.isEmpty())
 513                 clinit.appendUniqueTypeAttributes(clinitTAs.toList());

 530                 nonfieldTAs.add(ta);
 531             }
 532         }
 533         sym.setTypeAttributes(fieldTAs.toList());
 534         return nonfieldTAs.toList();
 535     }
 536 
 537     /** Check a constant value and report if it is a string that is
 538      *  too large.
 539      */
 540     private void checkStringConstant(DiagnosticPosition pos, Object constValue) {
 541         if (nerrs != 0 || // only complain about a long string once
 542             constValue == null ||
 543             !(constValue instanceof String str) ||
 544             str.length() < PoolWriter.MAX_STRING_LENGTH)
 545             return;
 546         log.error(pos, Errors.LimitString);
 547         nerrs++;
 548     }
 549 
 550     /** Insert instance initializer code into constructors prior to the super() call.
 551      *  @param md        The tree potentially representing a
 552      *                   constructor's definition.
 553      *  @param initCode  The list of instance initializer statements.
 554      *  @param initTAs  Type annotations from the initializer expression.
 555      */
 556     void normalizeMethod(JCMethodDecl md, List<JCStatement> initCode, List<JCStatement> initBlocks,  List<TypeCompound> initTAs) {
 557         if (TreeInfo.isConstructor(md) && TreeInfo.hasConstructorCall(md, names._super)) {
 558             // We are seeing a constructor that has a super() call.
 559             // Find the super() invocation and append the given initializer code.
 560             if (md.sym.owner.isValueClass()) {
 561                 rewriteInitializersIfNeeded(md, initCode);
 562                 TreeInfo.mapSuperCalls(md.body, supercall -> make.Block(0, initCode.append(supercall).appendList(initBlocks)));
 563             } else {
 564                 TreeInfo.mapSuperCalls(md.body, supercall -> make.Block(0, initCode.prepend(supercall)));





















 565             }
 566 
 567             if (md.body.endpos == Position.NOPOS)
 568                 md.body.endpos = TreeInfo.endPos(md.body.stats.last());
 569 
 570             md.sym.appendUniqueTypeAttributes(initTAs);
 571         }
 572     }
 573 
 574     void rewriteInitializersIfNeeded(JCMethodDecl md, List<JCStatement> initCode) {
 575         if (lower.initializerOuterThis.containsKey(md.sym.owner)) {
 576             InitializerVisitor initializerVisitor = new InitializerVisitor(md, lower.initializerOuterThis.get(md.sym.owner));
 577             for (JCStatement init : initCode) {
 578                 initializerVisitor.scan(init);
 579             }
 580         }
 581     }
 582 
 583     class InitializerVisitor extends TreeScanner {
 584         JCMethodDecl md;
 585         Set<JCExpression> exprSet;
 586 
 587         InitializerVisitor(JCMethodDecl md, Set<JCExpression> exprSet) {
 588             this.md = md;
 589             this.exprSet = exprSet;
 590         }
 591 
 592         @Override
 593         public void visitTree(JCTree tree) {}
 594 
 595         @Override
 596         public void visitIdent(JCIdent tree) {
 597             if (exprSet.contains(tree)) {
 598                 for (JCVariableDecl param: md.params) {
 599                     if (param.name == tree.name &&
 600                             ((param.sym.flags_field & (MANDATED | NOOUTERTHIS)) == (MANDATED | NOOUTERTHIS))) {
 601                         tree.sym = param.sym;
 602                     }
 603                 }
 604             }
 605         }
 606     }
 607 
 608 /* ************************************************************************
 609  * Traversal methods
 610  *************************************************************************/
 611 
 612     /** Visitor argument: The current environment.
 613      */
 614     Env<GenContext> env;
 615 
 616     /** Visitor argument: The expected type (prototype).
 617      */
 618     Type pt;
 619 
 620     /** Visitor result: The item representing the computed value.
 621      */
 622     Item result;
 623 
 624     /** Visitor method: generate code for a definition, catching and reporting
 625      *  any completion failures.
 626      *  @param tree    The definition to be visited.
 627      *  @param env     The environment current at the definition.

1096             code.pendingStackMap = false;
1097 
1098             return startpcCrt;
1099         }
1100 
1101     public void visitVarDef(JCVariableDecl tree) {
1102         VarSymbol v = tree.sym;
1103         if (tree.init != null) {
1104             checkStringConstant(tree.init.pos(), v.getConstValue());
1105             if (v.getConstValue() == null || varDebugInfo) {
1106                 Assert.check(code.isStatementStart());
1107                 code.newLocal(v);
1108                 genExpr(tree.init, v.erasure(types)).load();
1109                 items.makeLocalItem(v).store();
1110                 Assert.check(code.isStatementStart());
1111             }
1112         } else {
1113             code.newLocal(v);
1114         }
1115         checkDimension(tree.pos(), v.type);
1116         Type localType = v.erasure(types);
1117         if (localType.requiresPreload(env.enclClass.sym)) {
1118             poolWriter.enterPreloadClass((ClassSymbol) localType.tsym);
1119         }
1120     }
1121 
1122     public void visitSkip(JCSkip tree) {
1123     }
1124 
1125     public void visitBlock(JCBlock tree) {
1126         if (tree.patternMatchingCatch != null) {
1127             Set<JCMethodInvocation> prevInvocationsWithPatternMatchingCatch = invocationsWithPatternMatchingCatch;
1128             ListBuffer<int[]> prevRanges = patternMatchingInvocationRanges;
1129             State startState = code.state.dup();
1130             try {
1131                 invocationsWithPatternMatchingCatch = tree.patternMatchingCatch.calls2Handle();
1132                 patternMatchingInvocationRanges = new ListBuffer<>();
1133                 doVisitBlock(tree);
1134             } finally {
1135                 Chain skipCatch = code.branch(goto_);
1136                 JCCatch handler = tree.patternMatchingCatch.handler();
1137                 code.entryPoint(startState, handler.param.sym.type);
1138                 genPatternMatchingCatch(handler, env, patternMatchingInvocationRanges.toList());
1139                 code.resolve(skipCatch);

2367             items.makeThisItem().load();
2368             sym = binaryQualifier(sym, env.enclClass.type);
2369             result = items.makeMemberItem(sym, nonVirtualForPrivateAccess(sym));
2370         }
2371     }
2372 
2373     //where
2374     private boolean nonVirtualForPrivateAccess(Symbol sym) {
2375         boolean useVirtual = target.hasVirtualPrivateInvoke() &&
2376                              !disableVirtualizedPrivateInvoke;
2377         return !useVirtual && ((sym.flags() & PRIVATE) != 0);
2378     }
2379 
2380     public void visitSelect(JCFieldAccess tree) {
2381         Symbol sym = tree.sym;
2382 
2383         if (tree.name == names._class) {
2384             code.emitLdc((LoadableConstant)checkDimension(tree.pos(), tree.selected.type));
2385             result = items.makeStackItem(pt);
2386             return;
2387         }
2388 
2389         Symbol ssym = TreeInfo.symbol(tree.selected);
2390 
2391         // Are we selecting via super?
2392         boolean selectSuper =
2393             ssym != null && (ssym.kind == TYP || ssym.name == names._super);
2394 
2395         // Are we accessing a member of the superclass in an access method
2396         // resulting from a qualified super?
2397         boolean accessSuper = isAccessSuper(env.enclMethod);
2398 
2399         Item base = (selectSuper)
2400             ? items.makeSuperItem()
2401             : genExpr(tree.selected, tree.selected.type);
2402 
2403         if (sym.kind == VAR && ((VarSymbol) sym).getConstValue() != null) {
2404             // We are seeing a variable that is constant but its selecting
2405             // expression is not.
2406             if ((sym.flags() & STATIC) != 0) {
2407                 if (!selectSuper && (ssym == null || ssym.kind != TYP))
< prev index next >