use of com.oracle.truffle.espresso.meta.ExceptionHandler in project graal by oracle.
the class BytecodeNode method executeBodyFromBCI.
@ExplodeLoop(kind = ExplodeLoop.LoopExplosionKind.MERGE_EXPLODE)
Object executeBodyFromBCI(VirtualFrame frame, int startBCI, int startTop, int startStatementIndex, boolean startSkipEntryInstrumentation) {
CompilerAsserts.partialEvaluationConstant(startBCI);
int curBCI = startBCI;
int top = startTop;
final InstrumentationSupport instrument = this.instrumentation;
int statementIndex = InstrumentationSupport.NO_STATEMENT;
int nextStatementIndex = startStatementIndex;
boolean skipEntryInstrumentation = startSkipEntryInstrumentation;
// so force the initialization here
if (!frame.isInt(EspressoFrame.BCI_SLOT)) {
initializeBody(frame);
}
final Counter loopCount = new Counter();
setBCI(frame, curBCI);
if (instrument != null && !skipEntryInstrumentation) {
instrument.notifyEntry(frame, this);
}
// the method from the beginning hence onStart is not applicable
if (startBCI == 0) {
livenessAnalysis.onStart(frame);
}
loop: while (true) {
final int curOpcode = bs.opcode(curBCI);
EXECUTED_BYTECODES_COUNT.inc();
try {
CompilerAsserts.partialEvaluationConstant(top);
CompilerAsserts.partialEvaluationConstant(curBCI);
CompilerAsserts.partialEvaluationConstant(skipEntryInstrumentation);
CompilerAsserts.partialEvaluationConstant(curOpcode);
CompilerAsserts.partialEvaluationConstant(statementIndex);
CompilerAsserts.partialEvaluationConstant(nextStatementIndex);
if (instrument != null || Bytecodes.canTrap(curOpcode)) {
/*
* curOpcode can be == WIDE, but none of the WIDE-prefixed bytecodes throw
* exceptions.
*/
setBCI(frame, curBCI);
}
if (instrument != null) {
if (!skipEntryInstrumentation) {
instrument.notifyStatement(frame, statementIndex, nextStatementIndex);
}
skipEntryInstrumentation = false;
statementIndex = nextStatementIndex;
}
// @formatter:off
switch(curOpcode) {
case NOP:
break;
case ACONST_NULL:
putObject(frame, top, StaticObject.NULL);
break;
// fall through
case ICONST_M1:
// fall through
case ICONST_0:
// fall through
case ICONST_1:
// fall through
case ICONST_2:
// fall through
case ICONST_3:
// fall through
case ICONST_4:
case ICONST_5:
putInt(frame, top, curOpcode - ICONST_0);
break;
// fall through
case LCONST_0:
case LCONST_1:
putLong(frame, top, curOpcode - LCONST_0);
break;
// fall through
case FCONST_0:
// fall through
case FCONST_1:
case FCONST_2:
putFloat(frame, top, curOpcode - FCONST_0);
break;
// fall through
case DCONST_0:
case DCONST_1:
putDouble(frame, top, curOpcode - DCONST_0);
break;
case BIPUSH:
putInt(frame, top, bs.readByte(curBCI));
break;
case SIPUSH:
putInt(frame, top, bs.readShort(curBCI));
break;
// fall through
case LDC:
// fall through
case LDC_W:
case LDC2_W:
putPoolConstant(frame, top, readCPI(curBCI), curOpcode);
break;
case ILOAD:
putInt(frame, top, getLocalInt(frame, bs.readLocalIndex(curBCI)));
livenessAnalysis.performPostBCI(frame, curBCI);
break;
case LLOAD:
putLong(frame, top, getLocalLong(frame, bs.readLocalIndex(curBCI)));
livenessAnalysis.performPostBCI(frame, curBCI);
break;
case FLOAD:
putFloat(frame, top, getLocalFloat(frame, bs.readLocalIndex(curBCI)));
livenessAnalysis.performPostBCI(frame, curBCI);
break;
case DLOAD:
putDouble(frame, top, getLocalDouble(frame, bs.readLocalIndex(curBCI)));
livenessAnalysis.performPostBCI(frame, curBCI);
break;
case ALOAD:
putObject(frame, top, getLocalObject(frame, bs.readLocalIndex(curBCI)));
livenessAnalysis.performPostBCI(frame, curBCI);
break;
// fall through
case ILOAD_0:
// fall through
case ILOAD_1:
// fall through
case ILOAD_2:
case ILOAD_3:
putInt(frame, top, getLocalInt(frame, curOpcode - ILOAD_0));
livenessAnalysis.performPostBCI(frame, curBCI);
break;
// fall through
case LLOAD_0:
// fall through
case LLOAD_1:
// fall through
case LLOAD_2:
case LLOAD_3:
putLong(frame, top, getLocalLong(frame, curOpcode - LLOAD_0));
livenessAnalysis.performPostBCI(frame, curBCI);
break;
// fall through
case FLOAD_0:
// fall through
case FLOAD_1:
// fall through
case FLOAD_2:
case FLOAD_3:
putFloat(frame, top, getLocalFloat(frame, curOpcode - FLOAD_0));
livenessAnalysis.performPostBCI(frame, curBCI);
break;
// fall through
case DLOAD_0:
// fall through
case DLOAD_1:
// fall through
case DLOAD_2:
case DLOAD_3:
putDouble(frame, top, getLocalDouble(frame, curOpcode - DLOAD_0));
livenessAnalysis.performPostBCI(frame, curBCI);
break;
case ALOAD_0:
putObject(frame, top, getLocalObject(frame, 0));
livenessAnalysis.performPostBCI(frame, curBCI);
break;
// fall through
case ALOAD_1:
// fall through
case ALOAD_2:
case ALOAD_3:
putObject(frame, top, getLocalObject(frame, curOpcode - ALOAD_0));
livenessAnalysis.performPostBCI(frame, curBCI);
break;
// fall through
case IALOAD:
// fall through
case LALOAD:
// fall through
case FALOAD:
// fall through
case DALOAD:
// fall through
case BALOAD:
// fall through
case CALOAD:
case SALOAD:
arrayLoad(frame, top, curBCI, curOpcode);
break;
case AALOAD:
arrayLoad(frame, top, curBCI, AALOAD);
checkNoForeignObjectAssumption(peekObject(frame, top - 2));
break;
case ISTORE:
setLocalInt(frame, bs.readLocalIndex(curBCI), popInt(frame, top - 1));
livenessAnalysis.performPostBCI(frame, curBCI);
break;
case LSTORE:
setLocalLong(frame, bs.readLocalIndex(curBCI), popLong(frame, top - 1));
livenessAnalysis.performPostBCI(frame, curBCI);
break;
case FSTORE:
setLocalFloat(frame, bs.readLocalIndex(curBCI), popFloat(frame, top - 1));
livenessAnalysis.performPostBCI(frame, curBCI);
break;
case DSTORE:
setLocalDouble(frame, bs.readLocalIndex(curBCI), popDouble(frame, top - 1));
livenessAnalysis.performPostBCI(frame, curBCI);
break;
case ASTORE:
setLocalObjectOrReturnAddress(frame, bs.readLocalIndex(curBCI), popReturnAddressOrObject(frame, top - 1));
livenessAnalysis.performPostBCI(frame, curBCI);
break;
// fall through
case ISTORE_0:
// fall through
case ISTORE_1:
// fall through
case ISTORE_2:
case ISTORE_3:
setLocalInt(frame, curOpcode - ISTORE_0, popInt(frame, top - 1));
livenessAnalysis.performPostBCI(frame, curBCI);
break;
// fall through
case LSTORE_0:
// fall through
case LSTORE_1:
// fall through
case LSTORE_2:
case LSTORE_3:
setLocalLong(frame, curOpcode - LSTORE_0, popLong(frame, top - 1));
livenessAnalysis.performPostBCI(frame, curBCI);
break;
// fall through
case FSTORE_0:
// fall through
case FSTORE_1:
// fall through
case FSTORE_2:
case FSTORE_3:
setLocalFloat(frame, curOpcode - FSTORE_0, popFloat(frame, top - 1));
livenessAnalysis.performPostBCI(frame, curBCI);
break;
// fall through
case DSTORE_0:
// fall through
case DSTORE_1:
// fall through
case DSTORE_2:
case DSTORE_3:
setLocalDouble(frame, curOpcode - DSTORE_0, popDouble(frame, top - 1));
livenessAnalysis.performPostBCI(frame, curBCI);
break;
// fall through
case ASTORE_0:
// fall through
case ASTORE_1:
// fall through
case ASTORE_2:
case ASTORE_3:
setLocalObjectOrReturnAddress(frame, curOpcode - ASTORE_0, popReturnAddressOrObject(frame, top - 1));
livenessAnalysis.performPostBCI(frame, curBCI);
break;
// fall through
case IASTORE:
// fall through
case LASTORE:
// fall through
case FASTORE:
// fall through
case DASTORE:
// fall through
case AASTORE:
// fall through
case BASTORE:
// fall through
case CASTORE:
case SASTORE:
arrayStore(frame, top, curBCI, curOpcode);
break;
case POP2:
clear(frame, top - 1);
clear(frame, top - 2);
break;
case POP:
clear(frame, top - 1);
break;
// TODO(peterssen): Stack shuffling is expensive.
case DUP:
EspressoFrame.dup1(frame, top);
break;
case DUP_X1:
EspressoFrame.dupx1(frame, top);
break;
case DUP_X2:
EspressoFrame.dupx2(frame, top);
break;
case DUP2:
EspressoFrame.dup2(frame, top);
break;
case DUP2_X1:
EspressoFrame.dup2x1(frame, top);
break;
case DUP2_X2:
EspressoFrame.dup2x2(frame, top);
break;
case SWAP:
EspressoFrame.swapSingle(frame, top);
break;
case IADD:
putInt(frame, top - 2, popInt(frame, top - 1) + popInt(frame, top - 2));
break;
case LADD:
putLong(frame, top - 4, popLong(frame, top - 1) + popLong(frame, top - 3));
break;
case FADD:
putFloat(frame, top - 2, popFloat(frame, top - 1) + popFloat(frame, top - 2));
break;
case DADD:
putDouble(frame, top - 4, popDouble(frame, top - 1) + popDouble(frame, top - 3));
break;
case ISUB:
putInt(frame, top - 2, popInt(frame, top - 2) - popInt(frame, top - 1));
break;
case LSUB:
putLong(frame, top - 4, popLong(frame, top - 3) - popLong(frame, top - 1));
break;
case FSUB:
putFloat(frame, top - 2, popFloat(frame, top - 2) - popFloat(frame, top - 1));
break;
case DSUB:
putDouble(frame, top - 4, popDouble(frame, top - 3) - popDouble(frame, top - 1));
break;
case IMUL:
putInt(frame, top - 2, popInt(frame, top - 1) * popInt(frame, top - 2));
break;
case LMUL:
putLong(frame, top - 4, popLong(frame, top - 1) * popLong(frame, top - 3));
break;
case FMUL:
putFloat(frame, top - 2, popFloat(frame, top - 1) * popFloat(frame, top - 2));
break;
case DMUL:
putDouble(frame, top - 4, popDouble(frame, top - 1) * popDouble(frame, top - 3));
break;
case IDIV:
putInt(frame, top - 2, divInt(checkNonZero(popInt(frame, top - 1)), popInt(frame, top - 2)));
break;
case LDIV:
putLong(frame, top - 4, divLong(checkNonZero(popLong(frame, top - 1)), popLong(frame, top - 3)));
break;
case FDIV:
putFloat(frame, top - 2, divFloat(popFloat(frame, top - 1), popFloat(frame, top - 2)));
break;
case DDIV:
putDouble(frame, top - 4, divDouble(popDouble(frame, top - 1), popDouble(frame, top - 3)));
break;
case IREM:
putInt(frame, top - 2, remInt(checkNonZero(popInt(frame, top - 1)), popInt(frame, top - 2)));
break;
case LREM:
putLong(frame, top - 4, remLong(checkNonZero(popLong(frame, top - 1)), popLong(frame, top - 3)));
break;
case FREM:
putFloat(frame, top - 2, remFloat(popFloat(frame, top - 1), popFloat(frame, top - 2)));
break;
case DREM:
putDouble(frame, top - 4, remDouble(popDouble(frame, top - 1), popDouble(frame, top - 3)));
break;
case INEG:
putInt(frame, top - 1, -popInt(frame, top - 1));
break;
case LNEG:
putLong(frame, top - 2, -popLong(frame, top - 1));
break;
case FNEG:
putFloat(frame, top - 1, -popFloat(frame, top - 1));
break;
case DNEG:
putDouble(frame, top - 2, -popDouble(frame, top - 1));
break;
case ISHL:
putInt(frame, top - 2, shiftLeftInt(popInt(frame, top - 1), popInt(frame, top - 2)));
break;
case LSHL:
putLong(frame, top - 3, shiftLeftLong(popInt(frame, top - 1), popLong(frame, top - 2)));
break;
case ISHR:
putInt(frame, top - 2, shiftRightSignedInt(popInt(frame, top - 1), popInt(frame, top - 2)));
break;
case LSHR:
putLong(frame, top - 3, shiftRightSignedLong(popInt(frame, top - 1), popLong(frame, top - 2)));
break;
case IUSHR:
putInt(frame, top - 2, shiftRightUnsignedInt(popInt(frame, top - 1), popInt(frame, top - 2)));
break;
case LUSHR:
putLong(frame, top - 3, shiftRightUnsignedLong(popInt(frame, top - 1), popLong(frame, top - 2)));
break;
case IAND:
putInt(frame, top - 2, popInt(frame, top - 1) & popInt(frame, top - 2));
break;
case LAND:
putLong(frame, top - 4, popLong(frame, top - 1) & popLong(frame, top - 3));
break;
case IOR:
putInt(frame, top - 2, popInt(frame, top - 1) | popInt(frame, top - 2));
break;
case LOR:
putLong(frame, top - 4, popLong(frame, top - 1) | popLong(frame, top - 3));
break;
case IXOR:
putInt(frame, top - 2, popInt(frame, top - 1) ^ popInt(frame, top - 2));
break;
case LXOR:
putLong(frame, top - 4, popLong(frame, top - 1) ^ popLong(frame, top - 3));
break;
case IINC:
setLocalInt(frame, bs.readLocalIndex1(curBCI), getLocalInt(frame, bs.readLocalIndex1(curBCI)) + bs.readIncrement1(curBCI));
livenessAnalysis.performPostBCI(frame, curBCI);
break;
case I2L:
putLong(frame, top - 1, popInt(frame, top - 1));
break;
case I2F:
putFloat(frame, top - 1, popInt(frame, top - 1));
break;
case I2D:
putDouble(frame, top - 1, popInt(frame, top - 1));
break;
case L2I:
putInt(frame, top - 2, (int) popLong(frame, top - 1));
break;
case L2F:
putFloat(frame, top - 2, popLong(frame, top - 1));
break;
case L2D:
putDouble(frame, top - 2, popLong(frame, top - 1));
break;
case F2I:
putInt(frame, top - 1, (int) popFloat(frame, top - 1));
break;
case F2L:
putLong(frame, top - 1, (long) popFloat(frame, top - 1));
break;
case F2D:
putDouble(frame, top - 1, popFloat(frame, top - 1));
break;
case D2I:
putInt(frame, top - 2, (int) popDouble(frame, top - 1));
break;
case D2L:
putLong(frame, top - 2, (long) popDouble(frame, top - 1));
break;
case D2F:
putFloat(frame, top - 2, (float) popDouble(frame, top - 1));
break;
case I2B:
putInt(frame, top - 1, (byte) popInt(frame, top - 1));
break;
case I2C:
putInt(frame, top - 1, (char) popInt(frame, top - 1));
break;
case I2S:
putInt(frame, top - 1, (short) popInt(frame, top - 1));
break;
case LCMP:
putInt(frame, top - 4, compareLong(popLong(frame, top - 1), popLong(frame, top - 3)));
break;
case FCMPL:
putInt(frame, top - 2, compareFloatLess(popFloat(frame, top - 1), popFloat(frame, top - 2)));
break;
case FCMPG:
putInt(frame, top - 2, compareFloatGreater(popFloat(frame, top - 1), popFloat(frame, top - 2)));
break;
case DCMPL:
putInt(frame, top - 4, compareDoubleLess(popDouble(frame, top - 1), popDouble(frame, top - 3)));
break;
case DCMPG:
putInt(frame, top - 4, compareDoubleGreater(popDouble(frame, top - 1), popDouble(frame, top - 3)));
break;
// fall through
case IFEQ:
// fall through
case IFNE:
// fall through
case IFLT:
// fall through
case IFGE:
// fall through
case IFGT:
case // fall through
IFLE:
if (takeBranchPrimitive1(popInt(frame, top - 1), curOpcode)) {
int targetBCI = bs.readBranchDest2(curBCI);
top += Bytecodes.stackEffectOf(IFLE);
nextStatementIndex = beforeJumpChecks(frame, curBCI, targetBCI, top, statementIndex, instrument, loopCount);
curBCI = targetBCI;
continue loop;
}
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:
if (takeBranchPrimitive2(popInt(frame, top - 1), popInt(frame, top - 2), curOpcode)) {
top += Bytecodes.stackEffectOf(IF_ICMPLE);
nextStatementIndex = beforeJumpChecks(frame, curBCI, bs.readBranchDest2(curBCI), top, statementIndex, instrument, loopCount);
curBCI = bs.readBranchDest2(curBCI);
continue loop;
}
break;
// fall through
case IF_ACMPEQ:
case IF_ACMPNE:
if (takeBranchRef2(popObject(frame, top - 1), popObject(frame, top - 2), curOpcode)) {
int targetBCI = bs.readBranchDest2(curBCI);
top += Bytecodes.stackEffectOf(IF_ACMPNE);
nextStatementIndex = beforeJumpChecks(frame, curBCI, targetBCI, top, statementIndex, instrument, loopCount);
curBCI = targetBCI;
continue loop;
}
break;
// fall through
case IFNULL:
case IFNONNULL:
if (takeBranchRef1(popObject(frame, top - 1), curOpcode)) {
int targetBCI = bs.readBranchDest2(curBCI);
top += Bytecodes.stackEffectOf(IFNONNULL);
nextStatementIndex = beforeJumpChecks(frame, curBCI, targetBCI, top, statementIndex, instrument, loopCount);
curBCI = targetBCI;
continue loop;
}
break;
case GOTO:
{
int targetBCI = bs.readBranchDest2(curBCI);
nextStatementIndex = beforeJumpChecks(frame, curBCI, targetBCI, top, statementIndex, instrument, loopCount);
curBCI = targetBCI;
continue loop;
}
case GOTO_W:
{
int targetBCI = bs.readBranchDest4(curBCI);
nextStatementIndex = beforeJumpChecks(frame, curBCI, targetBCI, top, statementIndex, instrument, loopCount);
curBCI = targetBCI;
continue loop;
}
case JSR:
{
putReturnAddress(frame, top, bs.nextBCI(curBCI));
int targetBCI = bs.readBranchDest2(curBCI);
top += Bytecodes.stackEffectOf(JSR);
nextStatementIndex = beforeJumpChecks(frame, curBCI, targetBCI, top, statementIndex, instrument, loopCount);
curBCI = targetBCI;
continue loop;
}
case JSR_W:
{
putReturnAddress(frame, top, bs.nextBCI(curBCI));
int targetBCI = bs.readBranchDest4(curBCI);
top += Bytecodes.stackEffectOf(JSR_W);
nextStatementIndex = beforeJumpChecks(frame, curBCI, targetBCI, top, statementIndex, instrument, loopCount);
curBCI = targetBCI;
continue loop;
}
case RET:
{
int targetBCI = getLocalReturnAddress(frame, bs.readLocalIndex1(curBCI));
livenessAnalysis.performPostBCI(frame, curBCI);
if (jsrBci == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
jsrBci = new int[bs.endBCI()][];
}
if (jsrBci[curBCI] == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
jsrBci[curBCI] = new int[] { targetBCI };
}
for (int jsr : jsrBci[curBCI]) {
if (jsr == targetBCI) {
CompilerAsserts.partialEvaluationConstant(jsr);
targetBCI = jsr;
top += Bytecodes.stackEffectOf(RET);
nextStatementIndex = beforeJumpChecks(frame, curBCI, targetBCI, top, statementIndex, instrument, loopCount);
curBCI = targetBCI;
continue loop;
}
}
CompilerDirectives.transferToInterpreterAndInvalidate();
jsrBci[curBCI] = Arrays.copyOf(jsrBci[curBCI], jsrBci[curBCI].length + 1);
jsrBci[curBCI][jsrBci[curBCI].length - 1] = targetBCI;
top += Bytecodes.stackEffectOf(RET);
nextStatementIndex = beforeJumpChecks(frame, curBCI, targetBCI, top, statementIndex, instrument, loopCount);
curBCI = targetBCI;
continue loop;
}
case TABLESWITCH:
{
int index = popInt(frame, top - 1);
BytecodeTableSwitch switchHelper = BytecodeTableSwitch.INSTANCE;
int low = switchHelper.lowKey(bs, curBCI);
int high = switchHelper.highKey(bs, curBCI);
assert low <= high;
// Interpreter uses direct lookup.
if (CompilerDirectives.inInterpreter()) {
int targetBCI;
if (low <= index && index <= high) {
targetBCI = switchHelper.targetAt(bs, curBCI, index - low);
} else {
targetBCI = switchHelper.defaultTarget(bs, curBCI);
}
top += Bytecodes.stackEffectOf(TABLESWITCH);
nextStatementIndex = beforeJumpChecks(frame, curBCI, targetBCI, top, statementIndex, instrument, loopCount);
curBCI = targetBCI;
continue loop;
}
// This loops take that into account.
for (int i = low; i != high + 1; ++i) {
if (i == index) {
// Key found.
int targetBCI = switchHelper.targetAt(bs, curBCI, i - low);
top += Bytecodes.stackEffectOf(TABLESWITCH);
nextStatementIndex = beforeJumpChecks(frame, curBCI, targetBCI, top, statementIndex, instrument, loopCount);
curBCI = targetBCI;
continue loop;
}
}
// Key not found.
int targetBCI = switchHelper.defaultTarget(bs, curBCI);
top += Bytecodes.stackEffectOf(TABLESWITCH);
nextStatementIndex = beforeJumpChecks(frame, curBCI, targetBCI, top, statementIndex, instrument, loopCount);
curBCI = targetBCI;
continue loop;
}
case LOOKUPSWITCH:
{
int key = popInt(frame, top - 1);
BytecodeLookupSwitch switchHelper = BytecodeLookupSwitch.INSTANCE;
int low = 0;
int high = switchHelper.numberOfCases(bs, curBCI) - 1;
while (low <= high) {
int mid = (low + high) >>> 1;
int midVal = switchHelper.keyAt(bs, curBCI, mid);
if (midVal < key) {
low = mid + 1;
} else if (midVal > key) {
high = mid - 1;
} else {
// Key found.
int targetBCI = curBCI + switchHelper.offsetAt(bs, curBCI, mid);
top += Bytecodes.stackEffectOf(LOOKUPSWITCH);
nextStatementIndex = beforeJumpChecks(frame, curBCI, targetBCI, top, statementIndex, instrument, loopCount);
curBCI = targetBCI;
continue loop;
}
}
// Key not found.
int targetBCI = switchHelper.defaultTarget(bs, curBCI);
top += Bytecodes.stackEffectOf(LOOKUPSWITCH);
nextStatementIndex = beforeJumpChecks(frame, curBCI, targetBCI, top, statementIndex, instrument, loopCount);
curBCI = targetBCI;
continue loop;
}
// fall through
case IRETURN:
// fall through
case LRETURN:
// fall through
case FRETURN:
// fall through
case DRETURN:
// fall through
case ARETURN:
case RETURN:
{
if (CompilerDirectives.hasNextTier() && loopCount.value > 0) {
LoopNode.reportLoopCount(this, loopCount.value);
}
Object returnValue = getReturnValueAsObject(frame, top);
if (instrument != null) {
instrument.notifyReturn(frame, statementIndex, returnValue);
}
return returnValue;
}
// fall through
case GETSTATIC:
case GETFIELD:
top += getField(frame, top, resolveField(curOpcode, /* Quickenable -> read from original code for thread safety */
readOriginalCPI(curBCI)), curBCI, curOpcode, statementIndex);
break;
// fall through
case PUTSTATIC:
case PUTFIELD:
top += putField(frame, top, resolveField(curOpcode, /* Quickenable -> read from original code for thread safety */
readOriginalCPI(curBCI)), curBCI, curOpcode, statementIndex);
break;
// fall through
case INVOKEVIRTUAL:
// fall through
case INVOKESPECIAL:
// fall through
case INVOKESTATIC:
case INVOKEINTERFACE:
top += quickenInvoke(frame, top, curBCI, curOpcode, statementIndex);
break;
case NEW:
putObject(frame, top, InterpreterToVM.newObject(resolveType(NEW, readCPI(curBCI)), true));
break;
case NEWARRAY:
putObject(frame, top - 1, InterpreterToVM.allocatePrimitiveArray(bs.readByte(curBCI), popInt(frame, top - 1), getMeta(), this));
break;
case ANEWARRAY:
putObject(frame, top - 1, InterpreterToVM.newReferenceArray(resolveType(ANEWARRAY, readCPI(curBCI)), popInt(frame, top - 1), this));
break;
case ARRAYLENGTH:
arrayLength(frame, top, curBCI);
break;
case ATHROW:
throw getMeta().throwException(nullCheck(popObject(frame, top - 1)));
case CHECKCAST:
top += quickenCheckCast(frame, top, curBCI, CHECKCAST);
break;
case INSTANCEOF:
top += quickenInstanceOf(frame, top, curBCI, INSTANCEOF);
break;
case MONITORENTER:
getRoot().monitorEnter(frame, nullCheck(popObject(frame, top - 1)));
break;
case MONITOREXIT:
getRoot().monitorExit(frame, nullCheck(popObject(frame, top - 1)));
break;
case WIDE:
{
int wideOpcode = bs.opcode(curBCI + 1);
switch(wideOpcode) {
case ILOAD:
putInt(frame, top, getLocalInt(frame, bs.readLocalIndex2(curBCI)));
break;
case LLOAD:
putLong(frame, top, getLocalLong(frame, bs.readLocalIndex2(curBCI)));
break;
case FLOAD:
putFloat(frame, top, getLocalFloat(frame, bs.readLocalIndex2(curBCI)));
break;
case DLOAD:
putDouble(frame, top, getLocalDouble(frame, bs.readLocalIndex2(curBCI)));
break;
case ALOAD:
putObject(frame, top, getLocalObject(frame, bs.readLocalIndex2(curBCI)));
break;
case ISTORE:
setLocalInt(frame, bs.readLocalIndex2(curBCI), popInt(frame, top - 1));
break;
case LSTORE:
setLocalLong(frame, bs.readLocalIndex2(curBCI), popLong(frame, top - 1));
break;
case FSTORE:
setLocalFloat(frame, bs.readLocalIndex2(curBCI), popFloat(frame, top - 1));
break;
case DSTORE:
setLocalDouble(frame, bs.readLocalIndex2(curBCI), popDouble(frame, top - 1));
break;
case ASTORE:
setLocalObjectOrReturnAddress(frame, bs.readLocalIndex2(curBCI), popReturnAddressOrObject(frame, top - 1));
break;
case IINC:
setLocalInt(frame, bs.readLocalIndex2(curBCI), getLocalInt(frame, bs.readLocalIndex2(curBCI)) + bs.readIncrement2(curBCI));
break;
case RET:
{
int targetBCI = getLocalReturnAddress(frame, bs.readLocalIndex2(curBCI));
livenessAnalysis.performPostBCI(frame, curBCI);
if (jsrBci == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
jsrBci = new int[bs.endBCI()][];
}
if (jsrBci[curBCI] == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
jsrBci[curBCI] = new int[] { targetBCI };
}
for (int jsr : jsrBci[curBCI]) {
if (jsr == targetBCI) {
CompilerAsserts.partialEvaluationConstant(jsr);
targetBCI = jsr;
top += Bytecodes.stackEffectOf(RET);
nextStatementIndex = beforeJumpChecks(frame, curBCI, targetBCI, top, statementIndex, instrument, loopCount);
curBCI = targetBCI;
continue loop;
}
}
CompilerDirectives.transferToInterpreterAndInvalidate();
jsrBci[curBCI] = Arrays.copyOf(jsrBci[curBCI], jsrBci[curBCI].length + 1);
jsrBci[curBCI][jsrBci[curBCI].length - 1] = targetBCI;
top += Bytecodes.stackEffectOf(RET);
nextStatementIndex = beforeJumpChecks(frame, curBCI, targetBCI, top, statementIndex, instrument, loopCount);
curBCI = targetBCI;
continue loop;
}
default:
CompilerDirectives.transferToInterpreter();
throw EspressoError.shouldNotReachHere(Bytecodes.nameOf(curOpcode));
}
livenessAnalysis.performPostBCI(frame, curBCI);
int targetBCI = bs.nextBCI(curBCI);
livenessAnalysis.performOnEdge(frame, curBCI, targetBCI);
top += Bytecodes.stackEffectOf(wideOpcode);
curBCI = targetBCI;
continue loop;
}
case MULTIANEWARRAY:
top += allocateMultiArray(frame, top, resolveType(MULTIANEWARRAY, readCPI(curBCI)), bs.readUByte(curBCI + 3));
break;
case BREAKPOINT:
CompilerDirectives.transferToInterpreter();
throw EspressoError.unimplemented(Bytecodes.nameOf(curOpcode) + " not supported.");
case INVOKEDYNAMIC:
top += quickenInvokeDynamic(frame, top, curBCI, INVOKEDYNAMIC);
break;
case QUICK:
{
// Force a volatile read of the opcode.
if (bs.currentVolatileBC(curBCI) != QUICK) {
// Possible case of read reordering. Retry handling the bytecode to make sure we get a correct CPI.
CompilerDirectives.transferToInterpreterAndInvalidate();
continue loop;
}
BaseQuickNode quickNode = nodes[readCPI(curBCI)];
if (quickNode.removedByRedefintion()) {
CompilerDirectives.transferToInterpreterAndInvalidate();
quickNode = getBaseQuickNode(curBCI, top, statementIndex, quickNode);
}
top += quickNode.execute(frame);
break;
}
case SLIM_QUICK:
top += sparseNodes[curBCI].execute(frame);
break;
default:
CompilerDirectives.transferToInterpreter();
throw EspressoError.shouldNotReachHere(Bytecodes.nameOf(curOpcode));
}
// @formatter:on
} catch (AbstractTruffleException | StackOverflowError | OutOfMemoryError e) {
if (instrument != null && e instanceof EspressoException) {
instrument.notifyExceptionAt(frame, e, statementIndex);
}
CompilerAsserts.partialEvaluationConstant(curBCI);
// Handle both guest and host StackOverflowError.
if (e == getContext().getStackOverflow() || e instanceof StackOverflowError) {
// Always deopt on SOE.
CompilerDirectives.transferToInterpreter();
EspressoException wrappedStackOverflowError = null;
if (e == getContext().getStackOverflow()) {
wrappedStackOverflowError = (EspressoException) e;
} else {
wrappedStackOverflowError = getContext().getStackOverflow();
}
/*
* Stack Overflow management. All calls to stack manipulation are manually
* inlined to prevent another SOE.
*
* Note: no need to check for the stacktrace being null, as we reset the frames
* at each apparition of a host SOE.
*/
if (stackOverflowErrorInfo != null) {
for (int i = 0; i < stackOverflowErrorInfo.length; i += 3) {
if (curBCI >= stackOverflowErrorInfo[i] && curBCI < stackOverflowErrorInfo[i + 1]) {
clearOperandStack(frame, top);
top = EspressoFrame.VALUES_START + getMethodVersion().getCodeAttribute().getMaxLocals();
putObject(frame, top, wrappedStackOverflowError.getGuestException());
top++;
int targetBCI = stackOverflowErrorInfo[i + 2];
nextStatementIndex = beforeJumpChecks(frame, curBCI, targetBCI, top, statementIndex, instrument, loopCount);
curBCI = targetBCI;
// skip bs.next()
continue loop;
}
}
}
if (instrument != null) {
instrument.notifyExceptionAt(frame, wrappedStackOverflowError, statementIndex);
}
if (CompilerDirectives.hasNextTier() && loopCount.value > 0) {
LoopNode.reportLoopCount(this, loopCount.value);
}
throw wrappedStackOverflowError;
} else /* EspressoException or AbstractTruffleException or OutOfMemoryError */
{
EspressoException wrappedException;
if (e instanceof EspressoException) {
wrappedException = (EspressoException) e;
} else if (e instanceof AbstractTruffleException) {
if (e instanceof EspressoExitException) {
CompilerDirectives.transferToInterpreter();
getRoot().abortMonitor(frame);
// Tearing down the VM, no need to report loop count.
throw e;
}
assert getContext().Polyglot;
// should fold
getMeta().polyglot.ForeignException.safeInitialize();
wrappedException = EspressoException.wrap(StaticObject.createForeignException(getMeta(), e, InteropLibrary.getUncached(e)), getMeta());
} else {
assert e instanceof OutOfMemoryError;
CompilerDirectives.transferToInterpreter();
wrappedException = getContext().getOutOfMemory();
}
ExceptionHandler[] handlers = getMethodVersion().getExceptionHandlers();
ExceptionHandler handler = null;
for (ExceptionHandler toCheck : handlers) {
CompilerAsserts.partialEvaluationConstant(toCheck);
if (curBCI >= toCheck.getStartBCI() && curBCI < toCheck.getEndBCI()) {
Klass catchType = null;
if (!toCheck.isCatchAll()) {
// exception handlers are similar to instanceof bytecodes, so we
// pass instanceof
catchType = resolveType(Bytecodes.INSTANCEOF, (char) toCheck.catchTypeCPI());
}
CompilerAsserts.partialEvaluationConstant(catchType);
if (catchType == null || InterpreterToVM.instanceOf(wrappedException.getGuestException(), catchType)) {
// the first found exception handler is our exception handler
handler = toCheck;
break;
}
}
}
if (handler != null) {
clearOperandStack(frame, top);
top = EspressoFrame.VALUES_START + getMethodVersion().getCodeAttribute().getMaxLocals();
checkNoForeignObjectAssumption(wrappedException.getGuestException());
putObject(frame, top, wrappedException.getGuestException());
top++;
int targetBCI = handler.getHandlerBCI();
nextStatementIndex = beforeJumpChecks(frame, curBCI, targetBCI, top, statementIndex, instrument, loopCount);
curBCI = targetBCI;
// skip bs.next()
continue loop;
} else {
if (instrument != null) {
instrument.notifyExceptionAt(frame, wrappedException, statementIndex);
}
if (CompilerDirectives.hasNextTier() && loopCount.value > 0) {
LoopNode.reportLoopCount(this, loopCount.value);
}
throw e;
}
}
} catch (EspressoOSRReturnException e) {
if (CompilerDirectives.hasNextTier() && loopCount.value > 0) {
LoopNode.reportLoopCount(this, loopCount.value);
}
return e.getResult();
}
assert curOpcode != WIDE && curOpcode != LOOKUPSWITCH && curOpcode != TABLESWITCH;
int targetBCI = curBCI + Bytecodes.lengthOf(curOpcode);
livenessAnalysis.performOnEdge(frame, curBCI, targetBCI);
if (instrument != null) {
nextStatementIndex = instrument.getNextStatementIndex(statementIndex, targetBCI);
}
top += Bytecodes.stackEffectOf(curOpcode);
curBCI = targetBCI;
}
}
use of com.oracle.truffle.espresso.meta.ExceptionHandler in project graal by oracle.
the class Method method getSOEHandlerInfo.
public int[] getSOEHandlerInfo() {
ArrayList<Integer> toArray = new ArrayList<>();
for (ExceptionHandler handler : getExceptionHandlers()) {
if (handler.getCatchType() == Type.java_lang_StackOverflowError) {
toArray.add(handler.getStartBCI());
toArray.add(handler.getEndBCI());
toArray.add(handler.getHandlerBCI());
}
}
if (toArray.isEmpty()) {
return null;
}
int[] res = new int[toArray.size()];
int pos = 0;
for (Integer i : toArray) {
res[pos++] = i;
}
return res;
}
use of com.oracle.truffle.espresso.meta.ExceptionHandler in project graal by oracle.
the class ClassfileParser method parseExceptionHandlerEntries.
private ExceptionHandler[] parseExceptionHandlerEntries() {
int count = stream.readU2();
if (count == 0) {
return ExceptionHandler.EMPTY_ARRAY;
}
ExceptionHandler[] entries = new ExceptionHandler[count];
for (int i = 0; i < count; i++) {
int startPc = stream.readU2();
int endPc = stream.readU2();
int handlerPc = stream.readU2();
int catchTypeIndex = stream.readU2();
Symbol<Type> catchType = null;
if (catchTypeIndex != 0) {
catchType = context.getTypes().fromName(pool.classAt(catchTypeIndex).getName(pool));
}
entries[i] = new ExceptionHandler(startPc, endPc, handlerPc, catchTypeIndex, catchType);
}
return entries;
}
use of com.oracle.truffle.espresso.meta.ExceptionHandler in project graal by oracle.
the class GraphBuilder method registerHandlers.
/**
* Blocks are assigned, register each handler to the blocks it covers.
*/
private void registerHandlers() {
for (int hPos = 0; hPos < handlers.length; hPos++) {
ExceptionHandler handler = handlers[hPos];
int currentBlock = readBlockID(handler.getStartBCI());
do {
temporaryBlocks[currentBlock].registerHandler(hPos, this);
currentBlock++;
} while (currentBlock < nBlocks && temporaryBlocks[currentBlock].end() < handler.getEndBCI());
}
}
use of com.oracle.truffle.espresso.meta.ExceptionHandler in project graal by oracle.
the class GraphBuilder method spawnBlocks.
/**
* Creates temporary semi-linked blocks. We can know what the direct successors are from regular
* control flow. Once all blocks are assigned, we will have an easier time finding the blocks
* covered by the exception handlers.
*/
private void spawnBlocks() {
TemporaryBlock[] temp = new TemporaryBlock[nBlocks];
int id = 0;
int start = 0;
int[] successors = null;
boolean isRet = false;
boolean traps = false;
int bci = 0;
int last = 0;
while (bci < status.length) {
if (bci != 0 && isStatus(bci, BLOCK_START)) {
assert temp[id] == null;
assert id == readBlockID(start);
temp[id] = createTempBlock(id, start, successors, isRet, bci, last, traps);
start = bci;
id++;
successors = null;
isRet = false;
traps = false;
}
if (isStatus(bci, IS_RET)) {
assert successors == null;
isRet = true;
successors = returnTable;
}
if (isStatus(bci, TRAPS)) {
traps = true;
}
if (isStatus(bci, HAS_TARGET)) {
assert successors == null;
successors = findSuccessors(bci, id);
}
if (isStatus(bci, IS_CONTROL_SINK)) {
assert successors == null;
successors = EMPTY_SUCCESSORS;
}
last = bci;
bci = bs.nextBCI(bci);
}
temp[id] = createTempBlock(id, start, successors, isRet, status.length, last, traps);
temporaryBlocks = temp;
int[] handlerBlocks = new int[handlers.length];
int pos = 0;
for (ExceptionHandler handler : handlers) {
handlerBlocks[pos++] = readBlockID(handler.getHandlerBCI());
}
handlerToBlock = handlerBlocks;
}
Aggregations