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

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                 TreeInfo.mapSuperCalls(md.body, supercall -> make.Block(0, initCode.append(supercall).appendList(initBlocks)));
 562             } else {
 563                 TreeInfo.mapSuperCalls(md.body, supercall -> make.Block(0, initCode.prepend(supercall)));






















 564             }
 565 
 566             if (md.body.endpos == Position.NOPOS)
 567                 md.body.endpos = TreeInfo.endPos(md.body.stats.last());
 568 
 569             md.sym.appendUniqueTypeAttributes(initTAs);
 570         }
 571     }
 572 
 573 /* ************************************************************************
 574  * Traversal methods
 575  *************************************************************************/
 576 
 577     /** Visitor argument: The current environment.
 578      */
 579     Env<GenContext> env;
 580 
 581     /** Visitor argument: The expected type (prototype).
 582      */
 583     Type pt;
 584 
 585     /** Visitor result: The item representing the computed value.

1061             code.pendingStackMap = false;
1062 
1063             return startpcCrt;
1064         }
1065 
1066     public void visitVarDef(JCVariableDecl tree) {
1067         VarSymbol v = tree.sym;
1068         if (tree.init != null) {
1069             checkStringConstant(tree.init.pos(), v.getConstValue());
1070             if (v.getConstValue() == null || varDebugInfo) {
1071                 Assert.check(code.isStatementStart());
1072                 code.newLocal(v);
1073                 genExpr(tree.init, v.erasure(types)).load();
1074                 items.makeLocalItem(v).store();
1075                 Assert.check(code.isStatementStart());
1076             }
1077         } else {
1078             code.newLocal(v);
1079         }
1080         checkDimension(tree.pos(), v.type);
1081         Type localType = v.erasure(types);
1082         if (localType.requiresPreload(env.enclClass.sym)) {
1083             poolWriter.enterPreloadClass((ClassSymbol) localType.tsym);
1084         }
1085     }
1086 
1087     public void visitSkip(JCSkip tree) {
1088     }
1089 
1090     public void visitBlock(JCBlock tree) {
1091         if (tree.patternMatchingCatch != null) {
1092             Set<JCMethodInvocation> prevInvocationsWithPatternMatchingCatch = invocationsWithPatternMatchingCatch;
1093             ListBuffer<int[]> prevRanges = patternMatchingInvocationRanges;
1094             State startState = code.state.dup();
1095             try {
1096                 invocationsWithPatternMatchingCatch = tree.patternMatchingCatch.calls2Handle();
1097                 patternMatchingInvocationRanges = new ListBuffer<>();
1098                 doVisitBlock(tree);
1099             } finally {
1100                 Chain skipCatch = code.branch(goto_);
1101                 JCCatch handler = tree.patternMatchingCatch.handler();
1102                 code.entryPoint(startState, handler.param.sym.type);
1103                 genPatternMatchingCatch(handler, env, patternMatchingInvocationRanges.toList());
1104                 code.resolve(skipCatch);

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