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         }
 622         while (lookupSynthetic(name, s) != null);
 623         return name;
 624     }
 625 
 626     /** Check whether synthetic symbols generated during lowering conflict
 627      *  with user-defined symbols.
 628      *
 629      *  @param translatedTrees lowered class trees
 630      */
 631     void checkConflicts(List<JCTree> translatedTrees) {
 632         for (JCTree t : translatedTrees) {
 633             t.accept(conflictsChecker);
 634         }
 635     }
 636 
 637     JCTree.Visitor conflictsChecker = new TreeScanner() {
 638 
 639         TypeSymbol currentClass;
 640 
 641         @Override
 642         public void visitMethodDef(JCMethodDecl that) {
 643             chk.checkConflicts(that.pos(), that.sym, currentClass);
 644             super.visitMethodDef(that);
 645         }


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


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


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