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

Print this page




 588 
 589         // Append class definition tree to owner's definitions.
 590         odef.defs = odef.defs.prepend(cdef);
 591 
 592         return c;
 593     }
 594 
 595 /**************************************************************************
 596  * Symbol manipulation utilities
 597  *************************************************************************/
 598 
 599     /** Enter a synthetic symbol in a given scope, but complain if there was already one there.
 600      *  @param pos           Position for error reporting.
 601      *  @param sym           The symbol.
 602      *  @param s             The scope.
 603      */
 604     private void enterSynthetic(DiagnosticPosition pos, Symbol sym, Scope s) {
 605         s.enter(sym);
 606     }
 607 

















 608     /** Check whether synthetic symbols generated during lowering conflict
 609      *  with user-defined symbols.
 610      *
 611      *  @param translatedTrees lowered class trees
 612      */
 613     void checkConflicts(List<JCTree> translatedTrees) {
 614         for (JCTree t : translatedTrees) {
 615             t.accept(conflictsChecker);
 616         }
 617     }
 618 
 619     JCTree.Visitor conflictsChecker = new TreeScanner() {
 620 
 621         TypeSymbol currentClass;
 622 
 623         @Override
 624         public void visitMethodDef(JCMethodDecl that) {
 625             chk.checkConflicts(that.pos(), that.sym, currentClass);
 626             super.visitMethodDef(that);
 627         }


1282                 make.Call(
1283                     make.App(
1284                         callee,
1285                         make.Idents(md.params.reverse().tail.reverse())))));
1286         return md;
1287     }
1288 
1289 /**************************************************************************
1290  * Free variables proxies and this$n
1291  *************************************************************************/
1292 
1293     /** A scope containing all free variable proxies for currently translated
1294      *  class, as well as its this$n symbol (if needed).
1295      *  Proxy scopes are nested in the same way classes are.
1296      *  Inside a constructor, proxies and any this$n symbol are duplicated
1297      *  in an additional innermost scope, where they represent the constructor
1298      *  parameters.
1299      */
1300     Scope proxies;
1301 





1302     /** A stack containing the this$n field of the currently translated
1303      *  classes (if needed) in innermost first order.
1304      *  Inside a constructor, proxies and any this$n symbol are duplicated
1305      *  in an additional innermost scope, where they represent the constructor
1306      *  parameters.
1307      */
1308     List<VarSymbol> outerThisStack;
1309 
1310     /** The name of a free variable proxy.
1311      */
1312     Name proxyName(Name name) {
1313         return names.fromString("val" + target.syntheticNameChar() + name);
1314     }
1315 
1316     /** Proxy definitions for all free variables in given list, in reverse order.
1317      *  @param pos        The source code position of the definition.
1318      *  @param freevars   The free variables.
1319      *  @param owner      The class in which the definitions go.
1320      */
1321     List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars, Symbol owner) {


1383     }
1384 //where
1385         JCExpression loadFreevar(DiagnosticPosition pos, VarSymbol v) {
1386             return access(v, make.at(pos).Ident(v), null, false);
1387         }
1388 
1389     /** Construct a tree simulating the expression <C.this>.
1390      *  @param pos           The source code position to be used for the tree.
1391      *  @param c             The qualifier class.
1392      */
1393     JCExpression makeThis(DiagnosticPosition pos, TypeSymbol c) {
1394         if (currentClass == c) {
1395             // in this case, `this' works fine
1396             return make.at(pos).This(c.erasure(types));
1397         } else {
1398             // need to go via this$n
1399             return makeOuterThis(pos, c);
1400         }
1401     }
1402 




















































































































1403     /** Construct a tree that represents the outer instance
1404      *  <C.this>. Never pick the current `this'.
1405      *  @param pos           The source code position to be used for the tree.
1406      *  @param c             The qualifier class.
1407      */
1408     JCExpression makeOuterThis(DiagnosticPosition pos, TypeSymbol c) {
1409         List<VarSymbol> ots = outerThisStack;
1410         if (ots.isEmpty()) {
1411             log.error(pos, "no.encl.instance.of.type.in.scope", c);
1412             assert false;
1413             return makeNull();
1414         }
1415         VarSymbol ot = ots.head;
1416         JCExpression tree = access(make.at(pos).Ident(ot));
1417         TypeSymbol otc = ot.type.tsym;
1418         while (otc != c) {
1419             do {
1420                 ots = ots.tail;
1421                 if (ots.isEmpty()) {
1422                     log.error(pos,


3388         if (tree.name == names._class)
3389             result = classOf(tree.selected);
3390         else if (tree.name == names._this || tree.name == names._super)
3391             result = makeThis(tree.pos(), tree.selected.type.tsym);
3392         else
3393             result = access(tree.sym, tree, enclOp, qualifiedSuperAccess);
3394     }
3395 
3396     public void visitLetExpr(LetExpr tree) {
3397         tree.defs = translateVarDefs(tree.defs);
3398         tree.expr = translate(tree.expr, tree.type);
3399         result = tree;
3400     }
3401 
3402     // There ought to be nothing to rewrite here;
3403     // we don't generate code.
3404     public void visitAnnotation(JCAnnotation tree) {
3405         result = tree;
3406     }
3407 









3408 /**************************************************************************
3409  * main method
3410  *************************************************************************/
3411 
3412     /** Translate a toplevel class and return a list consisting of
3413      *  the translated class and translated versions of all inner classes.
3414      *  @param env   The attribution environment current at the class definition.
3415      *               We need this for resolving some additional symbols.
3416      *  @param cdef  The tree representing the class definition.
3417      */
3418     public List<JCTree> translateTopLevelClass(Env<AttrContext> env, JCTree cdef, TreeMaker make) {
3419         ListBuffer<JCTree> translated = null;
3420         try {
3421             attrEnv = env;
3422             this.make = make;
3423             endPositions = env.toplevel.endPositions;
3424             currentClass = null;
3425             currentMethodDef = null;
3426             outermostClassDef = (cdef.getTag() == JCTree.CLASSDEF) ? (JCClassDecl)cdef : null;
3427             outermostMemberDef = null;
3428             this.translated = new ListBuffer<JCTree>();
3429             classdefs = new HashMap<ClassSymbol,JCClassDecl>();
3430             actualSymbols = new HashMap<Symbol,Symbol>();
3431             freevarCache = new HashMap<ClassSymbol,List<VarSymbol>>();
3432             proxies = new Scope(syms.noSymbol);

3433             outerThisStack = List.nil();
3434             accessNums = new HashMap<Symbol,Integer>();
3435             accessSyms = new HashMap<Symbol,MethodSymbol[]>();
3436             accessConstrs = new HashMap<Symbol,MethodSymbol>();
3437             accessConstrTags = List.nil();
3438             accessed = new ListBuffer<Symbol>();
3439             translate(cdef, (JCExpression)null);
3440             for (List<Symbol> l = accessed.toList(); l.nonEmpty(); l = l.tail)
3441                 makeAccessible(l.head);
3442             for (EnumMapping map : enumSwitchMap.values())
3443                 map.translate();
3444             checkConflicts(this.translated.toList());
3445             checkAccessConstructorTags();
3446             translated = this.translated;
3447         } finally {
3448             // note that recursive invocations of this method fail hard
3449             attrEnv = null;
3450             this.make = null;
3451             endPositions = null;
3452             currentClass = null;




 588 
 589         // Append class definition tree to owner's definitions.
 590         odef.defs = odef.defs.prepend(cdef);
 591 
 592         return c;
 593     }
 594 
 595 /**************************************************************************
 596  * Symbol manipulation utilities
 597  *************************************************************************/
 598 
 599     /** Enter a synthetic symbol in a given scope, but complain if there was already one there.
 600      *  @param pos           Position for error reporting.
 601      *  @param sym           The symbol.
 602      *  @param s             The scope.
 603      */
 604     private void enterSynthetic(DiagnosticPosition pos, Symbol sym, Scope s) {
 605         s.enter(sym);
 606     }
 607 
 608     /** Create a fresh synthetic name within a given scope - the unique name is
 609      *  obtained by appending '$' chars at the end of the name until no match
 610      *  is found.
 611      *
 612      * @param name base name
 613      * @param s scope in which the name has to be unique
 614      * @return fresh synthetic name
 615      */
 616     private Name makeSyntheticName(Name name, Scope s) {
 617         do {
 618             name = name.append(
 619                     target.syntheticNameChar(),
 620                     names.empty);
 621         } while (lookupSynthetic(name, s) != null);
 622         return name;
 623     }
 624 
 625     /** Check whether synthetic symbols generated during lowering conflict
 626      *  with user-defined symbols.
 627      *
 628      *  @param translatedTrees lowered class trees
 629      */
 630     void checkConflicts(List<JCTree> translatedTrees) {
 631         for (JCTree t : translatedTrees) {
 632             t.accept(conflictsChecker);
 633         }
 634     }
 635 
 636     JCTree.Visitor conflictsChecker = new TreeScanner() {
 637 
 638         TypeSymbol currentClass;
 639 
 640         @Override
 641         public void visitMethodDef(JCMethodDecl that) {
 642             chk.checkConflicts(that.pos(), that.sym, currentClass);
 643             super.visitMethodDef(that);
 644         }


1299                 make.Call(
1300                     make.App(
1301                         callee,
1302                         make.Idents(md.params.reverse().tail.reverse())))));
1303         return md;
1304     }
1305 
1306 /**************************************************************************
1307  * Free variables proxies and this$n
1308  *************************************************************************/
1309 
1310     /** A scope containing all free variable proxies for currently translated
1311      *  class, as well as its this$n symbol (if needed).
1312      *  Proxy scopes are nested in the same way classes are.
1313      *  Inside a constructor, proxies and any this$n symbol are duplicated
1314      *  in an additional innermost scope, where they represent the constructor
1315      *  parameters.
1316      */
1317     Scope proxies;
1318 
1319     /** A scope containing all unnamed resource variables/saved exception variables
1320      *  for translated ARM blocks
1321      */
1322     Scope armVars;
1323 
1324     /** A stack containing the this$n field of the currently translated
1325      *  classes (if needed) in innermost first order.
1326      *  Inside a constructor, proxies and any this$n symbol are duplicated
1327      *  in an additional innermost scope, where they represent the constructor
1328      *  parameters.
1329      */
1330     List<VarSymbol> outerThisStack;
1331 
1332     /** The name of a free variable proxy.
1333      */
1334     Name proxyName(Name name) {
1335         return names.fromString("val" + target.syntheticNameChar() + name);
1336     }
1337 
1338     /** Proxy definitions for all free variables in given list, in reverse order.
1339      *  @param pos        The source code position of the definition.
1340      *  @param freevars   The free variables.
1341      *  @param owner      The class in which the definitions go.
1342      */
1343     List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars, Symbol owner) {


1405     }
1406 //where
1407         JCExpression loadFreevar(DiagnosticPosition pos, VarSymbol v) {
1408             return access(v, make.at(pos).Ident(v), null, false);
1409         }
1410 
1411     /** Construct a tree simulating the expression <C.this>.
1412      *  @param pos           The source code position to be used for the tree.
1413      *  @param c             The qualifier class.
1414      */
1415     JCExpression makeThis(DiagnosticPosition pos, TypeSymbol c) {
1416         if (currentClass == c) {
1417             // in this case, `this' works fine
1418             return make.at(pos).This(c.erasure(types));
1419         } else {
1420             // need to go via this$n
1421             return makeOuterThis(pos, c);
1422         }
1423     }
1424 
1425     /** Optionally replace a try statement with an automatic resource management
1426      *  (ARM) block.
1427      * @param tree  The try statement to inspect.
1428      * @return      An ARM block, or the original try block if there are no
1429      *              resources to manage.
1430      */
1431     JCTree makeArmTry(JCTry tree) {
1432         make_at(tree.pos());
1433         armVars = armVars.dup();
1434         JCBlock armBlock = makeArmBlock(tree.resources, tree.body, 0);        
1435         if (tree.catchers.isEmpty() && tree.finalizer == null)
1436             result = translate(armBlock);
1437         else
1438             result = translate(make.Try(armBlock, tree.catchers, tree.finalizer));
1439         armVars = armVars.leave();
1440         return result;
1441     }
1442 
1443     private JCBlock makeArmBlock(List<JCTree> resources, JCBlock block, int depth) {
1444         if (resources.isEmpty())
1445             return block;
1446 
1447         // Add resource declaration or expression to block statements
1448         ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
1449         JCTree resource = resources.head;
1450         JCExpression expr = null;
1451         if (resource instanceof JCVariableDecl) {
1452             JCVariableDecl var = (JCVariableDecl) resource;
1453             expr = make.Ident(var.sym).setType(resource.type);
1454             stats.add(var);
1455         } else {
1456             assert resource instanceof JCExpression;
1457             VarSymbol syntheticArmVar =
1458             new VarSymbol(SYNTHETIC | FINAL,
1459                           makeSyntheticName(names.fromString("armVar" +
1460                                            depth), armVars),
1461                           (resource.type.tag == TypeTags.BOT) ?
1462                           syms.autoCloseableType : resource.type,
1463                           currentMethodSym);
1464             armVars.enter(syntheticArmVar);
1465             JCVariableDecl syntheticArmVarDecl =
1466                 make.VarDef(syntheticArmVar, (JCExpression)resource);
1467             expr = (JCExpression)make.Ident(syntheticArmVar);
1468             stats.add(syntheticArmVarDecl);
1469         }
1470 
1471         // Add primaryException declaration
1472         VarSymbol primaryException =
1473             new VarSymbol(SYNTHETIC,
1474                           makeSyntheticName(names.fromString("primaryException" +
1475                           depth), armVars),
1476                           syms.throwableType,
1477                           currentMethodSym);
1478         armVars.enter(primaryException);
1479         JCVariableDecl primaryExceptionTreeDecl = make.VarDef(primaryException, makeNull());
1480         stats.add(primaryExceptionTreeDecl);
1481 
1482         // Create catch clause that saves exception and then rethrows it
1483         VarSymbol param =
1484             new VarSymbol(FINAL|SYNTHETIC,
1485                           names.fromString("t" +                                           
1486                                            target.syntheticNameChar()),
1487                           syms.throwableType,
1488                           currentMethodSym);
1489         JCVariableDecl paramTree = make.VarDef(param, null);
1490         JCStatement assign = make.Assignment(primaryException, make.Ident(param));
1491         JCStatement rethrowStat = make.Throw(make.Ident(param));
1492         JCBlock catchBlock = make.Block(0L, List.<JCStatement>of(assign, rethrowStat));
1493         JCCatch catchClause = make.Catch(paramTree, catchBlock);
1494 
1495         int oldPos = make.pos;
1496         make.at(TreeInfo.endPos(block));
1497         JCBlock finallyClause = makeArmFinallyClause(primaryException, expr);
1498         make.at(oldPos);
1499         JCTry outerTry = make.Try(makeArmBlock(resources.tail, block, depth + 1),
1500                                   List.<JCCatch>of(catchClause),
1501                                   finallyClause);
1502         stats.add(outerTry);
1503         return make.Block(0L, stats.toList());
1504     }
1505    
1506     private JCBlock makeArmFinallyClause(Symbol primaryException, JCExpression resource) {
1507         // primaryException.addSuppressedException(catchException);
1508         VarSymbol catchException =
1509             new VarSymbol(0, make.paramName(2),
1510                           syms.throwableType,
1511                           currentMethodSym);
1512         JCStatement addSuppressionStatement =
1513             make.Exec(makeCall(make.Ident(primaryException),
1514                                names.fromString("addSuppressedException"),
1515                                List.<JCExpression>of(make.Ident(catchException))));
1516 
1517         // try { resource.close(); } catch (e) { primaryException.addSuppressedException(e); }
1518         JCBlock tryBlock =
1519             make.Block(0L, List.<JCStatement>of(makeResourceCloseInvocation(resource)));
1520         JCVariableDecl catchExceptionDecl = make.VarDef(catchException, null);
1521         JCBlock catchBlock = make.Block(0L, List.<JCStatement>of(addSuppressionStatement));
1522         List<JCCatch> catchClauses = List.<JCCatch>of(make.Catch(catchExceptionDecl, catchBlock));
1523         JCTry tryTree = make.Try(tryBlock, catchClauses, null);
1524 
1525         // if (resource != null) resourceClose;
1526         JCExpression nullCheck = makeBinary(JCTree.NE,
1527                                             make.Ident(primaryException),
1528                                             makeNull());
1529         JCIf closeIfStatement = make.If(nullCheck,
1530                                         tryTree,
1531                                         makeResourceCloseInvocation(resource));
1532         return make.Block(0L, List.<JCStatement>of(closeIfStatement));
1533     }
1534 
1535     private JCStatement makeResourceCloseInvocation(JCExpression resource) {
1536         // create resource.close() method invocation
1537         JCExpression resourceClose = makeCall(resource, names.close, List.<JCExpression>nil());
1538         return make.Exec(resourceClose);
1539     }
1540 
1541     /** Construct a tree that represents the outer instance
1542      *  <C.this>. Never pick the current `this'.
1543      *  @param pos           The source code position to be used for the tree.
1544      *  @param c             The qualifier class.
1545      */
1546     JCExpression makeOuterThis(DiagnosticPosition pos, TypeSymbol c) {
1547         List<VarSymbol> ots = outerThisStack;
1548         if (ots.isEmpty()) {
1549             log.error(pos, "no.encl.instance.of.type.in.scope", c);
1550             assert false;
1551             return makeNull();
1552         }
1553         VarSymbol ot = ots.head;
1554         JCExpression tree = access(make.at(pos).Ident(ot));
1555         TypeSymbol otc = ot.type.tsym;
1556         while (otc != c) {
1557             do {
1558                 ots = ots.tail;
1559                 if (ots.isEmpty()) {
1560                     log.error(pos,


3526         if (tree.name == names._class)
3527             result = classOf(tree.selected);
3528         else if (tree.name == names._this || tree.name == names._super)
3529             result = makeThis(tree.pos(), tree.selected.type.tsym);
3530         else
3531             result = access(tree.sym, tree, enclOp, qualifiedSuperAccess);
3532     }
3533 
3534     public void visitLetExpr(LetExpr tree) {
3535         tree.defs = translateVarDefs(tree.defs);
3536         tree.expr = translate(tree.expr, tree.type);
3537         result = tree;
3538     }
3539 
3540     // There ought to be nothing to rewrite here;
3541     // we don't generate code.
3542     public void visitAnnotation(JCAnnotation tree) {
3543         result = tree;
3544     }
3545 
3546     @Override
3547     public void visitTry(JCTry tree) {
3548         if (tree.resources.isEmpty()) {
3549             super.visitTry(tree);
3550         } else {
3551             result = makeArmTry(tree);
3552         }
3553     }
3554 
3555 /**************************************************************************
3556  * main method
3557  *************************************************************************/
3558 
3559     /** Translate a toplevel class and return a list consisting of
3560      *  the translated class and translated versions of all inner classes.
3561      *  @param env   The attribution environment current at the class definition.
3562      *               We need this for resolving some additional symbols.
3563      *  @param cdef  The tree representing the class definition.
3564      */
3565     public List<JCTree> translateTopLevelClass(Env<AttrContext> env, JCTree cdef, TreeMaker make) {
3566         ListBuffer<JCTree> translated = null;
3567         try {
3568             attrEnv = env;
3569             this.make = make;
3570             endPositions = env.toplevel.endPositions;
3571             currentClass = null;
3572             currentMethodDef = null;
3573             outermostClassDef = (cdef.getTag() == JCTree.CLASSDEF) ? (JCClassDecl)cdef : null;
3574             outermostMemberDef = null;
3575             this.translated = new ListBuffer<JCTree>();
3576             classdefs = new HashMap<ClassSymbol,JCClassDecl>();
3577             actualSymbols = new HashMap<Symbol,Symbol>();
3578             freevarCache = new HashMap<ClassSymbol,List<VarSymbol>>();
3579             proxies = new Scope(syms.noSymbol);
3580             armVars = new Scope(syms.noSymbol);
3581             outerThisStack = List.nil();
3582             accessNums = new HashMap<Symbol,Integer>();
3583             accessSyms = new HashMap<Symbol,MethodSymbol[]>();
3584             accessConstrs = new HashMap<Symbol,MethodSymbol>();
3585             accessConstrTags = List.nil();
3586             accessed = new ListBuffer<Symbol>();
3587             translate(cdef, (JCExpression)null);
3588             for (List<Symbol> l = accessed.toList(); l.nonEmpty(); l = l.tail)
3589                 makeAccessible(l.head);
3590             for (EnumMapping map : enumSwitchMap.values())
3591                 map.translate();
3592             checkConflicts(this.translated.toList());
3593             checkAccessConstructorTags();
3594             translated = this.translated;
3595         } finally {
3596             // note that recursive invocations of this method fail hard
3597             attrEnv = null;
3598             this.make = null;
3599             endPositions = null;
3600             currentClass = null;