use of com.oracle.truffle.espresso.classfile.constantpool.PoolConstant in project graal by oracle.
the class MethodVerifier method verify.
/**
* Core of the verifier. Performs verification for a single bci, according (mostly) to the JVM
* specs
*
* @param bci The bci of the opcode being verified
* @param stack The current state of the stack at the point of verification
* @param locals The current state of the local variables at the point of verification
* @return The index of the next opcode to verify, or bci if there is no next opcode to verify
* (in case of a return bytecode, for example).
*/
private int verify(int bci, OperandStack stack, Locals locals) {
verifyGuarantee(bciStates[bci] != UNREACHABLE, "Jump to the middle of an instruction: " + bci);
bciStates[bci] = setStatus(bciStates[bci], DONE);
int curOpcode;
curOpcode = code.opcode(bci);
verifyGuarantee(curOpcode < SLIM_QUICK, "invalid bytecode: " + code.readUByte(bci));
// widened instruction.
wideEscape: while (true) {
switch(curOpcode) {
case NOP:
break;
case ACONST_NULL:
stack.push(Null);
break;
case ICONST_M1:
case ICONST_0:
case ICONST_1:
case ICONST_2:
case ICONST_3:
case ICONST_4:
case ICONST_5:
stack.pushInt();
break;
case LCONST_0:
case LCONST_1:
stack.pushLong();
break;
case FCONST_0:
case FCONST_1:
case FCONST_2:
stack.pushFloat();
break;
case DCONST_0:
case DCONST_1:
stack.pushDouble();
break;
case BIPUSH:
stack.pushInt();
break;
case SIPUSH:
stack.pushInt();
break;
case LDC:
case LDC_W:
{
PoolConstant pc = poolAt(code.readCPI(bci));
pc.validate(pool);
Operand op = ldcFromTag(pc);
verifyGuarantee(!isType2(op), "Loading Long or Double with LDC or LDC_W, please use LDC2_W.");
if (earlierThan49()) {
verifyGuarantee(op == Int || op == Float || op.getType() == jlString.getType(), "Loading non Int, Float or String with LDC in classfile version < 49.0");
}
stack.push(op);
break;
}
case LDC2_W:
{
PoolConstant pc = poolAt(code.readCPI(bci));
pc.validate(pool);
Operand op = ldcFromTag(pc);
verifyGuarantee(isType2(op), "Loading non-Long or Double with LDC2_W, please use LDC or LDC_W.");
stack.push(op);
break;
}
case ILOAD:
locals.load(code.readLocalIndex(bci), Int);
stack.pushInt();
break;
case LLOAD:
locals.load(code.readLocalIndex(bci), Long);
stack.pushLong();
break;
case FLOAD:
locals.load(code.readLocalIndex(bci), Float);
stack.pushFloat();
break;
case DLOAD:
locals.load(code.readLocalIndex(bci), Double);
stack.pushDouble();
break;
case ALOAD:
stack.push(locals.loadRef(code.readLocalIndex(bci)));
break;
case ILOAD_0:
case ILOAD_1:
case ILOAD_2:
case ILOAD_3:
locals.load(curOpcode - ILOAD_0, Int);
stack.pushInt();
break;
case LLOAD_0:
case LLOAD_1:
case LLOAD_2:
case LLOAD_3:
locals.load(curOpcode - LLOAD_0, Long);
stack.pushLong();
break;
case FLOAD_0:
case FLOAD_1:
case FLOAD_2:
case FLOAD_3:
locals.load(curOpcode - FLOAD_0, Float);
stack.pushFloat();
break;
case DLOAD_0:
case DLOAD_1:
case DLOAD_2:
case DLOAD_3:
locals.load(curOpcode - DLOAD_0, Double);
stack.pushDouble();
break;
case ALOAD_0:
case ALOAD_1:
case ALOAD_2:
case ALOAD_3:
stack.push(locals.loadRef(curOpcode - ALOAD_0));
break;
case IALOAD:
xaload(stack, Int);
break;
case LALOAD:
xaload(stack, Long);
break;
case FALOAD:
xaload(stack, Float);
break;
case DALOAD:
xaload(stack, Double);
break;
case AALOAD:
{
stack.popInt();
Operand op = stack.popArray();
verifyGuarantee(op == Null || op.getComponent().isReference(), "Loading reference from " + op + " array.");
stack.push(op.getComponent());
break;
}
case BALOAD:
xaload(stack, ByteOrBoolean);
break;
case CALOAD:
xaload(stack, Char);
break;
case SALOAD:
xaload(stack, Short);
break;
case ISTORE:
stack.popInt();
locals.store(code.readLocalIndex(bci), Int);
break;
case LSTORE:
stack.popLong();
locals.store(code.readLocalIndex(bci), Long);
break;
case FSTORE:
stack.popFloat();
locals.store(code.readLocalIndex(bci), Float);
break;
case DSTORE:
stack.popDouble();
locals.store(code.readLocalIndex(bci), Double);
break;
case ASTORE:
locals.store(code.readLocalIndex(bci), stack.popObjOrRA());
break;
case ISTORE_0:
case ISTORE_1:
case ISTORE_2:
case ISTORE_3:
stack.popInt();
locals.store(curOpcode - ISTORE_0, Int);
break;
case LSTORE_0:
case LSTORE_1:
case LSTORE_2:
case LSTORE_3:
stack.popLong();
locals.store(curOpcode - LSTORE_0, Long);
break;
case FSTORE_0:
case FSTORE_1:
case FSTORE_2:
case FSTORE_3:
stack.popFloat();
locals.store(curOpcode - FSTORE_0, Float);
break;
case DSTORE_0:
case DSTORE_1:
case DSTORE_2:
case DSTORE_3:
stack.popDouble();
locals.store(curOpcode - DSTORE_0, Double);
break;
case ASTORE_0:
case ASTORE_1:
case ASTORE_2:
case ASTORE_3:
locals.store(curOpcode - ASTORE_0, stack.popObjOrRA());
break;
case IASTORE:
xastore(stack, Int);
break;
case LASTORE:
xastore(stack, Long);
break;
case FASTORE:
xastore(stack, Float);
break;
case DASTORE:
xastore(stack, Double);
break;
case AASTORE:
{
Operand toStore = stack.popRef();
stack.popInt();
Operand array = stack.popArray();
verifyGuarantee(array == Null || array.getComponent().isReference(), "Trying to store " + toStore + " in " + array);
// Other checks are done at runtime
break;
}
case BASTORE:
xastore(stack, ByteOrBoolean);
break;
case CASTORE:
xastore(stack, Char);
break;
case SASTORE:
xastore(stack, Short);
break;
case POP:
stack.pop();
break;
case POP2:
stack.pop2();
break;
case DUP:
stack.dup();
break;
case DUP_X1:
stack.dupx1();
break;
case DUP_X2:
stack.dupx2();
break;
case DUP2:
stack.dup2();
break;
case DUP2_X1:
stack.dup2x1();
break;
case DUP2_X2:
stack.dup2x2();
break;
case SWAP:
stack.swap();
break;
case IADD:
stack.popInt();
stack.popInt();
stack.pushInt();
break;
case LADD:
stack.popLong();
stack.popLong();
stack.pushLong();
break;
case FADD:
stack.popFloat();
stack.popFloat();
stack.pushFloat();
break;
case DADD:
stack.popDouble();
stack.popDouble();
stack.pushDouble();
break;
case ISUB:
stack.popInt();
stack.popInt();
stack.pushInt();
break;
case LSUB:
stack.popLong();
stack.popLong();
stack.pushLong();
break;
case FSUB:
stack.popFloat();
stack.popFloat();
stack.pushFloat();
break;
case DSUB:
stack.popDouble();
stack.popDouble();
stack.pushDouble();
break;
case IMUL:
stack.popInt();
stack.popInt();
stack.pushInt();
break;
case LMUL:
stack.popLong();
stack.popLong();
stack.pushLong();
break;
case FMUL:
stack.popFloat();
stack.popFloat();
stack.pushFloat();
break;
case DMUL:
stack.popDouble();
stack.popDouble();
stack.pushDouble();
break;
case IDIV:
stack.popInt();
stack.popInt();
stack.pushInt();
break;
case LDIV:
stack.popLong();
stack.popLong();
stack.pushLong();
break;
case FDIV:
stack.popFloat();
stack.popFloat();
stack.pushFloat();
break;
case DDIV:
stack.popDouble();
stack.popDouble();
stack.pushDouble();
break;
case IREM:
stack.popInt();
stack.popInt();
stack.pushInt();
break;
case LREM:
stack.popLong();
stack.popLong();
stack.pushLong();
break;
case FREM:
stack.popFloat();
stack.popFloat();
stack.pushFloat();
break;
case DREM:
stack.popDouble();
stack.popDouble();
stack.pushDouble();
break;
case INEG:
stack.popInt();
stack.pushInt();
break;
case LNEG:
stack.popLong();
stack.pushLong();
break;
case FNEG:
stack.popFloat();
stack.pushFloat();
break;
case DNEG:
stack.popDouble();
stack.pushDouble();
break;
case ISHL:
stack.popInt();
stack.popInt();
stack.pushInt();
break;
case LSHL:
stack.popInt();
stack.popLong();
stack.pushLong();
break;
case ISHR:
stack.popInt();
stack.popInt();
stack.pushInt();
break;
case LSHR:
stack.popInt();
stack.popLong();
stack.pushLong();
break;
case IUSHR:
stack.popInt();
stack.popInt();
stack.pushInt();
break;
case LUSHR:
stack.popInt();
stack.popLong();
stack.pushLong();
break;
case IAND:
stack.popInt();
stack.popInt();
stack.pushInt();
break;
case LAND:
stack.popLong();
stack.popLong();
stack.pushLong();
break;
case IOR:
stack.popInt();
stack.popInt();
stack.pushInt();
break;
case LOR:
stack.popLong();
stack.popLong();
stack.pushLong();
break;
case IXOR:
stack.popInt();
stack.popInt();
stack.pushInt();
break;
case LXOR:
stack.popLong();
stack.popLong();
stack.pushLong();
break;
case IINC:
locals.load(code.readLocalIndex(bci), Int);
break;
case I2L:
stack.popInt();
stack.pushLong();
break;
case I2F:
stack.popInt();
stack.pushFloat();
break;
case I2D:
stack.popInt();
stack.pushDouble();
break;
case L2I:
stack.popLong();
stack.pushInt();
break;
case L2F:
stack.popLong();
stack.pushFloat();
break;
case L2D:
stack.popLong();
stack.pushDouble();
break;
case F2I:
stack.popFloat();
stack.pushInt();
break;
case F2L:
stack.popFloat();
stack.pushLong();
break;
case F2D:
stack.popFloat();
stack.pushDouble();
break;
case D2I:
stack.popDouble();
stack.pushInt();
break;
case D2L:
stack.popDouble();
stack.pushLong();
break;
case D2F:
stack.popDouble();
stack.pushFloat();
break;
case I2B:
stack.popInt();
stack.pushInt();
break;
case I2C:
stack.popInt();
stack.pushInt();
break;
case I2S:
stack.popInt();
stack.pushInt();
break;
case LCMP:
stack.popLong();
stack.popLong();
stack.pushInt();
break;
case FCMPL:
case FCMPG:
stack.popFloat();
stack.popFloat();
stack.pushInt();
break;
case DCMPL:
case DCMPG:
stack.popDouble();
stack.popDouble();
stack.pushInt();
break;
// fall through
case IFEQ:
// fall through
case IFNE:
// fall through
case IFLT:
// fall through
case IFGE:
// fall through
case IFGT:
case IFLE:
stack.popInt();
branch(code.readBranchDest(bci), stack, locals);
break;
// fall through
case IF_ICMPEQ:
// fall through
case IF_ICMPNE:
// fall through
case IF_ICMPLT:
// fall through
case IF_ICMPGE:
// fall through
case IF_ICMPGT:
case IF_ICMPLE:
stack.popInt();
stack.popInt();
branch(code.readBranchDest(bci), stack, locals);
break;
// fall through
case IF_ACMPEQ:
case IF_ACMPNE:
stack.popRef();
stack.popRef();
branch(code.readBranchDest(bci), stack, locals);
break;
case GOTO:
case GOTO_W:
branch(code.readBranchDest(bci), stack, locals);
return bci;
// fall through
case IFNULL:
case IFNONNULL:
stack.popRef();
branch(code.readBranchDest(bci), stack, locals);
break;
// fall through
case JSR:
case JSR_W:
verifyJSR(bci, stack, locals);
return bci;
case RET:
verifyRET(bci, stack, locals);
return bci;
case TABLESWITCH:
return verifyTableSwitch(bci, stack, locals);
case LOOKUPSWITCH:
return verifyLookupSwitch(bci, stack, locals);
case IRETURN:
{
stack.pop(Int);
verifyGuarantee(returnOperand.getKind().isStackInt(), "Found an IRETURN when return type is " + returnOperand);
return bci;
}
case LRETURN:
doReturn(stack, Long);
return bci;
case FRETURN:
doReturn(stack, Float);
return bci;
case DRETURN:
doReturn(stack, Double);
return bci;
case ARETURN:
stack.popRef(returnOperand);
return bci;
case RETURN:
verifyGuarantee(returnOperand == Void, "Encountered RETURN, but method return type is not void: " + returnOperand);
// Only j.l.Object.<init> can omit calling another initializer.
if (isInstanceInit(methodName) && thisKlass.getType() != Type.java_lang_Object) {
verifyGuarantee(calledConstructor, "Did not call super() or this() in constructor " + thisKlass.getType() + "." + methodName);
}
return bci;
case GETSTATIC:
case GETFIELD:
verifyGetField(bci, stack, curOpcode);
break;
case PUTSTATIC:
case PUTFIELD:
verifyPutField(bci, stack, curOpcode);
break;
case INVOKEVIRTUAL:
verifyInvokeVirtual(bci, stack);
break;
case INVOKESPECIAL:
verifyInvokeSpecial(bci, stack, locals);
break;
case INVOKESTATIC:
verifyInvokeStatic(bci, stack);
break;
case INVOKEINTERFACE:
verifyInvokeInterface(bci, stack);
break;
case NEW:
verifyNew(bci, stack);
break;
case NEWARRAY:
verifyNewPrimitiveArray(bci, stack);
break;
case ANEWARRAY:
verifyNewObjectArray(bci, stack);
break;
case ARRAYLENGTH:
stack.popArray();
stack.pushInt();
break;
case ATHROW:
stack.popRef(jlThrowable);
return bci;
case CHECKCAST:
verifyCheckCast(bci, stack);
break;
case INSTANCEOF:
verifyInstanceOf(bci, stack);
break;
case MONITORENTER:
stack.popRef();
break;
case MONITOREXIT:
stack.popRef();
break;
case WIDE:
curOpcode = code.currentBC(bci);
verifyGuarantee(wideOpcodes(curOpcode), "invalid widened opcode: " + Bytecodes.nameOf(curOpcode));
continue wideEscape;
case MULTIANEWARRAY:
verifyMultiNewArray(bci, stack);
break;
case BREAKPOINT:
break;
case INVOKEDYNAMIC:
verifyInvokeDynamic(bci, stack);
break;
case QUICK:
break;
case SLIM_QUICK:
break;
default:
}
return code.nextBCI(bci);
}
// Checkstyle: resume
// @formatter:on
}
Aggregations