machine.clearArgs();
checkReturnType(Type.VOID);
break;
}
case ByteOps.IRETURN: {
Type checkType = type;
if (type == Type.OBJECT) {
/*
* For an object return, use the best-known
* type of the popped value.
*/
checkType = frame.getStack().peekType(0);
}
machine.popArgs(frame, type);
checkReturnType(checkType);
break;
}
case ByteOps.POP: {
Type peekType = frame.getStack().peekType(0);
if (peekType.isCategory2()) {
throw illegalTos();
}
machine.popArgs(frame, 1);
break;
}
case ByteOps.ARRAYLENGTH: {
Type arrayType = frame.getStack().peekType(0);
if (!arrayType.isArrayOrKnownNull()) {
throw new SimException("type mismatch: expected " +
"array type but encountered " +
arrayType.toHuman());
}
machine.popArgs(frame, Type.OBJECT);
break;
}
case ByteOps.ATHROW:
case ByteOps.MONITORENTER:
case ByteOps.MONITOREXIT: {
machine.popArgs(frame, Type.OBJECT);
break;
}
case ByteOps.IALOAD: {
/*
* Change the type (which is to be pushed) to
* reflect the actual component type of the array
* being popped, unless it turns out to be a
* known-null, in which case we just use the type
* implied by the original instruction.
*/
Type foundArrayType = frame.getStack().peekType(1);
Type requireArrayType;
if (foundArrayType != Type.KNOWN_NULL) {
requireArrayType = foundArrayType;
type = foundArrayType.getComponentType();
} else {
requireArrayType = type.getArrayType();
}
machine.popArgs(frame, requireArrayType, Type.INT);
break;
}
case ByteOps.IADD:
case ByteOps.ISUB:
case ByteOps.IMUL:
case ByteOps.IDIV:
case ByteOps.IREM:
case ByteOps.IAND:
case ByteOps.IOR:
case ByteOps.IXOR: {
machine.popArgs(frame, type, type);
break;
}
case ByteOps.ISHL:
case ByteOps.ISHR:
case ByteOps.IUSHR: {
machine.popArgs(frame, type, Type.INT);
break;
}
case ByteOps.LCMP: {
machine.popArgs(frame, Type.LONG, Type.LONG);
break;
}
case ByteOps.FCMPL:
case ByteOps.FCMPG: {
machine.popArgs(frame, Type.FLOAT, Type.FLOAT);
break;
}
case ByteOps.DCMPL:
case ByteOps.DCMPG: {
machine.popArgs(frame, Type.DOUBLE, Type.DOUBLE);
break;
}
case ByteOps.IASTORE: {
/*
* Change the type (which is the type of the
* element) to reflect the actual component type
* of the array being popped, unless it turns out
* to be a known-null, in which case we just use
* the type implied by the original instruction.
* The category 1 vs. 2 thing here is that, if the
* element type is category 2, we have to skip over
* one extra stack slot to find the array.
*/
Type foundArrayType =
frame.getStack().peekType(type.isCategory1() ? 2 : 3);
Type requireArrayType;
if (foundArrayType != Type.KNOWN_NULL) {
requireArrayType = foundArrayType;
type = foundArrayType.getComponentType();
} else {
requireArrayType = type.getArrayType();
}
machine.popArgs(frame, requireArrayType, Type.INT, type);
break;
}
case ByteOps.POP2:
case ByteOps.DUP2: {
ExecutionStack stack = frame.getStack();
int pattern;
if (stack.peekType(0).isCategory2()) {
// "form 2" in vmspec-2
machine.popArgs(frame, 1);
pattern = 0x11;
} else if (stack.peekType(1).isCategory1()) {
// "form 1"
machine.popArgs(frame, 2);
pattern = 0x2121;
} else {
throw illegalTos();
}
if (opcode == ByteOps.DUP2) {
machine.auxIntArg(pattern);
}
break;
}
case ByteOps.DUP: {
Type peekType = frame.getStack().peekType(0);
if (peekType.isCategory2()) {
throw illegalTos();
}
machine.popArgs(frame, 1);
machine.auxIntArg(0x11);