< prev index next >

src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java

Print this page
rev 51104 : imported patch switch


  64     private final Log log;
  65     private final Symtab syms;
  66     private final Check chk;
  67     private final Resolve rs;
  68     private final TreeMaker make;
  69     private final Names names;
  70     private final Target target;
  71     private final Name accessDollar;
  72     private final Types types;
  73     private final Lower lower;
  74     private final Annotate annotate;
  75     private final StringConcat concat;
  76 
  77     /** Format of stackmap tables to be generated. */
  78     private final Code.StackMapFormat stackMap;
  79 
  80     /** A type that serves as the expected type for all method expressions.
  81      */
  82     private final Type methodType;
  83 
  84     /**
  85      * Are we presently traversing a let expression ? Yes if depth != 0
  86      */
  87     private int letExprDepth;
  88 
  89     public static Gen instance(Context context) {
  90         Gen instance = context.get(genKey);
  91         if (instance == null)
  92             instance = new Gen(context);
  93         return instance;
  94     }
  95 
  96     /** Constant pool, reset by genClass.
  97      */
  98     private final Pool pool;
  99 
 100     protected Gen(Context context) {
 101         context.put(genKey, this);
 102 
 103         names = Names.instance(context);
 104         log = Log.instance(context);
 105         syms = Symtab.instance(context);
 106         chk = Check.instance(context);
 107         rs = Resolve.instance(context);
 108         make = TreeMaker.instance(context);


 994                 checkDimension(l.head.pos(), l.head.sym.type);
 995                 code.setDefined(code.newLocal(l.head.sym));
 996             }
 997 
 998             // Get ready to generate code for method body.
 999             int startpcCrt = genCrt ? code.curCP() : 0;
1000             code.entryPoint();
1001 
1002             // Suppress initial stackmap
1003             code.pendingStackMap = false;
1004 
1005             return startpcCrt;
1006         }
1007 
1008     public void visitVarDef(JCVariableDecl tree) {
1009         VarSymbol v = tree.sym;
1010         code.newLocal(v);
1011         if (tree.init != null) {
1012             checkStringConstant(tree.init.pos(), v.getConstValue());
1013             if (v.getConstValue() == null || varDebugInfo) {
1014                 Assert.check(letExprDepth != 0 || code.state.stacksize == 0);
1015                 genExpr(tree.init, v.erasure(types)).load();
1016                 items.makeLocalItem(v).store();
1017                 Assert.check(letExprDepth != 0 || code.state.stacksize == 0);
1018             }
1019         }
1020         checkDimension(tree.pos(), v.type);
1021     }
1022 
1023     public void visitSkip(JCSkip tree) {
1024     }
1025 
1026     public void visitBlock(JCBlock tree) {
1027         int limit = code.nextreg;
1028         Env<GenContext> localEnv = env.dup(tree, new GenContext());
1029         genStats(tree.stats, localEnv);
1030         // End the scope of all block-local variables in variable info.
1031         if (!env.tree.hasTag(METHODDEF)) {
1032             code.statBegin(tree.endpos);
1033             code.endScopes(limit);
1034             code.pendingStatPos = Position.NOPOS;
1035         }
1036     }
1037 


1052     //where
1053         /** Generate code for a loop.
1054          *  @param loop       The tree representing the loop.
1055          *  @param body       The loop's body.
1056          *  @param cond       The loop's controling condition.
1057          *  @param step       "Step" statements to be inserted at end of
1058          *                    each iteration.
1059          *  @param testFirst  True if the loop test belongs before the body.
1060          */
1061         private void genLoop(JCStatement loop,
1062                              JCStatement body,
1063                              JCExpression cond,
1064                              List<JCExpressionStatement> step,
1065                              boolean testFirst) {
1066             Env<GenContext> loopEnv = env.dup(loop, new GenContext());
1067             int startpc = code.entryPoint();
1068             if (testFirst) { //while or for loop
1069                 CondItem c;
1070                 if (cond != null) {
1071                     code.statBegin(cond.pos);
1072                     Assert.check(code.state.stacksize == 0);
1073                     c = genCond(TreeInfo.skipParens(cond), CRT_FLOW_CONTROLLER);
1074                 } else {
1075                     c = items.makeCondItem(goto_);
1076                 }
1077                 Chain loopDone = c.jumpFalse();
1078                 code.resolve(c.trueJumps);
1079                 Assert.check(code.state.stacksize == 0);
1080                 genStat(body, loopEnv, CRT_STATEMENT | CRT_FLOW_TARGET);
1081                 code.resolve(loopEnv.info.cont);
1082                 genStats(step, loopEnv);
1083                 code.resolve(code.branch(goto_), startpc);
1084                 code.resolve(loopDone);
1085             } else {
1086                 genStat(body, loopEnv, CRT_STATEMENT | CRT_FLOW_TARGET);
1087                 code.resolve(loopEnv.info.cont);
1088                 genStats(step, loopEnv);
1089                 if (code.isAlive()) {
1090                     CondItem c;
1091                     if (cond != null) {
1092                         code.statBegin(cond.pos);
1093                         Assert.check(code.state.stacksize == 0);
1094                         c = genCond(TreeInfo.skipParens(cond), CRT_FLOW_CONTROLLER);
1095                     } else {
1096                         c = items.makeCondItem(goto_);
1097                     }
1098                     code.resolve(c.jumpTrue(), startpc);
1099                     Assert.check(code.state.stacksize == 0);
1100                     code.resolve(c.falseJumps);
1101                 }
1102             }
1103             Chain exit = loopEnv.info.exit;
1104             if (exit != null) {
1105                 code.resolve(exit);
1106                 exit.state.defined.excludeFrom(code.nextreg);
1107             }
1108         }
1109 
1110     public void visitForeachLoop(JCEnhancedForLoop tree) {
1111         throw new AssertionError(); // should have been removed by Lower.
1112     }
1113 
1114     public void visitLabelled(JCLabeledStatement tree) {
1115         Env<GenContext> localEnv = env.dup(tree, new GenContext());
1116         genStat(tree.body, localEnv, CRT_STATEMENT);
1117         Chain exit = localEnv.info.exit;
1118         if (exit != null) {
1119             code.resolve(exit);
1120             exit.state.defined.excludeFrom(code.nextreg);
1121         }
1122     }
1123 
1124     public void visitSwitch(JCSwitch tree) {
1125         int limit = code.nextreg;
1126         Assert.check(!tree.selector.type.hasTag(CLASS));
1127         int startpcCrt = genCrt ? code.curCP() : 0;
1128         Assert.check(code.state.stacksize == 0);
1129         Item sel = genExpr(tree.selector, syms.intType);
1130         List<JCCase> cases = tree.cases;
1131         if (cases.isEmpty()) {
1132             // We are seeing:  switch <sel> {}
1133             sel.load().drop();
1134             if (genCrt)
1135                 code.crt.put(TreeInfo.skipParens(tree.selector),
1136                              CRT_FLOW_CONTROLLER, startpcCrt, code.curCP());
1137         } else {
1138             // We are seeing a nonempty switch.
1139             sel.load();
1140             if (genCrt)
1141                 code.crt.put(TreeInfo.skipParens(tree.selector),
1142                              CRT_FLOW_CONTROLLER, startpcCrt, code.curCP());
1143             Env<GenContext> switchEnv = env.dup(tree, new GenContext());
1144             switchEnv.info.isSwitch = true;
1145 
1146             // Compute number of labels and minimum and maximum label values.
1147             // For each case, store its label in an array.
1148             int lo = Integer.MAX_VALUE;  // minimum label.
1149             int hi = Integer.MIN_VALUE;  // maximum label.
1150             int nlabels = 0;               // number of labels.
1151 
1152             int[] labels = new int[cases.length()];  // the label array.
1153             int defaultIndex = -1;     // the index of the default clause.
1154 
1155             List<JCCase> l = cases;
1156             for (int i = 0; i < labels.length; i++) {
1157                 if (l.head.pat != null) {
1158                     int val = ((Number)l.head.pat.type.constValue()).intValue();

1159                     labels[i] = val;
1160                     if (val < lo) lo = val;
1161                     if (hi < val) hi = val;
1162                     nlabels++;
1163                 } else {
1164                     Assert.check(defaultIndex == -1);
1165                     defaultIndex = i;
1166                 }
1167                 l = l.tail;
1168             }
1169 
1170             // Determine whether to issue a tableswitch or a lookupswitch
1171             // instruction.
1172             long table_space_cost = 4 + ((long) hi - lo + 1); // words
1173             long table_time_cost = 3; // comparisons
1174             long lookup_space_cost = 3 + 2 * (long) nlabels;
1175             long lookup_time_cost = nlabels;
1176             int opcode =
1177                 nlabels > 0 &&
1178                 table_space_cost + 3 * table_time_cost <=


1277                 while (pivot < keys[j]) j--;
1278                 if (i <= j) {
1279                     int temp1 = keys[i];
1280                     keys[i] = keys[j];
1281                     keys[j] = temp1;
1282                     int temp2 = values[i];
1283                     values[i] = values[j];
1284                     values[j] = temp2;
1285                     i++;
1286                     j--;
1287                 }
1288             } while (i <= j);
1289             if (lo < j) qsort2(keys, values, lo, j);
1290             if (i < hi) qsort2(keys, values, i, hi);
1291         }
1292 
1293     public void visitSynchronized(JCSynchronized tree) {
1294         int limit = code.nextreg;
1295         // Generate code to evaluate lock and save in temporary variable.
1296         final LocalItem lockVar = makeTemp(syms.objectType);
1297         Assert.check(code.state.stacksize == 0);
1298         genExpr(tree.lock, tree.lock.type).load().duplicate();
1299         lockVar.store();
1300 
1301         // Generate code to enter monitor.
1302         code.emitop0(monitorenter);
1303         code.state.lock(lockVar.reg);
1304 
1305         // Generate code for a try statement with given body, no catch clauses
1306         // in a new environment with the "exit-monitor" operation as finalizer.
1307         final Env<GenContext> syncEnv = env.dup(tree, new GenContext());
1308         syncEnv.info.finalize = new GenFinalizer() {
1309             void gen() {
1310                 genLast();
1311                 Assert.check(syncEnv.info.gaps.length() % 2 == 0);
1312                 syncEnv.info.gaps.append(code.curCP());
1313             }
1314             void genLast() {
1315                 if (code.isAlive()) {
1316                     lockVar.load();
1317                     code.emitop0(monitorexit);


1539         void registerCatch(DiagnosticPosition pos,
1540                            int startpc, int endpc,
1541                            int handler_pc, int catch_type) {
1542             char startpc1 = (char)startpc;
1543             char endpc1 = (char)endpc;
1544             char handler_pc1 = (char)handler_pc;
1545             if (startpc1 == startpc &&
1546                 endpc1 == endpc &&
1547                 handler_pc1 == handler_pc) {
1548                 code.addCatch(startpc1, endpc1, handler_pc1,
1549                               (char)catch_type);
1550             } else {
1551                 log.error(pos, Errors.LimitCodeTooLargeForTryStmt);
1552                 nerrs++;
1553             }
1554         }
1555 
1556     public void visitIf(JCIf tree) {
1557         int limit = code.nextreg;
1558         Chain thenExit = null;
1559         Assert.check(code.state.stacksize == 0);
1560         CondItem c = genCond(TreeInfo.skipParens(tree.cond),
1561                              CRT_FLOW_CONTROLLER);
1562         Chain elseChain = c.jumpFalse();
1563         Assert.check(code.state.stacksize == 0);
1564         if (!c.isFalse()) {
1565             code.resolve(c.trueJumps);
1566             genStat(tree.thenpart, env, CRT_STATEMENT | CRT_FLOW_TARGET);
1567             thenExit = code.branch(goto_);
1568         }
1569         if (elseChain != null) {
1570             code.resolve(elseChain);
1571             if (tree.elsepart != null) {
1572                 genStat(tree.elsepart, env,CRT_STATEMENT | CRT_FLOW_TARGET);
1573             }
1574         }
1575         code.resolve(thenExit);
1576         code.endScopes(limit);
1577         Assert.check(code.state.stacksize == 0);
1578     }
1579 
1580     public void visitExec(JCExpressionStatement tree) {
1581         // Optimize x++ to ++x and x-- to --x.
1582         JCExpression e = tree.expr;
1583         switch (e.getTag()) {
1584             case POSTINC:
1585                 ((JCUnary) e).setTag(PREINC);
1586                 break;
1587             case POSTDEC:
1588                 ((JCUnary) e).setTag(PREDEC);
1589                 break;
1590         }
1591         Assert.check(code.state.stacksize == 0);
1592         genExpr(tree.expr, tree.expr.type).drop();
1593         Assert.check(code.state.stacksize == 0);
1594     }
1595 
1596     public void visitBreak(JCBreak tree) {
1597         int tmpPos = code.pendingStatPos;
1598         Env<GenContext> targetEnv = unwind(tree.target, env);
1599         code.pendingStatPos = tmpPos;
1600         Assert.check(code.state.stacksize == 0);
1601         targetEnv.info.addExit(code.branch(goto_));
1602         endFinalizerGaps(env, targetEnv);
1603     }
1604 
1605     public void visitContinue(JCContinue tree) {
1606         int tmpPos = code.pendingStatPos;
1607         Env<GenContext> targetEnv = unwind(tree.target, env);
1608         code.pendingStatPos = tmpPos;
1609         Assert.check(code.state.stacksize == 0);
1610         targetEnv.info.addCont(code.branch(goto_));
1611         endFinalizerGaps(env, targetEnv);
1612     }
1613 
1614     public void visitReturn(JCReturn tree) {
1615         int limit = code.nextreg;
1616         final Env<GenContext> targetEnv;
1617 
1618         /* Save and then restore the location of the return in case a finally
1619          * is expanded (with unwind()) in the middle of our bytecodes.
1620          */
1621         int tmpPos = code.pendingStatPos;
1622         if (tree.expr != null) {
1623             Assert.check(code.state.stacksize == 0);
1624             Item r = genExpr(tree.expr, pt).load();
1625             if (hasFinally(env.enclMethod, env)) {
1626                 r = makeTemp(pt);
1627                 r.store();
1628             }
1629             targetEnv = unwind(env.enclMethod, env);
1630             code.pendingStatPos = tmpPos;
1631             r.load();
1632             code.emitop0(ireturn + Code.truncate(Code.typecode(pt)));
1633         } else {
1634             targetEnv = unwind(env.enclMethod, env);
1635             code.pendingStatPos = tmpPos;
1636             code.emitop0(return_);
1637         }
1638         endFinalizerGaps(env, targetEnv);
1639         code.endScopes(limit);
1640     }
1641 
1642     public void visitThrow(JCThrow tree) {
1643         Assert.check(code.state.stacksize == 0);
1644         genExpr(tree.expr, tree.expr.type).load();
1645         code.emitop0(athrow);
1646         Assert.check(code.state.stacksize == 0);
1647     }
1648 
1649 /* ************************************************************************
1650  * Visitor methods for expressions
1651  *************************************************************************/
1652 
1653     public void visitApply(JCMethodInvocation tree) {
1654         setTypeAnnotationPositions(tree.pos);
1655         // Generate code for method.
1656         Item m = genExpr(tree.meth, methodType);
1657         // Generate code for all arguments, where the expected types are
1658         // the parameters of the method's external type (that is, any implicit
1659         // outer instance of a super(...) call appears as first parameter).
1660         MethodSymbol msym = (MethodSymbol)TreeInfo.symbol(tree.meth);
1661         genArgs(tree.args,
1662                 msym.externalType(types).getParameterTypes());
1663         if (!msym.isDynamic()) {
1664             code.statBegin(tree.pos);
1665         }
1666         result = m.invoke();


2130                                        selectSuper || accessSuper);
2131                 }
2132             }
2133         }
2134     }
2135 
2136     public boolean isInvokeDynamic(Symbol sym) {
2137         return sym.kind == MTH && ((MethodSymbol)sym).isDynamic();
2138     }
2139 
2140     public void visitLiteral(JCLiteral tree) {
2141         if (tree.type.hasTag(BOT)) {
2142             code.emitop0(aconst_null);
2143             result = items.makeStackItem(tree.type);
2144         }
2145         else
2146             result = items.makeImmediateItem(tree.type, tree.value);
2147     }
2148 
2149     public void visitLetExpr(LetExpr tree) {
2150         letExprDepth++;
2151         int limit = code.nextreg;


2152         genStats(tree.defs, env);



2153         result = genExpr(tree.expr, tree.expr.type).load();
2154         code.endScopes(limit);
2155         letExprDepth--;
2156     }
2157 
2158     private void generateReferencesToPrunedTree(ClassSymbol classSymbol, Pool pool) {
2159         List<JCTree> prunedInfo = lower.prunedTree.get(classSymbol);
2160         if (prunedInfo != null) {
2161             for (JCTree prunedTree: prunedInfo) {
2162                 prunedTree.accept(classReferenceVisitor);
2163             }
2164         }
2165     }
2166 
2167 /* ************************************************************************
2168  * main method
2169  *************************************************************************/
2170 
2171     /** Generate code for a class definition.
2172      *  @param env   The attribution environment that belongs to the
2173      *               outermost class containing this class definition.
2174      *               We need this for resolving some additional symbols.
2175      *  @param cdef  The tree representing the class definition.




  64     private final Log log;
  65     private final Symtab syms;
  66     private final Check chk;
  67     private final Resolve rs;
  68     private final TreeMaker make;
  69     private final Names names;
  70     private final Target target;
  71     private final Name accessDollar;
  72     private final Types types;
  73     private final Lower lower;
  74     private final Annotate annotate;
  75     private final StringConcat concat;
  76 
  77     /** Format of stackmap tables to be generated. */
  78     private final Code.StackMapFormat stackMap;
  79 
  80     /** A type that serves as the expected type for all method expressions.
  81      */
  82     private final Type methodType;
  83 





  84     public static Gen instance(Context context) {
  85         Gen instance = context.get(genKey);
  86         if (instance == null)
  87             instance = new Gen(context);
  88         return instance;
  89     }
  90 
  91     /** Constant pool, reset by genClass.
  92      */
  93     private final Pool pool;
  94 
  95     protected Gen(Context context) {
  96         context.put(genKey, this);
  97 
  98         names = Names.instance(context);
  99         log = Log.instance(context);
 100         syms = Symtab.instance(context);
 101         chk = Check.instance(context);
 102         rs = Resolve.instance(context);
 103         make = TreeMaker.instance(context);


 989                 checkDimension(l.head.pos(), l.head.sym.type);
 990                 code.setDefined(code.newLocal(l.head.sym));
 991             }
 992 
 993             // Get ready to generate code for method body.
 994             int startpcCrt = genCrt ? code.curCP() : 0;
 995             code.entryPoint();
 996 
 997             // Suppress initial stackmap
 998             code.pendingStackMap = false;
 999 
1000             return startpcCrt;
1001         }
1002 
1003     public void visitVarDef(JCVariableDecl tree) {
1004         VarSymbol v = tree.sym;
1005         code.newLocal(v);
1006         if (tree.init != null) {
1007             checkStringConstant(tree.init.pos(), v.getConstValue());
1008             if (v.getConstValue() == null || varDebugInfo) {
1009                 Assert.check(code.isStatementStart());
1010                 genExpr(tree.init, v.erasure(types)).load();
1011                 items.makeLocalItem(v).store();
1012                 Assert.check(code.isStatementStart());
1013             }
1014         }
1015         checkDimension(tree.pos(), v.type);
1016     }
1017 
1018     public void visitSkip(JCSkip tree) {
1019     }
1020 
1021     public void visitBlock(JCBlock tree) {
1022         int limit = code.nextreg;
1023         Env<GenContext> localEnv = env.dup(tree, new GenContext());
1024         genStats(tree.stats, localEnv);
1025         // End the scope of all block-local variables in variable info.
1026         if (!env.tree.hasTag(METHODDEF)) {
1027             code.statBegin(tree.endpos);
1028             code.endScopes(limit);
1029             code.pendingStatPos = Position.NOPOS;
1030         }
1031     }
1032 


1047     //where
1048         /** Generate code for a loop.
1049          *  @param loop       The tree representing the loop.
1050          *  @param body       The loop's body.
1051          *  @param cond       The loop's controling condition.
1052          *  @param step       "Step" statements to be inserted at end of
1053          *                    each iteration.
1054          *  @param testFirst  True if the loop test belongs before the body.
1055          */
1056         private void genLoop(JCStatement loop,
1057                              JCStatement body,
1058                              JCExpression cond,
1059                              List<JCExpressionStatement> step,
1060                              boolean testFirst) {
1061             Env<GenContext> loopEnv = env.dup(loop, new GenContext());
1062             int startpc = code.entryPoint();
1063             if (testFirst) { //while or for loop
1064                 CondItem c;
1065                 if (cond != null) {
1066                     code.statBegin(cond.pos);
1067                     Assert.check(code.isStatementStart());
1068                     c = genCond(TreeInfo.skipParens(cond), CRT_FLOW_CONTROLLER);
1069                 } else {
1070                     c = items.makeCondItem(goto_);
1071                 }
1072                 Chain loopDone = c.jumpFalse();
1073                 code.resolve(c.trueJumps);
1074                 Assert.check(code.isStatementStart());
1075                 genStat(body, loopEnv, CRT_STATEMENT | CRT_FLOW_TARGET);
1076                 code.resolve(loopEnv.info.cont);
1077                 genStats(step, loopEnv);
1078                 code.resolve(code.branch(goto_), startpc);
1079                 code.resolve(loopDone);
1080             } else {
1081                 genStat(body, loopEnv, CRT_STATEMENT | CRT_FLOW_TARGET);
1082                 code.resolve(loopEnv.info.cont);
1083                 genStats(step, loopEnv);
1084                 if (code.isAlive()) {
1085                     CondItem c;
1086                     if (cond != null) {
1087                         code.statBegin(cond.pos);
1088                         Assert.check(code.isStatementStart());
1089                         c = genCond(TreeInfo.skipParens(cond), CRT_FLOW_CONTROLLER);
1090                     } else {
1091                         c = items.makeCondItem(goto_);
1092                     }
1093                     code.resolve(c.jumpTrue(), startpc);
1094                     Assert.check(code.isStatementStart());
1095                     code.resolve(c.falseJumps);
1096                 }
1097             }
1098             Chain exit = loopEnv.info.exit;
1099             if (exit != null) {
1100                 code.resolve(exit);
1101                 exit.state.defined.excludeFrom(code.nextreg);
1102             }
1103         }
1104 
1105     public void visitForeachLoop(JCEnhancedForLoop tree) {
1106         throw new AssertionError(); // should have been removed by Lower.
1107     }
1108 
1109     public void visitLabelled(JCLabeledStatement tree) {
1110         Env<GenContext> localEnv = env.dup(tree, new GenContext());
1111         genStat(tree.body, localEnv, CRT_STATEMENT);
1112         Chain exit = localEnv.info.exit;
1113         if (exit != null) {
1114             code.resolve(exit);
1115             exit.state.defined.excludeFrom(code.nextreg);
1116         }
1117     }
1118 
1119     public void visitSwitch(JCSwitch tree) {
1120         int limit = code.nextreg;
1121         Assert.check(!tree.selector.type.hasTag(CLASS));
1122         int startpcCrt = genCrt ? code.curCP() : 0;
1123         Assert.check(code.isStatementStart());
1124         Item sel = genExpr(tree.selector, syms.intType);
1125         List<JCCase> cases = tree.cases;
1126         if (cases.isEmpty()) {
1127             // We are seeing:  switch <sel> {}
1128             sel.load().drop();
1129             if (genCrt)
1130                 code.crt.put(TreeInfo.skipParens(tree.selector),
1131                              CRT_FLOW_CONTROLLER, startpcCrt, code.curCP());
1132         } else {
1133             // We are seeing a nonempty switch.
1134             sel.load();
1135             if (genCrt)
1136                 code.crt.put(TreeInfo.skipParens(tree.selector),
1137                              CRT_FLOW_CONTROLLER, startpcCrt, code.curCP());
1138             Env<GenContext> switchEnv = env.dup(tree, new GenContext());
1139             switchEnv.info.isSwitch = true;
1140 
1141             // Compute number of labels and minimum and maximum label values.
1142             // For each case, store its label in an array.
1143             int lo = Integer.MAX_VALUE;  // minimum label.
1144             int hi = Integer.MIN_VALUE;  // maximum label.
1145             int nlabels = 0;               // number of labels.
1146 
1147             int[] labels = new int[cases.length()];  // the label array.
1148             int defaultIndex = -1;     // the index of the default clause.
1149 
1150             List<JCCase> l = cases;
1151             for (int i = 0; i < labels.length; i++) {
1152                 if (l.head.pats.nonEmpty()) {
1153                     Assert.check(l.head.pats.size() == 1);
1154                     int val = ((Number)l.head.pats.head.type.constValue()).intValue();
1155                     labels[i] = val;
1156                     if (val < lo) lo = val;
1157                     if (hi < val) hi = val;
1158                     nlabels++;
1159                 } else {
1160                     Assert.check(defaultIndex == -1);
1161                     defaultIndex = i;
1162                 }
1163                 l = l.tail;
1164             }
1165 
1166             // Determine whether to issue a tableswitch or a lookupswitch
1167             // instruction.
1168             long table_space_cost = 4 + ((long) hi - lo + 1); // words
1169             long table_time_cost = 3; // comparisons
1170             long lookup_space_cost = 3 + 2 * (long) nlabels;
1171             long lookup_time_cost = nlabels;
1172             int opcode =
1173                 nlabels > 0 &&
1174                 table_space_cost + 3 * table_time_cost <=


1273                 while (pivot < keys[j]) j--;
1274                 if (i <= j) {
1275                     int temp1 = keys[i];
1276                     keys[i] = keys[j];
1277                     keys[j] = temp1;
1278                     int temp2 = values[i];
1279                     values[i] = values[j];
1280                     values[j] = temp2;
1281                     i++;
1282                     j--;
1283                 }
1284             } while (i <= j);
1285             if (lo < j) qsort2(keys, values, lo, j);
1286             if (i < hi) qsort2(keys, values, i, hi);
1287         }
1288 
1289     public void visitSynchronized(JCSynchronized tree) {
1290         int limit = code.nextreg;
1291         // Generate code to evaluate lock and save in temporary variable.
1292         final LocalItem lockVar = makeTemp(syms.objectType);
1293         Assert.check(code.isStatementStart());
1294         genExpr(tree.lock, tree.lock.type).load().duplicate();
1295         lockVar.store();
1296 
1297         // Generate code to enter monitor.
1298         code.emitop0(monitorenter);
1299         code.state.lock(lockVar.reg);
1300 
1301         // Generate code for a try statement with given body, no catch clauses
1302         // in a new environment with the "exit-monitor" operation as finalizer.
1303         final Env<GenContext> syncEnv = env.dup(tree, new GenContext());
1304         syncEnv.info.finalize = new GenFinalizer() {
1305             void gen() {
1306                 genLast();
1307                 Assert.check(syncEnv.info.gaps.length() % 2 == 0);
1308                 syncEnv.info.gaps.append(code.curCP());
1309             }
1310             void genLast() {
1311                 if (code.isAlive()) {
1312                     lockVar.load();
1313                     code.emitop0(monitorexit);


1535         void registerCatch(DiagnosticPosition pos,
1536                            int startpc, int endpc,
1537                            int handler_pc, int catch_type) {
1538             char startpc1 = (char)startpc;
1539             char endpc1 = (char)endpc;
1540             char handler_pc1 = (char)handler_pc;
1541             if (startpc1 == startpc &&
1542                 endpc1 == endpc &&
1543                 handler_pc1 == handler_pc) {
1544                 code.addCatch(startpc1, endpc1, handler_pc1,
1545                               (char)catch_type);
1546             } else {
1547                 log.error(pos, Errors.LimitCodeTooLargeForTryStmt);
1548                 nerrs++;
1549             }
1550         }
1551 
1552     public void visitIf(JCIf tree) {
1553         int limit = code.nextreg;
1554         Chain thenExit = null;
1555         Assert.check(code.isStatementStart());
1556         CondItem c = genCond(TreeInfo.skipParens(tree.cond),
1557                              CRT_FLOW_CONTROLLER);
1558         Chain elseChain = c.jumpFalse();
1559         Assert.check(code.isStatementStart());
1560         if (!c.isFalse()) {
1561             code.resolve(c.trueJumps);
1562             genStat(tree.thenpart, env, CRT_STATEMENT | CRT_FLOW_TARGET);
1563             thenExit = code.branch(goto_);
1564         }
1565         if (elseChain != null) {
1566             code.resolve(elseChain);
1567             if (tree.elsepart != null) {
1568                 genStat(tree.elsepart, env,CRT_STATEMENT | CRT_FLOW_TARGET);
1569             }
1570         }
1571         code.resolve(thenExit);
1572         code.endScopes(limit);
1573         Assert.check(code.isStatementStart());
1574     }
1575 
1576     public void visitExec(JCExpressionStatement tree) {
1577         // Optimize x++ to ++x and x-- to --x.
1578         JCExpression e = tree.expr;
1579         switch (e.getTag()) {
1580             case POSTINC:
1581                 ((JCUnary) e).setTag(PREINC);
1582                 break;
1583             case POSTDEC:
1584                 ((JCUnary) e).setTag(PREDEC);
1585                 break;
1586         }
1587         Assert.check(code.isStatementStart());
1588         genExpr(tree.expr, tree.expr.type).drop();
1589         Assert.check(code.isStatementStart());
1590     }
1591 
1592     public void visitBreak(JCBreak tree) {
1593         int tmpPos = code.pendingStatPos;
1594         Env<GenContext> targetEnv = unwind(tree.target, env);
1595         code.pendingStatPos = tmpPos;
1596         Assert.check(code.isStatementStart());
1597         targetEnv.info.addExit(code.branch(goto_));
1598         endFinalizerGaps(env, targetEnv);
1599     }
1600 
1601     public void visitContinue(JCContinue tree) {
1602         int tmpPos = code.pendingStatPos;
1603         Env<GenContext> targetEnv = unwind(tree.target, env);
1604         code.pendingStatPos = tmpPos;
1605         Assert.check(code.isStatementStart());
1606         targetEnv.info.addCont(code.branch(goto_));
1607         endFinalizerGaps(env, targetEnv);
1608     }
1609 
1610     public void visitReturn(JCReturn tree) {
1611         int limit = code.nextreg;
1612         final Env<GenContext> targetEnv;
1613 
1614         /* Save and then restore the location of the return in case a finally
1615          * is expanded (with unwind()) in the middle of our bytecodes.
1616          */
1617         int tmpPos = code.pendingStatPos;
1618         if (tree.expr != null) {
1619             Assert.check(code.isStatementStart());
1620             Item r = genExpr(tree.expr, pt).load();
1621             if (hasFinally(env.enclMethod, env)) {
1622                 r = makeTemp(pt);
1623                 r.store();
1624             }
1625             targetEnv = unwind(env.enclMethod, env);
1626             code.pendingStatPos = tmpPos;
1627             r.load();
1628             code.emitop0(ireturn + Code.truncate(Code.typecode(pt)));
1629         } else {
1630             targetEnv = unwind(env.enclMethod, env);
1631             code.pendingStatPos = tmpPos;
1632             code.emitop0(return_);
1633         }
1634         endFinalizerGaps(env, targetEnv);
1635         code.endScopes(limit);
1636     }
1637 
1638     public void visitThrow(JCThrow tree) {
1639         Assert.check(code.isStatementStart());
1640         genExpr(tree.expr, tree.expr.type).load();
1641         code.emitop0(athrow);
1642         Assert.check(code.isStatementStart());
1643     }
1644 
1645 /* ************************************************************************
1646  * Visitor methods for expressions
1647  *************************************************************************/
1648 
1649     public void visitApply(JCMethodInvocation tree) {
1650         setTypeAnnotationPositions(tree.pos);
1651         // Generate code for method.
1652         Item m = genExpr(tree.meth, methodType);
1653         // Generate code for all arguments, where the expected types are
1654         // the parameters of the method's external type (that is, any implicit
1655         // outer instance of a super(...) call appears as first parameter).
1656         MethodSymbol msym = (MethodSymbol)TreeInfo.symbol(tree.meth);
1657         genArgs(tree.args,
1658                 msym.externalType(types).getParameterTypes());
1659         if (!msym.isDynamic()) {
1660             code.statBegin(tree.pos);
1661         }
1662         result = m.invoke();


2126                                        selectSuper || accessSuper);
2127                 }
2128             }
2129         }
2130     }
2131 
2132     public boolean isInvokeDynamic(Symbol sym) {
2133         return sym.kind == MTH && ((MethodSymbol)sym).isDynamic();
2134     }
2135 
2136     public void visitLiteral(JCLiteral tree) {
2137         if (tree.type.hasTag(BOT)) {
2138             code.emitop0(aconst_null);
2139             result = items.makeStackItem(tree.type);
2140         }
2141         else
2142             result = items.makeImmediateItem(tree.type, tree.value);
2143     }
2144 
2145     public void visitLetExpr(LetExpr tree) {

2146         int limit = code.nextreg;
2147         int prevLetExprStart = code.setLetExprStackPos(code.state.stacksize);
2148         try {
2149             genStats(tree.defs, env);
2150         } finally {
2151             code.setLetExprStackPos(prevLetExprStart);
2152         }
2153         result = genExpr(tree.expr, tree.expr.type).load();
2154         code.endScopes(limit);

2155     }
2156 
2157     private void generateReferencesToPrunedTree(ClassSymbol classSymbol, Pool pool) {
2158         List<JCTree> prunedInfo = lower.prunedTree.get(classSymbol);
2159         if (prunedInfo != null) {
2160             for (JCTree prunedTree: prunedInfo) {
2161                 prunedTree.accept(classReferenceVisitor);
2162             }
2163         }
2164     }
2165 
2166 /* ************************************************************************
2167  * main method
2168  *************************************************************************/
2169 
2170     /** Generate code for a class definition.
2171      *  @param env   The attribution environment that belongs to the
2172      *               outermost class containing this class definition.
2173      *               We need this for resolving some additional symbols.
2174      *  @param cdef  The tree representing the class definition.


< prev index next >