langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java
changeset 36153 ed5063b304be
parent 35424 96661d1df628
child 36269 5b3afff0e70c
equal deleted inserted replaced
36047:1c076468bf7d 36153:ed5063b304be
     1 /*
     1 /*
     2  * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
   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),