118 options.isUnset(G_CUSTOM) |
118 options.isUnset(G_CUSTOM) |
119 ? options.isSet(G) |
119 ? options.isSet(G) |
120 : options.isSet(G_CUSTOM, "vars"); |
120 : options.isSet(G_CUSTOM, "vars"); |
121 genCrt = options.isSet(XJCOV); |
121 genCrt = options.isSet(XJCOV); |
122 debugCode = options.isSet("debugcode"); |
122 debugCode = options.isSet("debugcode"); |
123 allowInvokedynamic = target.hasInvokedynamic() || options.isSet("invokedynamic"); |
|
124 allowBetterNullChecks = target.hasObjects(); |
123 allowBetterNullChecks = target.hasObjects(); |
125 pool = new Pool(types); |
124 pool = new Pool(types); |
126 |
125 |
127 // ignore cldc because we cannot have both stackmap formats |
126 // ignore cldc because we cannot have both stackmap formats |
128 this.stackMap = StackMapFormat.JSR202; |
127 this.stackMap = StackMapFormat.JSR202; |
129 |
|
130 // by default, avoid jsr's for simple finalizers |
|
131 int setjsrlimit = 50; |
|
132 String jsrlimitString = options.get("jsrlimit"); |
|
133 if (jsrlimitString != null) { |
|
134 try { |
|
135 setjsrlimit = Integer.parseInt(jsrlimitString); |
|
136 } catch (NumberFormatException ex) { |
|
137 // ignore ill-formed numbers for jsrlimit |
|
138 } |
|
139 } |
|
140 this.jsrlimit = setjsrlimit; |
|
141 this.useJsrLocally = false; // reset in visitTry |
|
142 annotate = Annotate.instance(context); |
128 annotate = Annotate.instance(context); |
143 } |
129 } |
144 |
130 |
145 /** Switches |
131 /** Switches |
146 */ |
132 */ |
147 private final boolean lineDebugInfo; |
133 private final boolean lineDebugInfo; |
148 private final boolean varDebugInfo; |
134 private final boolean varDebugInfo; |
149 private final boolean genCrt; |
135 private final boolean genCrt; |
150 private final boolean debugCode; |
136 private final boolean debugCode; |
151 private final boolean allowInvokedynamic; |
|
152 private final boolean allowBetterNullChecks; |
137 private final boolean allowBetterNullChecks; |
153 |
|
154 /** Default limit of (approximate) size of finalizer to inline. |
|
155 * Zero means always use jsr. 100 or greater means never use |
|
156 * jsr. |
|
157 */ |
|
158 private final int jsrlimit; |
|
159 |
|
160 /** True if jsr is used. |
|
161 */ |
|
162 private boolean useJsrLocally; |
|
163 |
138 |
164 /** Code buffer, set by genMethod. |
139 /** Code buffer, set by genMethod. |
165 */ |
140 */ |
166 private Code code; |
141 private Code code; |
167 |
142 |
1337 public void visitTry(final JCTry tree) { |
1312 public void visitTry(final JCTry tree) { |
1338 // Generate code for a try statement with given body and catch clauses, |
1313 // Generate code for a try statement with given body and catch clauses, |
1339 // in a new environment which calls the finally block if there is one. |
1314 // in a new environment which calls the finally block if there is one. |
1340 final Env<GenContext> tryEnv = env.dup(tree, new GenContext()); |
1315 final Env<GenContext> tryEnv = env.dup(tree, new GenContext()); |
1341 final Env<GenContext> oldEnv = env; |
1316 final Env<GenContext> oldEnv = env; |
1342 if (!useJsrLocally) { |
|
1343 useJsrLocally = |
|
1344 (stackMap == StackMapFormat.NONE) && |
|
1345 (jsrlimit <= 0 || |
|
1346 jsrlimit < 100 && |
|
1347 estimateCodeComplexity(tree.finalizer)>jsrlimit); |
|
1348 } |
|
1349 tryEnv.info.finalize = new GenFinalizer() { |
1317 tryEnv.info.finalize = new GenFinalizer() { |
1350 void gen() { |
1318 void gen() { |
1351 if (useJsrLocally) { |
1319 Assert.check(tryEnv.info.gaps.length() % 2 == 0); |
1352 if (tree.finalizer != null) { |
1320 tryEnv.info.gaps.append(code.curCP()); |
1353 Code.State jsrState = code.state.dup(); |
1321 genLast(); |
1354 jsrState.push(Code.jsrReturnValue); |
|
1355 tryEnv.info.cont = |
|
1356 new Chain(code.emitJump(jsr), |
|
1357 tryEnv.info.cont, |
|
1358 jsrState); |
|
1359 } |
|
1360 Assert.check(tryEnv.info.gaps.length() % 2 == 0); |
|
1361 tryEnv.info.gaps.append(code.curCP()); |
|
1362 } else { |
|
1363 Assert.check(tryEnv.info.gaps.length() % 2 == 0); |
|
1364 tryEnv.info.gaps.append(code.curCP()); |
|
1365 genLast(); |
|
1366 } |
|
1367 } |
1322 } |
1368 void genLast() { |
1323 void genLast() { |
1369 if (tree.finalizer != null) |
1324 if (tree.finalizer != null) |
1370 genStat(tree.finalizer, oldEnv, CRT_BLOCK); |
1325 genStat(tree.finalizer, oldEnv, CRT_BLOCK); |
1371 } |
1326 } |
1565 } else { |
1520 } else { |
1566 log.error(pos, "limit.code.too.large.for.try.stmt"); |
1521 log.error(pos, "limit.code.too.large.for.try.stmt"); |
1567 nerrs++; |
1522 nerrs++; |
1568 } |
1523 } |
1569 } |
1524 } |
1570 |
|
1571 /** Very roughly estimate the number of instructions needed for |
|
1572 * the given tree. |
|
1573 */ |
|
1574 int estimateCodeComplexity(JCTree tree) { |
|
1575 if (tree == null) return 0; |
|
1576 class ComplexityScanner extends TreeScanner { |
|
1577 int complexity = 0; |
|
1578 public void scan(JCTree tree) { |
|
1579 if (complexity > jsrlimit) return; |
|
1580 super.scan(tree); |
|
1581 } |
|
1582 public void visitClassDef(JCClassDecl tree) {} |
|
1583 public void visitDoLoop(JCDoWhileLoop tree) |
|
1584 { super.visitDoLoop(tree); complexity++; } |
|
1585 public void visitWhileLoop(JCWhileLoop tree) |
|
1586 { super.visitWhileLoop(tree); complexity++; } |
|
1587 public void visitForLoop(JCForLoop tree) |
|
1588 { super.visitForLoop(tree); complexity++; } |
|
1589 public void visitSwitch(JCSwitch tree) |
|
1590 { super.visitSwitch(tree); complexity+=5; } |
|
1591 public void visitCase(JCCase tree) |
|
1592 { super.visitCase(tree); complexity++; } |
|
1593 public void visitSynchronized(JCSynchronized tree) |
|
1594 { super.visitSynchronized(tree); complexity+=6; } |
|
1595 public void visitTry(JCTry tree) |
|
1596 { super.visitTry(tree); |
|
1597 if (tree.finalizer != null) complexity+=6; } |
|
1598 public void visitCatch(JCCatch tree) |
|
1599 { super.visitCatch(tree); complexity+=2; } |
|
1600 public void visitConditional(JCConditional tree) |
|
1601 { super.visitConditional(tree); complexity+=2; } |
|
1602 public void visitIf(JCIf tree) |
|
1603 { super.visitIf(tree); complexity+=2; } |
|
1604 // note: for break, continue, and return we don't take unwind() into account. |
|
1605 public void visitBreak(JCBreak tree) |
|
1606 { super.visitBreak(tree); complexity+=1; } |
|
1607 public void visitContinue(JCContinue tree) |
|
1608 { super.visitContinue(tree); complexity+=1; } |
|
1609 public void visitReturn(JCReturn tree) |
|
1610 { super.visitReturn(tree); complexity+=1; } |
|
1611 public void visitThrow(JCThrow tree) |
|
1612 { super.visitThrow(tree); complexity+=1; } |
|
1613 public void visitAssert(JCAssert tree) |
|
1614 { super.visitAssert(tree); complexity+=5; } |
|
1615 public void visitApply(JCMethodInvocation tree) |
|
1616 { super.visitApply(tree); complexity+=2; } |
|
1617 public void visitNewClass(JCNewClass tree) |
|
1618 { scan(tree.encl); scan(tree.args); complexity+=2; } |
|
1619 public void visitNewArray(JCNewArray tree) |
|
1620 { super.visitNewArray(tree); complexity+=5; } |
|
1621 public void visitAssign(JCAssign tree) |
|
1622 { super.visitAssign(tree); complexity+=1; } |
|
1623 public void visitAssignop(JCAssignOp tree) |
|
1624 { super.visitAssignop(tree); complexity+=2; } |
|
1625 public void visitUnary(JCUnary tree) |
|
1626 { complexity+=1; |
|
1627 if (tree.type.constValue() == null) super.visitUnary(tree); } |
|
1628 public void visitBinary(JCBinary tree) |
|
1629 { complexity+=1; |
|
1630 if (tree.type.constValue() == null) super.visitBinary(tree); } |
|
1631 public void visitTypeTest(JCInstanceOf tree) |
|
1632 { super.visitTypeTest(tree); complexity+=1; } |
|
1633 public void visitIndexed(JCArrayAccess tree) |
|
1634 { super.visitIndexed(tree); complexity+=1; } |
|
1635 public void visitSelect(JCFieldAccess tree) |
|
1636 { super.visitSelect(tree); |
|
1637 if (tree.sym.kind == VAR) complexity+=1; } |
|
1638 public void visitIdent(JCIdent tree) { |
|
1639 if (tree.sym.kind == VAR) { |
|
1640 complexity+=1; |
|
1641 if (tree.type.constValue() == null && |
|
1642 tree.sym.owner.kind == TYP) |
|
1643 complexity+=1; |
|
1644 } |
|
1645 } |
|
1646 public void visitLiteral(JCLiteral tree) |
|
1647 { complexity+=1; } |
|
1648 public void visitTree(JCTree tree) {} |
|
1649 public void visitWildcard(JCWildcard tree) { |
|
1650 throw new AssertionError(this.getClass().getName()); |
|
1651 } |
|
1652 } |
|
1653 ComplexityScanner scanner = new ComplexityScanner(); |
|
1654 tree.accept(scanner); |
|
1655 return scanner.complexity; |
|
1656 } |
|
1657 |
1525 |
1658 public void visitIf(JCIf tree) { |
1526 public void visitIf(JCIf tree) { |
1659 int limit = code.nextreg; |
1527 int limit = code.nextreg; |
1660 Chain thenExit = null; |
1528 Chain thenExit = null; |
1661 CondItem c = genCond(TreeInfo.skipParens(tree.cond), |
1529 CondItem c = genCond(TreeInfo.skipParens(tree.cond), |