Search in sources :

Example 1 with BaseQuickNode

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

the class BytecodeNode method quickenInvoke.

private int quickenInvoke(VirtualFrame frame, int top, int curBCI, int opcode, int statementIndex) {
    QUICKENED_INVOKES.inc();
    CompilerDirectives.transferToInterpreterAndInvalidate();
    assert Bytecodes.isInvoke(opcode);
    BaseQuickNode quick = tryPatchQuick(curBCI, () -> {
        // During resolution of the symbolic reference to the method, any of the exceptions
        // pertaining to method resolution (§5.4.3.3) can be thrown.
        char cpi = readCPI(curBCI);
        Method resolutionSeed = resolveMethod(opcode, cpi);
        return dispatchQuickened(top, curBCI, cpi, opcode, statementIndex, resolutionSeed, getContext().InlineFieldAccessors);
    });
    // Perform the call outside of the lock.
    return quick.execute(frame) - Bytecodes.stackEffectOf(opcode);
}
Also used : BaseQuickNode(com.oracle.truffle.espresso.nodes.quick.BaseQuickNode) Method(com.oracle.truffle.espresso.impl.Method)

Example 2 with BaseQuickNode

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

the class BytecodeNode method quickenArrayLoad.

private int quickenArrayLoad(VirtualFrame frame, int top, int curBCI, int loadOpcode) {
    CompilerDirectives.transferToInterpreterAndInvalidate();
    assert IALOAD <= loadOpcode && loadOpcode <= SALOAD;
    BaseQuickNode arrayLoadNode;
    synchronized (this) {
        if (bs.currentVolatileBC(curBCI) == SLIM_QUICK) {
            arrayLoadNode = sparseNodes[curBCI];
        } else {
            // @formatter:off
            switch(loadOpcode) {
                case BALOAD:
                    arrayLoadNode = new ByteArrayLoadQuickNode(top, curBCI);
                    break;
                case SALOAD:
                    arrayLoadNode = new ShortArrayLoadQuickNode(top, curBCI);
                    break;
                case CALOAD:
                    arrayLoadNode = new CharArrayLoadQuickNode(top, curBCI);
                    break;
                case IALOAD:
                    arrayLoadNode = new IntArrayLoadQuickNode(top, curBCI);
                    break;
                case FALOAD:
                    arrayLoadNode = new FloatArrayLoadQuickNode(top, curBCI);
                    break;
                case LALOAD:
                    arrayLoadNode = new LongArrayLoadQuickNode(top, curBCI);
                    break;
                case DALOAD:
                    arrayLoadNode = new DoubleArrayLoadQuickNode(top, curBCI);
                    break;
                case AALOAD:
                    arrayLoadNode = new ReferenceArrayLoadQuickNode(top, curBCI);
                    break;
                default:
                    CompilerDirectives.transferToInterpreter();
                    throw EspressoError.shouldNotReachHere("unexpected kind");
            }
            // @formatter:on
            arrayLoadNode = injectQuick(curBCI, arrayLoadNode, SLIM_QUICK);
        }
    }
    return arrayLoadNode.execute(frame) - Bytecodes.stackEffectOf(loadOpcode);
}
Also used : ReferenceArrayLoadQuickNode(com.oracle.truffle.espresso.nodes.quick.interop.ReferenceArrayLoadQuickNode) ByteArrayLoadQuickNode(com.oracle.truffle.espresso.nodes.quick.interop.ByteArrayLoadQuickNode) ShortArrayLoadQuickNode(com.oracle.truffle.espresso.nodes.quick.interop.ShortArrayLoadQuickNode) FloatArrayLoadQuickNode(com.oracle.truffle.espresso.nodes.quick.interop.FloatArrayLoadQuickNode) LongArrayLoadQuickNode(com.oracle.truffle.espresso.nodes.quick.interop.LongArrayLoadQuickNode) BaseQuickNode(com.oracle.truffle.espresso.nodes.quick.BaseQuickNode) CharArrayLoadQuickNode(com.oracle.truffle.espresso.nodes.quick.interop.CharArrayLoadQuickNode) IntArrayLoadQuickNode(com.oracle.truffle.espresso.nodes.quick.interop.IntArrayLoadQuickNode) DoubleArrayLoadQuickNode(com.oracle.truffle.espresso.nodes.quick.interop.DoubleArrayLoadQuickNode)

Example 3 with BaseQuickNode

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

the class BytecodeNode method quickenArrayStore.

private int quickenArrayStore(final VirtualFrame frame, int top, int curBCI, int storeOpcode) {
    CompilerDirectives.transferToInterpreterAndInvalidate();
    assert IASTORE <= storeOpcode && storeOpcode <= SASTORE;
    BaseQuickNode arrayStoreNode;
    synchronized (this) {
        if (bs.currentVolatileBC(curBCI) == SLIM_QUICK) {
            arrayStoreNode = sparseNodes[curBCI];
        } else {
            // @formatter:off
            switch(storeOpcode) {
                case BASTORE:
                    arrayStoreNode = new ByteArrayStoreQuickNode(top, curBCI);
                    break;
                case SASTORE:
                    arrayStoreNode = new ShortArrayStoreQuickNode(top, curBCI);
                    break;
                case CASTORE:
                    arrayStoreNode = new CharArrayStoreQuickNode(top, curBCI);
                    break;
                case IASTORE:
                    arrayStoreNode = new IntArrayStoreQuickNode(top, curBCI);
                    break;
                case FASTORE:
                    arrayStoreNode = new FloatArrayStoreQuickNode(top, curBCI);
                    break;
                case LASTORE:
                    arrayStoreNode = new LongArrayStoreQuickNode(top, curBCI);
                    break;
                case DASTORE:
                    arrayStoreNode = new DoubleArrayStoreQuickNode(top, curBCI);
                    break;
                case AASTORE:
                    arrayStoreNode = new ReferenceArrayStoreQuickNode(top, curBCI);
                    break;
                default:
                    CompilerDirectives.transferToInterpreter();
                    throw EspressoError.shouldNotReachHere("unexpected kind");
            }
            // @formatter:on
            arrayStoreNode = injectQuick(curBCI, arrayStoreNode, SLIM_QUICK);
        }
    }
    return arrayStoreNode.execute(frame) - Bytecodes.stackEffectOf(storeOpcode);
}
Also used : LongArrayStoreQuickNode(com.oracle.truffle.espresso.nodes.quick.interop.LongArrayStoreQuickNode) ReferenceArrayStoreQuickNode(com.oracle.truffle.espresso.nodes.quick.interop.ReferenceArrayStoreQuickNode) FloatArrayStoreQuickNode(com.oracle.truffle.espresso.nodes.quick.interop.FloatArrayStoreQuickNode) CharArrayStoreQuickNode(com.oracle.truffle.espresso.nodes.quick.interop.CharArrayStoreQuickNode) ByteArrayStoreQuickNode(com.oracle.truffle.espresso.nodes.quick.interop.ByteArrayStoreQuickNode) IntArrayStoreQuickNode(com.oracle.truffle.espresso.nodes.quick.interop.IntArrayStoreQuickNode) DoubleArrayStoreQuickNode(com.oracle.truffle.espresso.nodes.quick.interop.DoubleArrayStoreQuickNode) BaseQuickNode(com.oracle.truffle.espresso.nodes.quick.BaseQuickNode) ShortArrayStoreQuickNode(com.oracle.truffle.espresso.nodes.quick.interop.ShortArrayStoreQuickNode)

Example 4 with BaseQuickNode

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

the class BytecodeNode method quickenGetField.

// region quickenForeign
public int quickenGetField(final VirtualFrame frame, int top, int curBCI, int opcode, int statementIndex, Field field) {
    CompilerDirectives.transferToInterpreterAndInvalidate();
    assert opcode == GETFIELD;
    BaseQuickNode getField = tryPatchQuick(curBCI, () -> new QuickenedGetFieldNode(top, curBCI, statementIndex, field));
    return getField.execute(frame) - Bytecodes.stackEffectOf(opcode);
}
Also used : QuickenedGetFieldNode(com.oracle.truffle.espresso.nodes.quick.interop.QuickenedGetFieldNode) BaseQuickNode(com.oracle.truffle.espresso.nodes.quick.BaseQuickNode)

Example 5 with BaseQuickNode

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

the class BytecodeNode method dispatchQuickened.

// endregion quickenForeign
private BaseQuickNode dispatchQuickened(int top, int curBCI, char cpi, int opcode, int statementIndex, Method resolutionSeed, boolean allowFieldAccessInlining) {
    assert !allowFieldAccessInlining || getContext().InlineFieldAccessors;
    BaseQuickNode invoke;
    Method resolved = resolutionSeed;
    switch(opcode) {
        case INVOKESTATIC:
            // instruction throws an IncompatibleClassChangeError.
            if (!resolved.isStatic()) {
                CompilerDirectives.transferToInterpreter();
                Meta meta = getMeta();
                throw meta.throwException(meta.java_lang_IncompatibleClassChangeError);
            }
            break;
        case INVOKEINTERFACE:
            // invokeinterface instruction throws an IncompatibleClassChangeError.
            if (resolved.isStatic() || (getContext().getJavaVersion().java8OrEarlier() && resolved.isPrivate())) {
                CompilerDirectives.transferToInterpreter();
                Meta meta = getMeta();
                throw meta.throwException(meta.java_lang_IncompatibleClassChangeError);
            }
            break;
        case INVOKEVIRTUAL:
            // instruction throws an IncompatibleClassChangeError.
            if (resolved.isStatic()) {
                CompilerDirectives.transferToInterpreter();
                Meta meta = getMeta();
                throw meta.throwException(meta.java_lang_IncompatibleClassChangeError);
            }
            break;
        case INVOKESPECIAL:
            // instruction, a NoSuchMethodError is thrown.
            if (resolved.isConstructor()) {
                if (resolved.getDeclaringKlass().getName() != getConstantPool().methodAt(cpi).getHolderKlassName(getConstantPool())) {
                    CompilerDirectives.transferToInterpreter();
                    Meta meta = getMeta();
                    throw meta.throwExceptionWithMessage(meta.java_lang_NoSuchMethodError, meta.toGuestString(resolved.getDeclaringKlass().getNameAsString() + "." + resolved.getName() + resolved.getRawSignature()));
                }
            }
            // instruction throws an IncompatibleClassChangeError.
            if (resolved.isStatic()) {
                CompilerDirectives.transferToInterpreter();
                Meta meta = getMeta();
                throw meta.throwException(meta.java_lang_IncompatibleClassChangeError);
            }
            // version of the class file.
            if (!resolved.isConstructor()) {
                Klass declaringKlass = getMethod().getDeclaringKlass();
                Klass symbolicRef = ((MethodRefConstant.Indexes) getConstantPool().methodAt(cpi)).getResolvedHolderKlass(declaringKlass, getConstantPool());
                if (!symbolicRef.isInterface() && symbolicRef != declaringKlass && declaringKlass.getSuperKlass() != null && symbolicRef != declaringKlass.getSuperKlass() && symbolicRef.isAssignableFrom(declaringKlass)) {
                    resolved = declaringKlass.getSuperKlass().lookupMethod(resolved.getName(), resolved.getRawSignature(), declaringKlass);
                }
            }
            break;
        default:
            CompilerDirectives.transferToInterpreter();
            throw EspressoError.unimplemented("Quickening for " + Bytecodes.nameOf(opcode));
    }
    if (allowFieldAccessInlining && resolved.isInlinableGetter()) {
        invoke = InlinedGetterNode.create(resolved, top, opcode, curBCI, statementIndex);
    } else if (allowFieldAccessInlining && resolved.isInlinableSetter()) {
        invoke = InlinedSetterNode.create(resolved, top, opcode, curBCI, statementIndex);
    } else if (resolved.isPolySignatureIntrinsic()) {
        invoke = new InvokeHandleNode(resolved, getDeclaringKlass(), top, curBCI);
    } else if (opcode == INVOKEINTERFACE && resolved.getITableIndex() < 0) {
        if (resolved.isPrivate()) {
            assert getJavaVersion().java9OrLater();
            // Interface private methods do not appear in itables.
            invoke = new InvokeSpecialQuickNode(resolved, top, curBCI);
        } else {
            // Can happen in old classfiles that calls j.l.Object on interfaces.
            invoke = new InvokeVirtualQuickNode(resolved, top, curBCI);
        }
    } else if (opcode == INVOKEVIRTUAL && (resolved.isFinalFlagSet() || resolved.getDeclaringKlass().isFinalFlagSet() || resolved.isPrivate())) {
        invoke = new InvokeSpecialQuickNode(resolved, top, curBCI);
    } else {
        // @formatter:off
        switch(opcode) {
            case INVOKESTATIC:
                invoke = new InvokeStaticQuickNode(resolved, top, curBCI);
                break;
            case INVOKEINTERFACE:
                invoke = new InvokeInterfaceQuickNode(resolved, top, curBCI);
                break;
            case INVOKEVIRTUAL:
                invoke = new InvokeVirtualQuickNode(resolved, top, curBCI);
                break;
            case INVOKESPECIAL:
                invoke = new InvokeSpecialQuickNode(resolved, top, curBCI);
                break;
            default:
                CompilerDirectives.transferToInterpreter();
                throw EspressoError.unimplemented("Quickening for " + Bytecodes.nameOf(opcode));
        }
    // @formatter:on
    }
    return invoke;
}
Also used : Meta(com.oracle.truffle.espresso.meta.Meta) Klass(com.oracle.truffle.espresso.impl.Klass) ArrayKlass(com.oracle.truffle.espresso.impl.ArrayKlass) InvokeStaticQuickNode(com.oracle.truffle.espresso.nodes.quick.invoke.InvokeStaticQuickNode) InvokeHandleNode(com.oracle.truffle.espresso.nodes.quick.invoke.InvokeHandleNode) BaseQuickNode(com.oracle.truffle.espresso.nodes.quick.BaseQuickNode) Method(com.oracle.truffle.espresso.impl.Method) InvokeVirtualQuickNode(com.oracle.truffle.espresso.nodes.quick.invoke.InvokeVirtualQuickNode) InvokeSpecialQuickNode(com.oracle.truffle.espresso.nodes.quick.invoke.InvokeSpecialQuickNode) InvokeInterfaceQuickNode(com.oracle.truffle.espresso.nodes.quick.invoke.InvokeInterfaceQuickNode)

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