< 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());

 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 constructors prior to the super() call.
 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 (TreeInfo.isConstructor(md) && TreeInfo.hasConstructorCall(md, names._super)) {
 552             // We are seeing a constructor that has a super() call.
 553             // Find the super() invocation and append the given initializer code.
 554             TreeInfo.mapSuperCalls(md.body, supercall -> make.Block(0, initCode.prepend(supercall)));





 555 
 556             if (md.body.endpos == Position.NOPOS)
 557                 md.body.endpos = TreeInfo.endPos(md.body.stats.last());
 558 
 559             md.sym.appendUniqueTypeAttributes(initTAs);
 560         }
 561     }
 562 


































 563 /* ************************************************************************
 564  * Traversal methods
 565  *************************************************************************/
 566 
 567     /** Visitor argument: The current environment.
 568      */
 569     Env<GenContext> env;
 570 
 571     /** Visitor argument: The expected type (prototype).
 572      */
 573     Type pt;
 574 
 575     /** Visitor result: The item representing the computed value.
 576      */
 577     Item result;
 578 
 579     /** Visitor method: generate code for a definition, catching and reporting
 580      *  any completion failures.
 581      *  @param tree    The definition to be visited.
 582      *  @param env     The environment current at the definition.

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

 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.

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