Search in sources :

Example 1 with Method

use of com.oracle.truffle.espresso.impl.Method 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 Method

use of com.oracle.truffle.espresso.impl.Method 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)

Example 3 with Method

use of com.oracle.truffle.espresso.impl.Method in project graal by oracle.

the class InvokeInterface method methodLookup.

static Method.MethodVersion methodLookup(Method resolutionSeed, Klass receiverKlass) {
    assert !receiverKlass.isArray();
    if (resolutionSeed.isRemovedByRedefition()) {
        /*
             * Accept a slow path once the method has been removed put method behind a boundary to
             * avoid a deopt loop
             */
        return resolutionSeed.getContext().getClassRedefinition().handleRemovedMethod(resolutionSeed, receiverKlass).getMethodVersion();
    }
    int iTableIndex = resolutionSeed.getITableIndex();
    Method method = ((ObjectKlass) receiverKlass).itableLookup(resolutionSeed.getDeclaringKlass(), iTableIndex);
    if (!method.isPublic()) {
        transferToInterpreterAndInvalidate();
        Meta meta = receiverKlass.getMeta();
        throw meta.throwException(meta.java_lang_IllegalAccessError);
    }
    return method.getMethodVersion();
}
Also used : Meta(com.oracle.truffle.espresso.meta.Meta) ObjectKlass(com.oracle.truffle.espresso.impl.ObjectKlass) Method(com.oracle.truffle.espresso.impl.Method)

Example 4 with Method

use of com.oracle.truffle.espresso.impl.Method in project graal by oracle.

the class AbstractLookupNode method doLookup.

@TruffleBoundary
Method doLookup(Klass klass, String key, boolean publicOnly, boolean isStatic, int arity) throws ArityException {
    String methodName;
    String signature = null;
    int separatorIndex = key.indexOf(METHOD_SELECTION_SEPARATOR);
    if (separatorIndex >= 0) {
        methodName = key.substring(0, separatorIndex);
        signature = key.substring(separatorIndex + 1);
    } else {
        methodName = key;
    }
    Method result = null;
    int minOverallArity = Integer.MAX_VALUE;
    int maxOverallArity = -1;
    for (Method.MethodVersion m : getMethodArray(klass)) {
        if (matchMethod(m.getMethod(), methodName, signature, isStatic, publicOnly)) {
            int matchArity = m.getMethod().getParameterCount();
            minOverallArity = min(minOverallArity, matchArity);
            maxOverallArity = max(maxOverallArity, matchArity);
            if (matchArity == arity) {
                if (result != null) {
                    /*
                         * Multiple methods with the same name and arity (if specified), cannot
                         * disambiguate
                         */
                    return null;
                }
                result = m.getMethod();
            }
        }
    }
    if (result == null && maxOverallArity >= 0) {
        throw ArityException.create(minOverallArity, maxOverallArity, arity);
    }
    return result;
}
Also used : Method(com.oracle.truffle.espresso.impl.Method) TruffleBoundary(com.oracle.truffle.api.CompilerDirectives.TruffleBoundary)

Example 5 with Method

use of com.oracle.truffle.espresso.impl.Method in project graal by oracle.

the class InvokeVirtual method methodLookup.

static Method.MethodVersion methodLookup(Method resolutionSeed, Klass receiverKlass) {
    if (resolutionSeed.isRemovedByRedefition()) {
        /*
             * Accept a slow path once the method has been removed put method behind a boundary to
             * avoid a deopt loop.
             */
        return resolutionSeed.getContext().getClassRedefinition().handleRemovedMethod(resolutionSeed, receiverKlass).getMethodVersion();
    }
    /*
         * Surprisingly, INVOKEVIRTUAL can try to invoke interface methods, even non-default ones.
         * Good thing is, miranda methods are taken care of at vtable creation !
         */
    int vtableIndex = resolutionSeed.getVTableIndex();
    Method.MethodVersion target;
    if (receiverKlass.isArray()) {
        target = receiverKlass.getSuperKlass().vtableLookup(vtableIndex).getMethodVersion();
    } else {
        target = receiverKlass.vtableLookup(vtableIndex).getMethodVersion();
    }
    if (!target.getMethod().hasCode()) {
        Meta meta = receiverKlass.getMeta();
        throw meta.throwException(meta.java_lang_AbstractMethodError);
    }
    return target;
}
Also used : Meta(com.oracle.truffle.espresso.meta.Meta) Method(com.oracle.truffle.espresso.impl.Method)

Aggregations

Method (com.oracle.truffle.espresso.impl.Method)91 StaticObject (com.oracle.truffle.espresso.runtime.StaticObject)57 Meta (com.oracle.truffle.espresso.meta.Meta)27 TruffleObject (com.oracle.truffle.api.interop.TruffleObject)22 Klass (com.oracle.truffle.espresso.impl.Klass)19 JavaType (com.oracle.truffle.espresso.substitutions.JavaType)19 ObjectKlass (com.oracle.truffle.espresso.impl.ObjectKlass)16 TruffleBoundary (com.oracle.truffle.api.CompilerDirectives.TruffleBoundary)14 ExportMessage (com.oracle.truffle.api.library.ExportMessage)12 ArrayKlass (com.oracle.truffle.espresso.impl.ArrayKlass)10 NoSafepoint (com.oracle.truffle.espresso.jni.NoSafepoint)9 FrameInstance (com.oracle.truffle.api.frame.FrameInstance)8 ArityException (com.oracle.truffle.api.interop.ArityException)8 UnsupportedTypeException (com.oracle.truffle.api.interop.UnsupportedTypeException)8 ArrayList (java.util.ArrayList)8 Name (com.oracle.truffle.espresso.descriptors.Symbol.Name)7 EspressoException (com.oracle.truffle.espresso.runtime.EspressoException)5 Field (com.oracle.truffle.espresso.impl.Field)4 MethodParametersAttribute (com.oracle.truffle.espresso.classfile.attributes.MethodParametersAttribute)3 Signature (com.oracle.truffle.espresso.descriptors.Symbol.Signature)3