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

Print this page




1414     /** Construct a tree simulating the expression <C.this>.
1415      *  @param pos           The source code position to be used for the tree.
1416      *  @param c             The qualifier class.
1417      */
1418     JCExpression makeThis(DiagnosticPosition pos, TypeSymbol c) {
1419         if (currentClass == c) {
1420             // in this case, `this' works fine
1421             return make.at(pos).This(c.erasure(types));
1422         } else {
1423             // need to go via this$n
1424             return makeOuterThis(pos, c);
1425         }
1426     }
1427 
1428     /** Optionally replace a try statement with an automatic resource
1429      *  management (ARM) block.
1430      * @param tree  The try statement to inspect.
1431      * @return      An ARM block, or the original try block if there are no
1432      *              resources to manage.
1433      */
1434     JCTree makeArmTry(JCTry tree) {
1435         make_at(tree.pos());
1436         twrVars = twrVars.dup();
1437         JCBlock armBlock = makeArmBlock(tree.resources, tree.body, 0);
1438         if (tree.catchers.isEmpty() && tree.finalizer == null)
1439             result = translate(armBlock);
1440         else
1441             result = translate(make.Try(armBlock, tree.catchers, tree.finalizer));
1442         twrVars = twrVars.leave();
1443         return result;
1444     }
1445 
1446     private JCBlock makeArmBlock(List<JCTree> resources, JCBlock block, int depth) {
1447         if (resources.isEmpty())
1448             return block;
1449 
1450         // Add resource declaration or expression to block statements
1451         ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
1452         JCTree resource = resources.head;
1453         JCExpression expr = null;
1454         if (resource instanceof JCVariableDecl) {
1455             JCVariableDecl var = (JCVariableDecl) resource;
1456             expr = make.Ident(var.sym).setType(resource.type);
1457             stats.add(var);
1458         } else {
1459             Assert.check(resource instanceof JCExpression);
1460             VarSymbol syntheticTwrVar =
1461             new VarSymbol(SYNTHETIC | FINAL,
1462                           makeSyntheticName(names.fromString("twrVar" +
1463                                            depth), twrVars),
1464                           (resource.type.tag == TypeTags.BOT) ?
1465                           syms.autoCloseableType : resource.type,
1466                           currentMethodSym);


1480                           currentMethodSym);
1481         twrVars.enter(primaryException);
1482         JCVariableDecl primaryExceptionTreeDecl = make.VarDef(primaryException, makeNull());
1483         stats.add(primaryExceptionTreeDecl);
1484 
1485         // Create catch clause that saves exception and then rethrows it
1486         VarSymbol param =
1487             new VarSymbol(FINAL|SYNTHETIC,
1488                           names.fromString("t" +
1489                                            target.syntheticNameChar()),
1490                           syms.throwableType,
1491                           currentMethodSym);
1492         JCVariableDecl paramTree = make.VarDef(param, null);
1493         JCStatement assign = make.Assignment(primaryException, make.Ident(param));
1494         JCStatement rethrowStat = make.Throw(make.Ident(param));
1495         JCBlock catchBlock = make.Block(0L, List.<JCStatement>of(assign, rethrowStat));
1496         JCCatch catchClause = make.Catch(paramTree, catchBlock);
1497 
1498         int oldPos = make.pos;
1499         make.at(TreeInfo.endPos(block));
1500         JCBlock finallyClause = makeArmFinallyClause(primaryException, expr);
1501         make.at(oldPos);
1502         JCTry outerTry = make.Try(makeArmBlock(resources.tail, block, depth + 1),
1503                                   List.<JCCatch>of(catchClause),
1504                                   finallyClause);
1505         stats.add(outerTry);
1506         return make.Block(0L, stats.toList());
1507     }
1508 
1509     private JCBlock makeArmFinallyClause(Symbol primaryException, JCExpression resource) {
1510         // primaryException.addSuppressed(catchException);
1511         VarSymbol catchException =
1512             new VarSymbol(0, make.paramName(2),
1513                           syms.throwableType,
1514                           currentMethodSym);
1515         JCStatement addSuppressionStatement =
1516             make.Exec(makeCall(make.Ident(primaryException),
1517                                names.addSuppressed,
1518                                List.<JCExpression>of(make.Ident(catchException))));
1519 
1520         // try { resource.close(); } catch (e) { primaryException.addSuppressed(e); }
1521         JCBlock tryBlock =
1522             make.Block(0L, List.<JCStatement>of(makeResourceCloseInvocation(resource)));
1523         JCVariableDecl catchExceptionDecl = make.VarDef(catchException, null);
1524         JCBlock catchBlock = make.Block(0L, List.<JCStatement>of(addSuppressionStatement));
1525         List<JCCatch> catchClauses = List.<JCCatch>of(make.Catch(catchExceptionDecl, catchBlock));
1526         JCTry tryTree = make.Try(tryBlock, catchClauses, null);
1527 
1528         // if (resource != null) resourceClose;
1529         JCExpression nullCheck = makeBinary(JCTree.NE,
1530                                             make.Ident(primaryException),
1531                                             makeNull());
1532         JCIf closeIfStatement = make.If(nullCheck,
1533                                         tryTree,
1534                                         makeResourceCloseInvocation(resource));
1535         return make.Block(0L, List.<JCStatement>of(closeIfStatement));





1536     }
1537 
1538     private JCStatement makeResourceCloseInvocation(JCExpression resource) {
1539         // create resource.close() method invocation
1540         JCExpression resourceClose = makeCall(resource, names.close, List.<JCExpression>nil());



1541         return make.Exec(resourceClose);






1542     }
1543 
1544     /** Construct a tree that represents the outer instance
1545      *  <C.this>. Never pick the current `this'.
1546      *  @param pos           The source code position to be used for the tree.
1547      *  @param c             The qualifier class.
1548      */
1549     JCExpression makeOuterThis(DiagnosticPosition pos, TypeSymbol c) {
1550         List<VarSymbol> ots = outerThisStack;
1551         if (ots.isEmpty()) {
1552             log.error(pos, "no.encl.instance.of.type.in.scope", c);
1553             Assert.error();
1554             return makeNull();
1555         }
1556         VarSymbol ot = ots.head;
1557         JCExpression tree = access(make.at(pos).Ident(ot));
1558         TypeSymbol otc = ot.type.tsym;
1559         while (otc != c) {
1560             do {
1561                 ots = ots.tail;


3556             result = access(tree.sym, tree, enclOp, qualifiedSuperAccess);
3557     }
3558 
3559     public void visitLetExpr(LetExpr tree) {
3560         tree.defs = translateVarDefs(tree.defs);
3561         tree.expr = translate(tree.expr, tree.type);
3562         result = tree;
3563     }
3564 
3565     // There ought to be nothing to rewrite here;
3566     // we don't generate code.
3567     public void visitAnnotation(JCAnnotation tree) {
3568         result = tree;
3569     }
3570 
3571     @Override
3572     public void visitTry(JCTry tree) {
3573         if (tree.resources.isEmpty()) {
3574             super.visitTry(tree);
3575         } else {
3576             result = makeArmTry(tree);
3577         }
3578     }
3579 
3580 /**************************************************************************
3581  * main method
3582  *************************************************************************/
3583 
3584     /** Translate a toplevel class and return a list consisting of
3585      *  the translated class and translated versions of all inner classes.
3586      *  @param env   The attribution environment current at the class definition.
3587      *               We need this for resolving some additional symbols.
3588      *  @param cdef  The tree representing the class definition.
3589      */
3590     public List<JCTree> translateTopLevelClass(Env<AttrContext> env, JCTree cdef, TreeMaker make) {
3591         ListBuffer<JCTree> translated = null;
3592         try {
3593             attrEnv = env;
3594             this.make = make;
3595             endPositions = env.toplevel.endPositions;
3596             currentClass = null;




1414     /** Construct a tree simulating the expression <C.this>.
1415      *  @param pos           The source code position to be used for the tree.
1416      *  @param c             The qualifier class.
1417      */
1418     JCExpression makeThis(DiagnosticPosition pos, TypeSymbol c) {
1419         if (currentClass == c) {
1420             // in this case, `this' works fine
1421             return make.at(pos).This(c.erasure(types));
1422         } else {
1423             // need to go via this$n
1424             return makeOuterThis(pos, c);
1425         }
1426     }
1427 
1428     /** Optionally replace a try statement with an automatic resource
1429      *  management (ARM) block.
1430      * @param tree  The try statement to inspect.
1431      * @return      An ARM block, or the original try block if there are no
1432      *              resources to manage.
1433      */
1434     JCTree makeTwrTry(JCTry tree) {
1435         make_at(tree.pos());
1436         twrVars = twrVars.dup();
1437         JCBlock armBlock = makeTwrBlock(tree.resources, tree.body, 0);
1438         if (tree.catchers.isEmpty() && tree.finalizer == null)
1439             result = translate(armBlock);
1440         else
1441             result = translate(make.Try(armBlock, tree.catchers, tree.finalizer));
1442         twrVars = twrVars.leave();
1443         return result;
1444     }
1445 
1446     private JCBlock makeTwrBlock(List<JCTree> resources, JCBlock block, int depth) {
1447         if (resources.isEmpty())
1448             return block;
1449 
1450         // Add resource declaration or expression to block statements
1451         ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
1452         JCTree resource = resources.head;
1453         JCExpression expr = null;
1454         if (resource instanceof JCVariableDecl) {
1455             JCVariableDecl var = (JCVariableDecl) resource;
1456             expr = make.Ident(var.sym).setType(resource.type);
1457             stats.add(var);
1458         } else {
1459             Assert.check(resource instanceof JCExpression);
1460             VarSymbol syntheticTwrVar =
1461             new VarSymbol(SYNTHETIC | FINAL,
1462                           makeSyntheticName(names.fromString("twrVar" +
1463                                            depth), twrVars),
1464                           (resource.type.tag == TypeTags.BOT) ?
1465                           syms.autoCloseableType : resource.type,
1466                           currentMethodSym);


1480                           currentMethodSym);
1481         twrVars.enter(primaryException);
1482         JCVariableDecl primaryExceptionTreeDecl = make.VarDef(primaryException, makeNull());
1483         stats.add(primaryExceptionTreeDecl);
1484 
1485         // Create catch clause that saves exception and then rethrows it
1486         VarSymbol param =
1487             new VarSymbol(FINAL|SYNTHETIC,
1488                           names.fromString("t" +
1489                                            target.syntheticNameChar()),
1490                           syms.throwableType,
1491                           currentMethodSym);
1492         JCVariableDecl paramTree = make.VarDef(param, null);
1493         JCStatement assign = make.Assignment(primaryException, make.Ident(param));
1494         JCStatement rethrowStat = make.Throw(make.Ident(param));
1495         JCBlock catchBlock = make.Block(0L, List.<JCStatement>of(assign, rethrowStat));
1496         JCCatch catchClause = make.Catch(paramTree, catchBlock);
1497 
1498         int oldPos = make.pos;
1499         make.at(TreeInfo.endPos(block));
1500         JCBlock finallyClause = makeTwrFinallyClause(primaryException, expr);
1501         make.at(oldPos);
1502         JCTry outerTry = make.Try(makeTwrBlock(resources.tail, block, depth + 1),
1503                                   List.<JCCatch>of(catchClause),
1504                                   finallyClause);
1505         stats.add(outerTry);
1506         return make.Block(0L, stats.toList());
1507     }
1508 
1509     private JCBlock makeTwrFinallyClause(Symbol primaryException, JCExpression resource) {
1510         // primaryException.addSuppressed(catchException);
1511         VarSymbol catchException =
1512             new VarSymbol(0, make.paramName(2),
1513                           syms.throwableType,
1514                           currentMethodSym);
1515         JCStatement addSuppressionStatement =
1516             make.Exec(makeCall(make.Ident(primaryException),
1517                                names.addSuppressed,
1518                                List.<JCExpression>of(make.Ident(catchException))));
1519 
1520         // try { resource.close(); } catch (e) { primaryException.addSuppressed(e); }
1521         JCBlock tryBlock =
1522             make.Block(0L, List.<JCStatement>of(makeResourceCloseInvocation(resource)));
1523         JCVariableDecl catchExceptionDecl = make.VarDef(catchException, null);
1524         JCBlock catchBlock = make.Block(0L, List.<JCStatement>of(addSuppressionStatement));
1525         List<JCCatch> catchClauses = List.<JCCatch>of(make.Catch(catchExceptionDecl, catchBlock));
1526         JCTry tryTree = make.Try(tryBlock, catchClauses, null);
1527 
1528         // if (primaryException != null) {try...} else resourceClose;
1529         JCIf closeIfStatement = make.If(makeNonNullCheck(make.Ident(primaryException)),



1530                                         tryTree,
1531                                         makeResourceCloseInvocation(resource));
1532 
1533         // if (#resource != null) { if (primaryException ...  }
1534         return make.Block(0L,
1535                           List.<JCStatement>of(make.If(makeNonNullCheck(resource),
1536                                                        closeIfStatement,
1537                                                        null)));
1538     }
1539 
1540     private JCStatement makeResourceCloseInvocation(JCExpression resource) {
1541         // create resource.close() method invocation protected by a null-check
1542 
1543         JCExpression resourceClose = makeCall(resource,
1544                                               names.close,
1545                                               List.<JCExpression>nil());
1546         return make.Exec(resourceClose);
1547 
1548         //return make.If(makeNonNullCheck(resource), make.Exec(resourceClose), null);
1549     }
1550 
1551     private JCExpression makeNonNullCheck(JCExpression expression) {
1552         return makeBinary(JCTree.NE, expression, makeNull());
1553     }
1554 
1555     /** Construct a tree that represents the outer instance
1556      *  <C.this>. Never pick the current `this'.
1557      *  @param pos           The source code position to be used for the tree.
1558      *  @param c             The qualifier class.
1559      */
1560     JCExpression makeOuterThis(DiagnosticPosition pos, TypeSymbol c) {
1561         List<VarSymbol> ots = outerThisStack;
1562         if (ots.isEmpty()) {
1563             log.error(pos, "no.encl.instance.of.type.in.scope", c);
1564             Assert.error();
1565             return makeNull();
1566         }
1567         VarSymbol ot = ots.head;
1568         JCExpression tree = access(make.at(pos).Ident(ot));
1569         TypeSymbol otc = ot.type.tsym;
1570         while (otc != c) {
1571             do {
1572                 ots = ots.tail;


3567             result = access(tree.sym, tree, enclOp, qualifiedSuperAccess);
3568     }
3569 
3570     public void visitLetExpr(LetExpr tree) {
3571         tree.defs = translateVarDefs(tree.defs);
3572         tree.expr = translate(tree.expr, tree.type);
3573         result = tree;
3574     }
3575 
3576     // There ought to be nothing to rewrite here;
3577     // we don't generate code.
3578     public void visitAnnotation(JCAnnotation tree) {
3579         result = tree;
3580     }
3581 
3582     @Override
3583     public void visitTry(JCTry tree) {
3584         if (tree.resources.isEmpty()) {
3585             super.visitTry(tree);
3586         } else {
3587             result = makeTwrTry(tree);
3588         }
3589     }
3590 
3591 /**************************************************************************
3592  * main method
3593  *************************************************************************/
3594 
3595     /** Translate a toplevel class and return a list consisting of
3596      *  the translated class and translated versions of all inner classes.
3597      *  @param env   The attribution environment current at the class definition.
3598      *               We need this for resolving some additional symbols.
3599      *  @param cdef  The tree representing the class definition.
3600      */
3601     public List<JCTree> translateTopLevelClass(Env<AttrContext> env, JCTree cdef, TreeMaker make) {
3602         ListBuffer<JCTree> translated = null;
3603         try {
3604             attrEnv = env;
3605             this.make = make;
3606             endPositions = env.toplevel.endPositions;
3607             currentClass = null;