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.
|