15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.tools.javac.jvm;
27
28 import com.sun.tools.javac.code.*;
29 import com.sun.tools.javac.code.Symbol.*;
30 import com.sun.tools.javac.resources.CompilerProperties.Errors;
31 import com.sun.tools.javac.util.*;
32 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
33
34 import java.util.function.ToIntBiFunction;
35 import java.util.function.ToIntFunction;
36
37 import static com.sun.tools.javac.code.TypeTag.ARRAY;
38 import static com.sun.tools.javac.code.TypeTag.BOT;
39 import static com.sun.tools.javac.code.TypeTag.DOUBLE;
40 import static com.sun.tools.javac.code.TypeTag.INT;
41 import static com.sun.tools.javac.code.TypeTag.LONG;
42 import static com.sun.tools.javac.code.TypeTag.TYPEVAR;
43 import static com.sun.tools.javac.jvm.ByteCodes.*;
44 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Class;
45 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Double;
46 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Fieldref;
47 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Float;
48 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Integer;
49 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_InterfaceMethodref;
50 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Long;
51 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_MethodHandle;
52 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_MethodType;
53 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Methodref;
54 import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_String;
55 import static com.sun.tools.javac.jvm.UninitializedType.*;
56 import static com.sun.tools.javac.jvm.ClassWriter.StackMapTableFrame;
57 import java.util.Arrays;
58
59 /** An internal structure that corresponds to the code attribute of
60 * methods in a classfile. The class also provides some utility operations to
61 * generate bytecode instructions.
62 *
63 * <p><b>This is NOT part of any supported API.
64 * If you write code that depends on this, you do so at your own risk.
65 * This code and its internal interfaces are subject to change or
66 * deletion without notice.</b>
67 */
68 public class Code {
69
70 public final boolean debugCode;
71 public final boolean needStackMap;
72
73 public enum StackMapFormat {
74 NONE,
75 CLDC {
76 Name getAttributeName(Names names) {
77 return names.StackMap;
182
183 /** The stack map format to be generated. */
184 StackMapFormat stackMap;
185
186 /** Switch: emit variable debug info.
187 */
188 boolean varDebugInfo;
189
190 /** Switch: emit line number info.
191 */
192 boolean lineDebugInfo;
193
194 /** Emit line number info if map supplied
195 */
196 Position.LineMap lineMap;
197
198 final MethodSymbol meth;
199
200 private int letExprStackPos = 0;
201
202 /** Construct a code object, given the settings of the fatcode,
203 * debugging info switches and the CharacterRangeTable.
204 */
205 public Code(MethodSymbol meth,
206 boolean fatcode,
207 Position.LineMap lineMap,
208 boolean varDebugInfo,
209 StackMapFormat stackMap,
210 boolean debugCode,
211 CRTable crt,
212 Symtab syms,
213 Types types,
214 PoolWriter poolWriter) {
215 this.meth = meth;
216 this.fatcode = fatcode;
217 this.lineMap = lineMap;
218 this.lineDebugInfo = lineMap != null;
219 this.varDebugInfo = varDebugInfo;
220 this.crt = crt;
221 this.syms = syms;
222 this.types = types;
223 this.poolWriter = poolWriter;
224 this.debugCode = debugCode;
225 this.stackMap = stackMap;
226 switch (stackMap) {
227 case CLDC:
228 case JSR202:
229 this.needStackMap = true;
230 break;
231 default:
232 this.needStackMap = false;
233 }
234 state = new State();
235 lvar = new LocalVar[20];
236 }
237
238
239 /* **************************************************************************
240 * Typecodes & related stuff
241 ****************************************************************************/
242
243 /** Given a type, return its type code (used implicitly in the
244 * JVM architecture).
245 */
246 public static int typecode(Type type) {
247 switch (type.getTag()) {
248 case BYTE: return BYTEcode;
249 case SHORT: return SHORTcode;
250 case CHAR: return CHARcode;
251 case INT: return INTcode;
252 case LONG: return LONGcode;
253 case FLOAT: return FLOATcode;
254 case DOUBLE: return DOUBLEcode;
255 case BOOLEAN: return BYTEcode;
1066 case checkcast: {
1067 state.pop(1); // object ref
1068 Type t = types.erasure((Type)data);
1069 state.push(t);
1070 break; }
1071 case ldc2:
1072 case ldc2w:
1073 state.push(types.constantType((LoadableConstant)data));
1074 break;
1075 case instanceof_:
1076 state.pop(1);
1077 state.push(syms.intType);
1078 break;
1079 case jsr:
1080 break;
1081 default:
1082 throw new AssertionError(mnem(op));
1083 }
1084 // postop();
1085 }
1086
1087 /** Emit an opcode with a four-byte operand field.
1088 */
1089 public void emitop4(int op, int od) {
1090 emitop(op);
1091 if (!alive) return;
1092 emit4(od);
1093 switch (op) {
1094 case goto_w:
1095 markDead();
1096 break;
1097 case jsr_w:
1098 break;
1099 default:
1100 throw new AssertionError(mnem(op));
1101 }
1102 // postop();
1103 }
1104
1105 /** Align code pointer to next `incr' boundary.
1106 */
1213
1214 public int setLetExprStackPos(int pos) {
1215 int res = letExprStackPos;
1216 letExprStackPos = pos;
1217 return res;
1218 }
1219
1220 public boolean isStatementStart() {
1221 return !alive || state.stacksize == letExprStackPos;
1222 }
1223
1224 /* ************************************************************************
1225 * Stack map generation
1226 *************************************************************************/
1227
1228 /** An entry in the stack map. */
1229 static class StackMapFrame {
1230 int pc;
1231 Type[] locals;
1232 Type[] stack;
1233 }
1234
1235 /** A buffer of cldc stack map entries. */
1236 StackMapFrame[] stackMapBuffer = null;
1237
1238 /** A buffer of compressed StackMapTable entries. */
1239 StackMapTableFrame[] stackMapTableBuffer = null;
1240 int stackMapBufferSize = 0;
1241
1242 /** The last PC at which we generated a stack map. */
1243 int lastStackMapPC = -1;
1244
1245 /** The last stack map frame in StackMapTable. */
1246 StackMapFrame lastFrame = null;
1247
1248 /** The stack map frame before the last one. */
1249 StackMapFrame frameBeforeLast = null;
1250
1251 /** Emit a stack map entry. */
1252 public void emitStackMap() {
1308 }
1309 frame.stack = new Type[state.stacksize];
1310 for (int i=0; i<state.stacksize; i++)
1311 frame.stack[i] = state.stack[i];
1312 }
1313
1314 void emitStackMapFrame(int pc, int localsSize) {
1315 if (lastFrame == null) {
1316 // first frame
1317 lastFrame = getInitialFrame();
1318 } else if (lastFrame.pc == pc) {
1319 // drop existing stackmap at this offset
1320 stackMapTableBuffer[--stackMapBufferSize] = null;
1321 lastFrame = frameBeforeLast;
1322 frameBeforeLast = null;
1323 }
1324
1325 StackMapFrame frame = new StackMapFrame();
1326 frame.pc = pc;
1327
1328 int localCount = 0;
1329 Type[] locals = new Type[localsSize];
1330 for (int i=0; i<localsSize; i++, localCount++) {
1331 if (state.defined.isMember(i) && lvar[i] != null) {
1332 Type vtype = lvar[i].sym.type;
1333 if (!(vtype instanceof UninitializedType))
1334 vtype = types.erasure(vtype);
1335 locals[i] = vtype;
1336 if (width(vtype) > 1) i++;
1337 }
1338 }
1339 frame.locals = new Type[localCount];
1340 for (int i=0, j=0; i<localsSize; i++, j++) {
1341 Assert.check(j < localCount);
1342 frame.locals[j] = locals[i];
1343 if (width(locals[i]) > 1) i++;
1344 }
1345
1346 int stackCount = 0;
1347 for (int i=0; i<state.stacksize; i++) {
1348 if (state.stack[i] != null) {
1349 stackCount++;
1350 }
1351 }
1352 frame.stack = new Type[stackCount];
1353 stackCount = 0;
1354 for (int i=0; i<state.stacksize; i++) {
1355 if (state.stack[i] != null) {
1356 frame.stack[stackCount++] = types.erasure(state.stack[i]);
1357 }
1358 }
1359
1360 if (stackMapTableBuffer == null) {
1361 stackMapTableBuffer = new StackMapTableFrame[20];
1362 } else {
1363 stackMapTableBuffer = ArrayUtils.ensureCapacity(
1364 stackMapTableBuffer,
1365 stackMapBufferSize);
1366 }
1367 stackMapTableBuffer[stackMapBufferSize++] =
1368 StackMapTableFrame.getInstance(frame, lastFrame.pc, lastFrame.locals, types);
1369
1370 frameBeforeLast = lastFrame;
1371 lastFrame = frame;
1372 }
1373
1374 StackMapFrame getInitialFrame() {
1375 StackMapFrame frame = new StackMapFrame();
1376 List<Type> arg_types = ((MethodType)meth.externalType(types)).argtypes;
1377 int len = arg_types.length();
1378 int count = 0;
1379 if (!meth.isStatic()) {
1380 Type thisType = meth.owner.type;
1381 frame.locals = new Type[len+1];
1382 if (meth.isConstructor() && thisType != syms.objectType) {
1383 frame.locals[count++] = UninitializedType.uninitializedThis(thisType);
1384 } else {
1385 frame.locals[count++] = types.erasure(thisType);
1386 }
1387 } else {
1388 frame.locals = new Type[len];
1389 }
1390 for (Type arg_type : arg_types) {
1391 frame.locals[count++] = types.erasure(arg_type);
1392 }
1393 frame.pc = -1;
1394 frame.stack = null;
1395 return frame;
1396 }
1397
1398
1399 /* ************************************************************************
1400 * Operations having to do with jumps
1401 *************************************************************************/
1402
1403 /** A chain represents a list of unresolved jumps. Jump locations
1404 * are sorted in decreasing order.
1405 */
1406 public static class Chain {
1407
1408 /** The position of the jump instruction.
1409 */
1410 public final int pc;
1411
1412 /** The machine state after the jump instruction.
1413 * Invariant: all elements of a chain list have the same stacksize
1414 * and compatible stack and register contents.
1453 return cp - 5;
1454 } else {
1455 emitop2(opcode, 0);
1456 return cp - 3;
1457 }
1458 }
1459
1460 /** Emit a branch with given opcode; return its chain.
1461 * branch differs from jump in that jsr is treated as no-op.
1462 */
1463 public Chain branch(int opcode) {
1464 Chain result = null;
1465 if (opcode == goto_) {
1466 result = pendingJumps;
1467 pendingJumps = null;
1468 }
1469 if (opcode != dontgoto && isAlive()) {
1470 result = new Chain(emitJump(opcode),
1471 result,
1472 state.dup());
1473 fixedPc = fatcode;
1474 if (opcode == goto_) alive = false;
1475 }
1476 return result;
1477 }
1478
1479 /** Resolve chain to point to given target.
1480 */
1481 public void resolve(Chain chain, int target) {
1482 boolean changed = false;
1483 State newState = state;
1484 for (; chain != null; chain = chain.next) {
1485 Assert.check(state != chain.state
1486 && (target > chain.pc || isStatementStart()));
1487 if (target >= cp) {
1488 target = cp;
1489 } else if (get1(target) == goto_) {
1490 if (fatcode) target = target + get4(target + 1);
1491 else target = target + get2(target + 1);
1492 }
1493 if (get1(chain.pc) == goto_ &&
1494 chain.pc + 3 == target && target == cp && !fixedPc) {
1495 // If goto the next instruction, the jump is not needed:
1496 // compact the code.
1497 if (varDebugInfo) {
1498 adjustAliveRanges(cp, -3);
1499 }
1500 cp = cp - 3;
1501 target = target - 3;
1502 if (chain.next == null) {
1503 // This is the only jump to the target. Exit the loop
1504 // without setting new state. The code is reachable
1505 // from the instruction before goto_.
1506 alive = true;
1507 break;
1508 }
1509 } else {
1510 if (fatcode)
1511 put4(chain.pc + 1, target - chain.pc);
1512 else if (target - chain.pc < Short.MIN_VALUE ||
1513 target - chain.pc > Short.MAX_VALUE)
1514 fatcode = true;
1515 else
1516 put2(chain.pc + 1, target - chain.pc);
1517 Assert.check(!alive ||
1518 chain.state.stacksize == newState.stacksize &&
1519 chain.state.nlocks == newState.nlocks);
1520 }
1521 fixedPc = true;
1522 if (cp == target) {
1523 changed = true;
1524 if (debugCode)
1525 System.err.println("resolving chain state=" + chain.state);
1526 if (alive) {
1527 newState = chain.state.join(newState);
1528 } else {
1529 newState = chain.state;
1530 alive = true;
1531 }
1532 }
1533 }
1534 Assert.check(!changed || state != newState);
1535 if (state != newState) {
1536 setDefined(newState.defined);
|
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.tools.javac.jvm;
27
28 import com.sun.tools.javac.code.*;
29 import com.sun.tools.javac.code.Symbol.*;
30 import com.sun.tools.javac.resources.CompilerProperties.Errors;
31 import com.sun.tools.javac.util.*;
32 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
33
34 import java.util.function.ToIntBiFunction;
35
36 import static com.sun.tools.javac.code.TypeTag.ARRAY;
37 import static com.sun.tools.javac.code.TypeTag.BOT;
38 import static com.sun.tools.javac.code.TypeTag.DOUBLE;
39 import static com.sun.tools.javac.code.TypeTag.INT;
40 import static com.sun.tools.javac.code.TypeTag.LONG;
41 import static com.sun.tools.javac.code.TypeTag.TYPEVAR;
42 import static com.sun.tools.javac.jvm.ByteCodes.*;
43 import static com.sun.tools.javac.jvm.UninitializedType.*;
44 import static com.sun.tools.javac.jvm.ClassWriter.StackMapTableFrame;
45 import java.util.Arrays;
46 import java.util.Map;
47 import java.util.HashMap;
48 import java.util.Set;
49
50 /** An internal structure that corresponds to the code attribute of
51 * methods in a classfile. The class also provides some utility operations to
52 * generate bytecode instructions.
53 *
54 * <p><b>This is NOT part of any supported API.
55 * If you write code that depends on this, you do so at your own risk.
56 * This code and its internal interfaces are subject to change or
57 * deletion without notice.</b>
58 */
59 public class Code {
60
61 public final boolean debugCode;
62 public final boolean needStackMap;
63
64 public enum StackMapFormat {
65 NONE,
66 CLDC {
67 Name getAttributeName(Names names) {
68 return names.StackMap;
173
174 /** The stack map format to be generated. */
175 StackMapFormat stackMap;
176
177 /** Switch: emit variable debug info.
178 */
179 boolean varDebugInfo;
180
181 /** Switch: emit line number info.
182 */
183 boolean lineDebugInfo;
184
185 /** Emit line number info if map supplied
186 */
187 Position.LineMap lineMap;
188
189 final MethodSymbol meth;
190
191 private int letExprStackPos = 0;
192
193 private Map<Integer, Set<VarSymbol>> cpToUnsetFieldsMap = new HashMap<>();
194
195 public Set<VarSymbol> initialUnsetFields;
196
197 public Set<VarSymbol> currentUnsetFields;
198
199 boolean generateEarlyLarvalFrame;
200
201 /** Construct a code object, given the settings of the fatcode,
202 * debugging info switches and the CharacterRangeTable.
203 */
204 public Code(MethodSymbol meth,
205 boolean fatcode,
206 Position.LineMap lineMap,
207 boolean varDebugInfo,
208 StackMapFormat stackMap,
209 boolean debugCode,
210 CRTable crt,
211 Symtab syms,
212 Types types,
213 PoolWriter poolWriter,
214 boolean generateEarlyLarvalFrame) {
215 this.meth = meth;
216 this.fatcode = fatcode;
217 this.lineMap = lineMap;
218 this.lineDebugInfo = lineMap != null;
219 this.varDebugInfo = varDebugInfo;
220 this.crt = crt;
221 this.syms = syms;
222 this.types = types;
223 this.poolWriter = poolWriter;
224 this.debugCode = debugCode;
225 this.stackMap = stackMap;
226 switch (stackMap) {
227 case CLDC:
228 case JSR202:
229 this.needStackMap = true;
230 break;
231 default:
232 this.needStackMap = false;
233 }
234 state = new State();
235 lvar = new LocalVar[20];
236 this.generateEarlyLarvalFrame = generateEarlyLarvalFrame;
237 }
238
239
240 /* **************************************************************************
241 * Typecodes & related stuff
242 ****************************************************************************/
243
244 /** Given a type, return its type code (used implicitly in the
245 * JVM architecture).
246 */
247 public static int typecode(Type type) {
248 switch (type.getTag()) {
249 case BYTE: return BYTEcode;
250 case SHORT: return SHORTcode;
251 case CHAR: return CHARcode;
252 case INT: return INTcode;
253 case LONG: return LONGcode;
254 case FLOAT: return FLOATcode;
255 case DOUBLE: return DOUBLEcode;
256 case BOOLEAN: return BYTEcode;
1067 case checkcast: {
1068 state.pop(1); // object ref
1069 Type t = types.erasure((Type)data);
1070 state.push(t);
1071 break; }
1072 case ldc2:
1073 case ldc2w:
1074 state.push(types.constantType((LoadableConstant)data));
1075 break;
1076 case instanceof_:
1077 state.pop(1);
1078 state.push(syms.intType);
1079 break;
1080 case jsr:
1081 break;
1082 default:
1083 throw new AssertionError(mnem(op));
1084 }
1085 // postop();
1086 }
1087 /** Emit an opcode with a four-byte operand field.
1088 */
1089 public void emitop4(int op, int od) {
1090 emitop(op);
1091 if (!alive) return;
1092 emit4(od);
1093 switch (op) {
1094 case goto_w:
1095 markDead();
1096 break;
1097 case jsr_w:
1098 break;
1099 default:
1100 throw new AssertionError(mnem(op));
1101 }
1102 // postop();
1103 }
1104
1105 /** Align code pointer to next `incr' boundary.
1106 */
1213
1214 public int setLetExprStackPos(int pos) {
1215 int res = letExprStackPos;
1216 letExprStackPos = pos;
1217 return res;
1218 }
1219
1220 public boolean isStatementStart() {
1221 return !alive || state.stacksize == letExprStackPos;
1222 }
1223
1224 /* ************************************************************************
1225 * Stack map generation
1226 *************************************************************************/
1227
1228 /** An entry in the stack map. */
1229 static class StackMapFrame {
1230 int pc;
1231 Type[] locals;
1232 Type[] stack;
1233 Set<VarSymbol> unsetFields;
1234 }
1235
1236 /** A buffer of cldc stack map entries. */
1237 StackMapFrame[] stackMapBuffer = null;
1238
1239 /** A buffer of compressed StackMapTable entries. */
1240 StackMapTableFrame[] stackMapTableBuffer = null;
1241 int stackMapBufferSize = 0;
1242
1243 /** The last PC at which we generated a stack map. */
1244 int lastStackMapPC = -1;
1245
1246 /** The last stack map frame in StackMapTable. */
1247 StackMapFrame lastFrame = null;
1248
1249 /** The stack map frame before the last one. */
1250 StackMapFrame frameBeforeLast = null;
1251
1252 /** Emit a stack map entry. */
1253 public void emitStackMap() {
1309 }
1310 frame.stack = new Type[state.stacksize];
1311 for (int i=0; i<state.stacksize; i++)
1312 frame.stack[i] = state.stack[i];
1313 }
1314
1315 void emitStackMapFrame(int pc, int localsSize) {
1316 if (lastFrame == null) {
1317 // first frame
1318 lastFrame = getInitialFrame();
1319 } else if (lastFrame.pc == pc) {
1320 // drop existing stackmap at this offset
1321 stackMapTableBuffer[--stackMapBufferSize] = null;
1322 lastFrame = frameBeforeLast;
1323 frameBeforeLast = null;
1324 }
1325
1326 StackMapFrame frame = new StackMapFrame();
1327 frame.pc = pc;
1328
1329 boolean hasUninitalizedThis = false;
1330 int localCount = 0;
1331 Type[] locals = new Type[localsSize];
1332 for (int i=0; i<localsSize; i++, localCount++) {
1333 if (state.defined.isMember(i) && lvar[i] != null) {
1334 Type vtype = lvar[i].sym.type;
1335 if (!(vtype instanceof UninitializedType)) {
1336 vtype = types.erasure(vtype);
1337 } else if (vtype.hasTag(TypeTag.UNINITIALIZED_THIS)) {
1338 hasUninitalizedThis = true;
1339 }
1340 locals[i] = vtype;
1341 if (width(vtype) > 1) i++;
1342 }
1343 }
1344 frame.locals = new Type[localCount];
1345 for (int i=0, j=0; i<localsSize; i++, j++) {
1346 Assert.check(j < localCount);
1347 frame.locals[j] = locals[i];
1348 if (width(locals[i]) > 1) i++;
1349 }
1350
1351 int stackCount = 0;
1352 for (int i=0; i<state.stacksize; i++) {
1353 if (state.stack[i] != null) {
1354 stackCount++;
1355 }
1356 }
1357 frame.stack = new Type[stackCount];
1358 stackCount = 0;
1359 for (int i=0; i<state.stacksize; i++) {
1360 if (state.stack[i] != null) {
1361 frame.stack[stackCount++] = types.erasure(state.stack[i]);
1362 }
1363 }
1364
1365 Set<VarSymbol> unsetFieldsAtPC = cpToUnsetFieldsMap.get(pc);
1366 boolean encloseWithEarlyLarvalFrame = unsetFieldsAtPC != null && generateEarlyLarvalFrame && hasUninitalizedThis
1367 && !lastFrame.unsetFields.equals(unsetFieldsAtPC);
1368
1369 if (stackMapTableBuffer == null) {
1370 stackMapTableBuffer = new StackMapTableFrame[20];
1371 } else {
1372 stackMapTableBuffer = ArrayUtils.ensureCapacity(
1373 stackMapTableBuffer,
1374 stackMapBufferSize);
1375 }
1376
1377 StackMapTableFrame tableFrame = StackMapTableFrame.getInstance(frame, lastFrame, types, pc);
1378 if (encloseWithEarlyLarvalFrame) {
1379 tableFrame = new StackMapTableFrame.EarlyLarvalFrame(tableFrame, unsetFieldsAtPC);
1380 frame.unsetFields = unsetFieldsAtPC;
1381 } else {
1382 frame.unsetFields = lastFrame.unsetFields;
1383 }
1384 stackMapTableBuffer[stackMapBufferSize++] = tableFrame;
1385
1386 frameBeforeLast = lastFrame;
1387 lastFrame = frame;
1388 }
1389
1390 public void addUnsetFieldsAtPC(int pc, Set<VarSymbol> unsetFields) {
1391 cpToUnsetFieldsMap.put(pc, unsetFields);
1392 }
1393
1394 StackMapFrame getInitialFrame() {
1395 StackMapFrame frame = new StackMapFrame();
1396 List<Type> arg_types = ((MethodType)meth.externalType(types)).argtypes;
1397 int len = arg_types.length();
1398 int count = 0;
1399 if (!meth.isStatic()) {
1400 Type thisType = meth.owner.type;
1401 frame.locals = new Type[len+1];
1402 if (meth.isConstructor() && thisType != syms.objectType) {
1403 frame.locals[count++] = UninitializedType.uninitializedThis(thisType);
1404 } else {
1405 frame.locals[count++] = types.erasure(thisType);
1406 }
1407 } else {
1408 frame.locals = new Type[len];
1409 }
1410 for (Type arg_type : arg_types) {
1411 frame.locals[count++] = types.erasure(arg_type);
1412 }
1413 frame.pc = -1;
1414 frame.stack = null;
1415 frame.unsetFields = initialUnsetFields;
1416 return frame;
1417 }
1418
1419
1420 /* ************************************************************************
1421 * Operations having to do with jumps
1422 *************************************************************************/
1423
1424 /** A chain represents a list of unresolved jumps. Jump locations
1425 * are sorted in decreasing order.
1426 */
1427 public static class Chain {
1428
1429 /** The position of the jump instruction.
1430 */
1431 public final int pc;
1432
1433 /** The machine state after the jump instruction.
1434 * Invariant: all elements of a chain list have the same stacksize
1435 * and compatible stack and register contents.
1474 return cp - 5;
1475 } else {
1476 emitop2(opcode, 0);
1477 return cp - 3;
1478 }
1479 }
1480
1481 /** Emit a branch with given opcode; return its chain.
1482 * branch differs from jump in that jsr is treated as no-op.
1483 */
1484 public Chain branch(int opcode) {
1485 Chain result = null;
1486 if (opcode == goto_) {
1487 result = pendingJumps;
1488 pendingJumps = null;
1489 }
1490 if (opcode != dontgoto && isAlive()) {
1491 result = new Chain(emitJump(opcode),
1492 result,
1493 state.dup());
1494 if (currentUnsetFields != null) {
1495 addUnsetFieldsAtPC(result.pc, currentUnsetFields);
1496 }
1497 fixedPc = fatcode;
1498 if (opcode == goto_) alive = false;
1499 }
1500 return result;
1501 }
1502
1503 /** Resolve chain to point to given target.
1504 */
1505 public void resolve(Chain chain, int target) {
1506 boolean changed = false;
1507 State newState = state;
1508 int originalTarget = target;
1509 for (; chain != null; chain = chain.next) {
1510 Assert.check(state != chain.state
1511 && (target > chain.pc || isStatementStart()));
1512 if (target >= cp) {
1513 target = cp;
1514 } else if (get1(target) == goto_) {
1515 if (fatcode) target = target + get4(target + 1);
1516 else target = target + get2(target + 1);
1517 }
1518 if (get1(chain.pc) == goto_ &&
1519 chain.pc + 3 == target && target == cp && !fixedPc) {
1520 // If goto the next instruction, the jump is not needed:
1521 // compact the code.
1522 if (varDebugInfo) {
1523 adjustAliveRanges(cp, -3);
1524 }
1525 cp = cp - 3;
1526 target = target - 3;
1527 if (chain.next == null) {
1528 // This is the only jump to the target. Exit the loop
1529 // without setting new state. The code is reachable
1530 // from the instruction before goto_.
1531 alive = true;
1532 break;
1533 }
1534 } else {
1535 if (fatcode) {
1536 put4(chain.pc + 1, target - chain.pc);
1537 if (cpToUnsetFieldsMap.get(chain.pc) != null) {
1538 addUnsetFieldsAtPC(originalTarget, cpToUnsetFieldsMap.get(chain.pc));
1539 }
1540 }
1541 else if (target - chain.pc < Short.MIN_VALUE ||
1542 target - chain.pc > Short.MAX_VALUE)
1543 fatcode = true;
1544 else {
1545 put2(chain.pc + 1, target - chain.pc);
1546 if (cpToUnsetFieldsMap.get(chain.pc) != null) {
1547 addUnsetFieldsAtPC(originalTarget, cpToUnsetFieldsMap.get(chain.pc));
1548 }
1549 }
1550 Assert.check(!alive ||
1551 chain.state.stacksize == newState.stacksize &&
1552 chain.state.nlocks == newState.nlocks);
1553 }
1554 fixedPc = true;
1555 if (cp == target) {
1556 changed = true;
1557 if (debugCode)
1558 System.err.println("resolving chain state=" + chain.state);
1559 if (alive) {
1560 newState = chain.state.join(newState);
1561 } else {
1562 newState = chain.state;
1563 alive = true;
1564 }
1565 }
1566 }
1567 Assert.check(!changed || state != newState);
1568 if (state != newState) {
1569 setDefined(newState.defined);
|