Search in sources :

Example 6 with BaseQuickNode

use of com.oracle.truffle.espresso.nodes.quick.BaseQuickNode in project graal by oracle.

the class BytecodeNode method quickenInstanceOf.

private int quickenInstanceOf(VirtualFrame frame, int top, int curBCI, int opcode) {
    if (StaticObject.isNull(peekObject(frame, top - 1))) {
        // Skip resolution.
        putInt(frame, top - 1, 0);
        return -Bytecodes.stackEffectOf(opcode);
    }
    CompilerDirectives.transferToInterpreterAndInvalidate();
    assert opcode == INSTANCEOF;
    BaseQuickNode quick = tryPatchQuick(curBCI, () -> new InstanceOfQuickNode(resolveType(CHECKCAST, readCPI(curBCI)), top, curBCI));
    return quick.execute(frame) - Bytecodes.stackEffectOf(opcode);
}
Also used : InstanceOfQuickNode(com.oracle.truffle.espresso.nodes.quick.InstanceOfQuickNode) BaseQuickNode(com.oracle.truffle.espresso.nodes.quick.BaseQuickNode)

Example 7 with BaseQuickNode

use of com.oracle.truffle.espresso.nodes.quick.BaseQuickNode 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;
    }
}
Also used : AbstractTruffleException(com.oracle.truffle.api.exception.AbstractTruffleException) TruffleSafepoint(com.oracle.truffle.api.TruffleSafepoint) ExceptionHandler(com.oracle.truffle.espresso.meta.ExceptionHandler) DebugCounter(com.oracle.truffle.espresso.perf.DebugCounter) EspressoException(com.oracle.truffle.espresso.runtime.EspressoException) Klass(com.oracle.truffle.espresso.impl.Klass) ArrayKlass(com.oracle.truffle.espresso.impl.ArrayKlass) EspressoExitException(com.oracle.truffle.espresso.runtime.EspressoExitException) BytecodeTableSwitch(com.oracle.truffle.espresso.bytecode.BytecodeTableSwitch) StaticObject(com.oracle.truffle.espresso.runtime.StaticObject) BaseQuickNode(com.oracle.truffle.espresso.nodes.quick.BaseQuickNode) BytecodeLookupSwitch(com.oracle.truffle.espresso.bytecode.BytecodeLookupSwitch) ExplodeLoop(com.oracle.truffle.api.nodes.ExplodeLoop)

Example 8 with BaseQuickNode

use of com.oracle.truffle.espresso.nodes.quick.BaseQuickNode in project graal by oracle.

the class BytecodeNode method quickenCheckCast.

private int quickenCheckCast(VirtualFrame frame, int top, int curBCI, int opcode) {
    if (StaticObject.isNull(peekObject(frame, top - 1))) {
        // Skip resolution.
        return -Bytecodes.stackEffectOf(opcode);
    }
    CompilerDirectives.transferToInterpreterAndInvalidate();
    assert opcode == CHECKCAST;
    BaseQuickNode quick = tryPatchQuick(curBCI, () -> new CheckCastQuickNode(resolveType(CHECKCAST, readCPI(curBCI)), top, curBCI));
    return quick.execute(frame) - Bytecodes.stackEffectOf(opcode);
}
Also used : CheckCastQuickNode(com.oracle.truffle.espresso.nodes.quick.CheckCastQuickNode) BaseQuickNode(com.oracle.truffle.espresso.nodes.quick.BaseQuickNode)

Example 9 with BaseQuickNode

use of com.oracle.truffle.espresso.nodes.quick.BaseQuickNode in project graal by oracle.

the class BytecodeNode method quickenInvokeDynamic.

private int quickenInvokeDynamic(final VirtualFrame frame, int top, int curBCI, int opcode) {
    CompilerDirectives.transferToInterpreterAndInvalidate();
    assert (Bytecodes.INVOKEDYNAMIC == opcode);
    RuntimeConstantPool pool = getConstantPool();
    BaseQuickNode quick = null;
    int indyIndex = -1;
    synchronized (this) {
        if (bs.currentVolatileBC(curBCI) == QUICK) {
            // Check if someone did the job for us. Defer the call until we are out of the lock.
            quick = nodes[readCPI(curBCI)];
        } else {
            // fetch indy under lock.
            indyIndex = readCPI(curBCI);
        }
    }
    if (quick != null) {
        // Do invocation outside of the lock.
        return quick.execute(frame) - Bytecodes.stackEffectOf(opcode);
    }
    // Resolution should happen outside of the bytecode patching lock.
    InvokeDynamicConstant.CallSiteLink link = pool.linkInvokeDynamic(getMethod().getDeclaringKlass(), indyIndex);
    // re-lock to check if someone did the job for us, since this was a heavy operation.
    synchronized (this) {
        if (bs.currentVolatileBC(curBCI) == QUICK) {
            // someone beat us to it, just trust him.
            quick = nodes[readCPI(curBCI)];
        } else {
            quick = injectQuick(curBCI, new InvokeDynamicCallSiteNode(link.getMemberName(), link.getUnboxedAppendix(), link.getParsedSignature(), getMeta(), top, curBCI), QUICK);
        }
    }
    return quick.execute(frame) - Bytecodes.stackEffectOf(opcode);
}
Also used : RuntimeConstantPool(com.oracle.truffle.espresso.classfile.RuntimeConstantPool) BaseQuickNode(com.oracle.truffle.espresso.nodes.quick.BaseQuickNode) InvokeDynamicConstant(com.oracle.truffle.espresso.classfile.constantpool.InvokeDynamicConstant) TruffleSafepoint(com.oracle.truffle.api.TruffleSafepoint) InvokeDynamicCallSiteNode(com.oracle.truffle.espresso.nodes.quick.invoke.InvokeDynamicCallSiteNode)

Example 10 with BaseQuickNode

use of com.oracle.truffle.espresso.nodes.quick.BaseQuickNode in project graal by oracle.

the class BytecodeNode method getBaseQuickNode.

private BaseQuickNode getBaseQuickNode(int curBCI, int top, int statementIndex, BaseQuickNode quickNode) {
    // block while class redefinition is ongoing
    quickNode.getContext().getClassRedefinition().check();
    BaseQuickNode result = quickNode;
    synchronized (this) {
        // re-check if node was already replaced by another thread
        if (result != nodes[readCPI(curBCI)]) {
            // another thread beat us
            result = nodes[readCPI(curBCI)];
        } else {
            // other threads might still have beat us but if
            // so, the resolution failed and so will we below
            BytecodeStream original = new BytecodeStream(getMethodVersion().getCodeAttribute().getOriginalCode());
            char cpi = original.readCPI(curBCI);
            int nodeOpcode = original.currentBC(curBCI);
            Method resolutionSeed = resolveMethodNoCache(nodeOpcode, cpi);
            result = insert(dispatchQuickened(top, curBCI, cpi, nodeOpcode, statementIndex, resolutionSeed, getContext().InlineFieldAccessors));
            nodes[readCPI(curBCI)] = result;
        }
    }
    return result;
}
Also used : BytecodeStream(com.oracle.truffle.espresso.bytecode.BytecodeStream) BaseQuickNode(com.oracle.truffle.espresso.nodes.quick.BaseQuickNode) Method(com.oracle.truffle.espresso.impl.Method) TruffleSafepoint(com.oracle.truffle.api.TruffleSafepoint)

Aggregations

BaseQuickNode (com.oracle.truffle.espresso.nodes.quick.BaseQuickNode)13 TruffleSafepoint (com.oracle.truffle.api.TruffleSafepoint)3 Method (com.oracle.truffle.espresso.impl.Method)3 ArrayKlass (com.oracle.truffle.espresso.impl.ArrayKlass)2 Klass (com.oracle.truffle.espresso.impl.Klass)2 AbstractTruffleException (com.oracle.truffle.api.exception.AbstractTruffleException)1 ExplodeLoop (com.oracle.truffle.api.nodes.ExplodeLoop)1 BytecodeLookupSwitch (com.oracle.truffle.espresso.bytecode.BytecodeLookupSwitch)1 BytecodeStream (com.oracle.truffle.espresso.bytecode.BytecodeStream)1 BytecodeTableSwitch (com.oracle.truffle.espresso.bytecode.BytecodeTableSwitch)1 RuntimeConstantPool (com.oracle.truffle.espresso.classfile.RuntimeConstantPool)1 InvokeDynamicConstant (com.oracle.truffle.espresso.classfile.constantpool.InvokeDynamicConstant)1 ExceptionHandler (com.oracle.truffle.espresso.meta.ExceptionHandler)1 Meta (com.oracle.truffle.espresso.meta.Meta)1 CheckCastQuickNode (com.oracle.truffle.espresso.nodes.quick.CheckCastQuickNode)1 InstanceOfQuickNode (com.oracle.truffle.espresso.nodes.quick.InstanceOfQuickNode)1 ArrayLengthQuickNode (com.oracle.truffle.espresso.nodes.quick.interop.ArrayLengthQuickNode)1 ByteArrayLoadQuickNode (com.oracle.truffle.espresso.nodes.quick.interop.ByteArrayLoadQuickNode)1 ByteArrayStoreQuickNode (com.oracle.truffle.espresso.nodes.quick.interop.ByteArrayStoreQuickNode)1 CharArrayLoadQuickNode (com.oracle.truffle.espresso.nodes.quick.interop.CharArrayLoadQuickNode)1