Java Code Examples for jdk.internal.dynalink.linker.LinkRequest#getReceiver()

The following examples show how to use jdk.internal.dynalink.linker.LinkRequest#getReceiver() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: BrowserJSObjectLinker.java    From jdk8u60 with GNU General Public License v2.0 6 votes vote down vote up
@Override
public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices) throws Exception {
    final LinkRequest requestWithoutContext = request.withoutRuntimeContext(); // Nashorn has no runtime context
    final Object self = requestWithoutContext.getReceiver();
    final CallSiteDescriptor desc = requestWithoutContext.getCallSiteDescriptor();
    checkJSObjectClass();

    if (desc.getNameTokenCount() < 2 || !"dyn".equals(desc.getNameToken(CallSiteDescriptor.SCHEME))) {
        // We only support standard "dyn:*[:*]" operations
        return null;
    }

    final GuardedInvocation inv;
    if (jsObjectClass.isInstance(self)) {
        inv = lookup(desc, request, linkerServices);
    } else {
        throw new AssertionError(); // Should never reach here.
    }

    return Bootstrap.asTypeSafeReturn(inv, linkerServices, desc);
}
 
Example 2
Source File: BeansLinker.java    From openjdk-8-source with GNU General Public License v2.0 6 votes vote down vote up
@Override
public GuardedInvocation getGuardedInvocation(LinkRequest request, final LinkerServices linkerServices)
        throws Exception {
    final CallSiteDescriptor callSiteDescriptor = request.getCallSiteDescriptor();
    final int l = callSiteDescriptor.getNameTokenCount();
    // All names conforming to the dynalang MOP should have at least two tokens, the first one being "dyn"
    if(l < 2 || "dyn" != callSiteDescriptor.getNameToken(CallSiteDescriptor.SCHEME)) {
        return null;
    }

    final Object receiver = request.getReceiver();
    if(receiver == null) {
        // Can't operate on null
        return null;
    }
    return getLinkerForClass(receiver.getClass()).getGuardedInvocation(request, linkerServices);
}
 
Example 3
Source File: BeansLinker.java    From openjdk-jdk8u with GNU General Public License v2.0 6 votes vote down vote up
@Override
public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices)
        throws Exception {
    final CallSiteDescriptor callSiteDescriptor = request.getCallSiteDescriptor();
    final int l = callSiteDescriptor.getNameTokenCount();
    // All names conforming to the dynalang MOP should have at least two tokens, the first one being "dyn"
    if(l < 2 || "dyn" != callSiteDescriptor.getNameToken(CallSiteDescriptor.SCHEME)) {
        return null;
    }

    final Object receiver = request.getReceiver();
    if(receiver == null) {
        // Can't operate on null
        return null;
    }
    return getLinkerForClass(receiver.getClass()).getGuardedInvocation(request, linkerServices);
}
 
Example 4
Source File: DynamicMethodLinker.java    From openjdk-8-source with GNU General Public License v2.0 6 votes vote down vote up
@Override
public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest, LinkerServices linkerServices) {
    final Object receiver = linkRequest.getReceiver();
    if(!(receiver instanceof DynamicMethod)) {
        return null;
    }
    final CallSiteDescriptor desc = linkRequest.getCallSiteDescriptor();
    if(desc.getNameTokenCount() != 2 && desc.getNameToken(CallSiteDescriptor.SCHEME) != "dyn") {
        return null;
    }
    final String operator = desc.getNameToken(CallSiteDescriptor.OPERATOR);
    if(operator == "call") {
        final MethodHandle invocation = ((DynamicMethod)receiver).getInvocation(
                CallSiteDescriptorFactory.dropParameterTypes(desc, 0, 1), linkerServices);
        if(invocation == null) {
            return null;
        }
        return new GuardedInvocation(MethodHandles.dropArguments(invocation, 0,
                desc.getMethodType().parameterType(0)), Guards.getIdentityGuard(receiver));
    }
    return null;
}
 
Example 5
Source File: JSObjectLinker.java    From openjdk-8 with GNU General Public License v2.0 6 votes vote down vote up
@Override
public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices) throws Exception {
    final LinkRequest requestWithoutContext = request.withoutRuntimeContext(); // Nashorn has no runtime context
    final Object self = requestWithoutContext.getReceiver();
    final CallSiteDescriptor desc = requestWithoutContext.getCallSiteDescriptor();

    if (desc.getNameTokenCount() < 2 || !"dyn".equals(desc.getNameToken(CallSiteDescriptor.SCHEME))) {
        // We only support standard "dyn:*[:*]" operations
        return null;
    }

    final GuardedInvocation inv;
    if (self instanceof JSObject) {
        inv = lookup(desc);
    } else {
        throw new AssertionError(); // Should never reach here.
    }

    return Bootstrap.asType(inv, linkerServices, desc);
}
 
Example 6
Source File: BeansLinker.java    From TencentKona-8 with GNU General Public License v2.0 6 votes vote down vote up
@Override
public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices)
        throws Exception {
    final CallSiteDescriptor callSiteDescriptor = request.getCallSiteDescriptor();
    final int l = callSiteDescriptor.getNameTokenCount();
    // All names conforming to the dynalang MOP should have at least two tokens, the first one being "dyn"
    if(l < 2 || "dyn" != callSiteDescriptor.getNameToken(CallSiteDescriptor.SCHEME)) {
        return null;
    }

    final Object receiver = request.getReceiver();
    if(receiver == null) {
        // Can't operate on null
        return null;
    }
    return getLinkerForClass(receiver.getClass()).getGuardedInvocation(request, linkerServices);
}
 
Example 7
Source File: NativeString.java    From openjdk-8-source with GNU General Public License v2.0 5 votes vote down vote up
@Override
protected GuardedInvocation findGetIndexMethod(final CallSiteDescriptor desc, final LinkRequest request) {
    final Object self = request.getReceiver();
    final Class<?> returnType = desc.getMethodType().returnType();

    if (returnType == Object.class && (self instanceof String || self instanceof ConsString)) {
        try {
            MethodHandle mh = MH.findStatic(MethodHandles.lookup(), NativeString.class, "get", desc.getMethodType());
            return new GuardedInvocation(mh, NashornGuards.getInstanceOf2Guard(String.class, ConsString.class));
        } catch (final LookupException e) {
            // Shouldn't happen. Fall back to super
        }
    }
    return super.findGetIndexMethod(desc, request);
}
 
Example 8
Source File: NashornBeansLinker.java    From openjdk-jdk8u-backup with GNU General Public License v2.0 5 votes vote down vote up
@Override
public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception {
    final Object self = linkRequest.getReceiver();
    final CallSiteDescriptor desc = linkRequest.getCallSiteDescriptor();
    if (self instanceof ConsString) {
        // In order to treat ConsString like a java.lang.String we need a link request with a string receiver.
        final Object[] arguments = linkRequest.getArguments();
        arguments[0] = "";
        final LinkRequest forgedLinkRequest = linkRequest.replaceArguments(desc, arguments);
        final GuardedInvocation invocation = getGuardedInvocation(beansLinker, forgedLinkRequest, linkerServices);
        // If an invocation is found we add a filter that makes it work for both Strings and ConsStrings.
        return invocation == null ? null : invocation.filterArguments(0, FILTER_CONSSTRING);
    }

    if (self != null && "call".equals(desc.getNameToken(CallSiteDescriptor.OPERATOR))) {
        // Support dyn:call on any object that supports some @FunctionalInterface
        // annotated interface. This way Java method, constructor references or
        // implementations of java.util.function.* interfaces can be called as though
        // those are script functions.
        final String name = getFunctionalInterfaceMethodName(self.getClass());
        if (name != null) {
            final MethodType callType = desc.getMethodType();
            // drop callee (Undefined ScriptFunction) and change the request to be dyn:callMethod:<name>
            final NashornCallSiteDescriptor newDesc = NashornCallSiteDescriptor.get(desc.getLookup(),
                    "dyn:callMethod:" + name, desc.getMethodType().dropParameterTypes(1, 2),
                    NashornCallSiteDescriptor.getFlags(desc));
            final GuardedInvocation gi = getGuardedInvocation(beansLinker,
                    linkRequest.replaceArguments(newDesc, linkRequest.getArguments()),
                    new NashornBeansLinkerServices(linkerServices));

            // drop 'thiz' passed from the script.
            return gi.replaceMethods(
                MH.dropArguments(linkerServices.filterInternalObjects(gi.getInvocation()), 1, callType.parameterType(1)),
                gi.getGuard());
        }
    }
    return getGuardedInvocation(beansLinker, linkRequest, linkerServices);
}
 
Example 9
Source File: NativeString.java    From nashorn with GNU General Public License v2.0 5 votes vote down vote up
@Override
protected GuardedInvocation findGetIndexMethod(final CallSiteDescriptor desc, final LinkRequest request) {
    final Object self = request.getReceiver();
    final Class<?> returnType = desc.getMethodType().returnType();

    if (returnType == Object.class && (self instanceof String || self instanceof ConsString)) {
        try {
            MethodHandle mh = MH.findStatic(MethodHandles.lookup(), NativeString.class, "get", desc.getMethodType());
            return new GuardedInvocation(mh, NashornGuards.getInstanceOf2Guard(String.class, ConsString.class));
        } catch (final LookupException e) {
            // Shouldn't happen. Fall back to super
        }
    }
    return super.findGetIndexMethod(desc, request);
}
 
Example 10
Source File: CompositeTypeBasedGuardingDynamicLinker.java    From TencentKona-8 with GNU General Public License v2.0 5 votes vote down vote up
@Override
public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices)
        throws Exception {
    final Object obj = linkRequest.getReceiver();
    if(obj == null) {
        return null;
    }
    for(final TypeBasedGuardingDynamicLinker linker: classToLinker.get(obj.getClass())) {
        final GuardedInvocation invocation = linker.getGuardedInvocation(linkRequest, linkerServices);
        if(invocation != null) {
            return invocation;
        }
    }
    return null;
}
 
Example 11
Source File: NashornLinker.java    From openjdk-jdk8u with GNU General Public License v2.0 5 votes vote down vote up
@Override
public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices) throws Exception {
    final LinkRequest requestWithoutContext = request.withoutRuntimeContext(); // Nashorn has no runtime context
    final Object self = requestWithoutContext.getReceiver();
    final CallSiteDescriptor desc = requestWithoutContext.getCallSiteDescriptor();

    if (desc.getNameTokenCount() < 2 || !"dyn".equals(desc.getNameToken(CallSiteDescriptor.SCHEME))) {
        // We only support standard "dyn:*[:*]" operations
        return null;
    }

    return Bootstrap.asTypeSafeReturn(getGuardedInvocation(self,  request, desc), linkerServices, desc);
}
 
Example 12
Source File: NativeString.java    From openjdk-jdk8u-backup with GNU General Public License v2.0 5 votes vote down vote up
@Override
protected GuardedInvocation findGetIndexMethod(final CallSiteDescriptor desc, final LinkRequest request) {
    final Object self = request.getReceiver();
    final Class<?> returnType = desc.getMethodType().returnType();

    if (returnType == Object.class && JSType.isString(self)) {
        try {
            return new GuardedInvocation(MH.findStatic(MethodHandles.lookup(), NativeString.class, "get", desc.getMethodType()), NashornGuards.getStringGuard());
        } catch (final LookupException e) {
            //empty. Shouldn't happen. Fall back to super
        }
    }
    return super.findGetIndexMethod(desc, request);
}
 
Example 13
Source File: ReflectionCheckLinker.java    From jdk8u60 with GNU General Public License v2.0 5 votes vote down vote up
private static void checkLinkRequest(final LinkRequest origRequest) {
    final Global global = Context.getGlobal();
    final ClassFilter cf = global.getClassFilter();
    if (cf != null) {
        throw typeError("no.reflection.with.classfilter");
    }

    final SecurityManager sm = System.getSecurityManager();
    if (sm != null) {
        final LinkRequest requestWithoutContext = origRequest.withoutRuntimeContext(); // Nashorn has no runtime context
        final Object self = requestWithoutContext.getReceiver();
        // allow 'static' access on Class objects representing public classes of non-restricted packages
        if ((self instanceof Class) && Modifier.isPublic(((Class<?>)self).getModifiers())) {
            final CallSiteDescriptor desc = requestWithoutContext.getCallSiteDescriptor();
            if(CallSiteDescriptorFactory.tokenizeOperators(desc).contains("getProp")) {
                if (desc.getNameTokenCount() > CallSiteDescriptor.NAME_OPERAND &&
                    "static".equals(desc.getNameToken(CallSiteDescriptor.NAME_OPERAND))) {
                    if (Context.isAccessibleClass((Class<?>)self) && !isReflectionClass((Class<?>)self)) {

                        // If "getProp:static" passes access checks, allow access.
                        return;
                    }
                }
            }
        }
        checkReflectionPermission(sm);
    }
}
 
Example 14
Source File: NashornLinker.java    From hottub with GNU General Public License v2.0 5 votes vote down vote up
@Override
public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices) throws Exception {
    final LinkRequest requestWithoutContext = request.withoutRuntimeContext(); // Nashorn has no runtime context
    final Object self = requestWithoutContext.getReceiver();
    final CallSiteDescriptor desc = requestWithoutContext.getCallSiteDescriptor();

    if (desc.getNameTokenCount() < 2 || !"dyn".equals(desc.getNameToken(CallSiteDescriptor.SCHEME))) {
        // We only support standard "dyn:*[:*]" operations
        return null;
    }

    return Bootstrap.asTypeSafeReturn(getGuardedInvocation(self,  request, desc), linkerServices, desc);
}
 
Example 15
Source File: ReflectionCheckLinker.java    From openjdk-jdk8u-backup with GNU General Public License v2.0 5 votes vote down vote up
private static void checkLinkRequest(final LinkRequest origRequest) {
    final Global global = Context.getGlobal();
    final ClassFilter cf = global.getClassFilter();
    if (cf != null) {
        throw typeError("no.reflection.with.classfilter");
    }

    final SecurityManager sm = System.getSecurityManager();
    if (sm != null) {
        final LinkRequest requestWithoutContext = origRequest.withoutRuntimeContext(); // Nashorn has no runtime context
        final Object self = requestWithoutContext.getReceiver();
        // allow 'static' access on Class objects representing public classes of non-restricted packages
        if ((self instanceof Class) && Modifier.isPublic(((Class<?>)self).getModifiers())) {
            final CallSiteDescriptor desc = requestWithoutContext.getCallSiteDescriptor();
            if(CallSiteDescriptorFactory.tokenizeOperators(desc).contains("getProp")) {
                if (desc.getNameTokenCount() > CallSiteDescriptor.NAME_OPERAND &&
                    "static".equals(desc.getNameToken(CallSiteDescriptor.NAME_OPERAND))) {
                    if (Context.isAccessibleClass((Class<?>)self) && !isReflectionClass((Class<?>)self)) {

                        // If "getProp:static" passes access checks, allow access.
                        return;
                    }
                }
            }
        }
        checkReflectionPermission(sm);
    }
}
 
Example 16
Source File: FindProperty.java    From hottub with GNU General Public License v2.0 5 votes vote down vote up
private MethodHandle insertAccessorsGetter(final UserAccessorProperty uap, final LinkRequest request, final MethodHandle mh) {
    MethodHandle superGetter = uap.getAccessorsGetter();
    if (isInherited()) {
        superGetter = ScriptObject.addProtoFilter(superGetter, getProtoChainLength());
    }
    if (request != null && !(request.getReceiver() instanceof ScriptObject)) {
        final MethodHandle wrapFilter = Global.getPrimitiveWrapFilter(request.getReceiver());
        superGetter = MH.filterArguments(superGetter, 0, wrapFilter.asType(wrapFilter.type().changeReturnType(superGetter.type().parameterType(0))));
    }
    superGetter = MH.asType(superGetter, superGetter.type().changeParameterType(0, Object.class));

    return MH.foldArguments(mh, superGetter);
}
 
Example 17
Source File: ReflectionCheckLinker.java    From jdk8u_nashorn with GNU General Public License v2.0 5 votes vote down vote up
private static void checkLinkRequest(final LinkRequest origRequest) {
    final Global global = Context.getGlobal();
    final ClassFilter cf = global.getClassFilter();
    if (cf != null) {
        throw typeError("no.reflection.with.classfilter");
    }

    final SecurityManager sm = System.getSecurityManager();
    if (sm != null) {
        final LinkRequest requestWithoutContext = origRequest.withoutRuntimeContext(); // Nashorn has no runtime context
        final Object self = requestWithoutContext.getReceiver();
        // allow 'static' access on Class objects representing public classes of non-restricted packages
        if ((self instanceof Class) && Modifier.isPublic(((Class<?>)self).getModifiers())) {
            final CallSiteDescriptor desc = requestWithoutContext.getCallSiteDescriptor();
            if(CallSiteDescriptorFactory.tokenizeOperators(desc).contains("getProp")) {
                if (desc.getNameTokenCount() > CallSiteDescriptor.NAME_OPERAND &&
                    "static".equals(desc.getNameToken(CallSiteDescriptor.NAME_OPERAND))) {
                    if (Context.isAccessibleClass((Class<?>)self) && !isReflectionClass((Class<?>)self)) {

                        // If "getProp:static" passes access checks, allow access.
                        return;
                    }
                }
            }
        }
        checkReflectionPermission(sm);
    }
}
 
Example 18
Source File: JavaSuperAdapterLinker.java    From openjdk-8 with GNU General Public License v2.0 4 votes vote down vote up
@Override
public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices)
        throws Exception {
    final Object objSuperAdapter = linkRequest.getReceiver();
    if(!(objSuperAdapter instanceof JavaSuperAdapter)) {
        return null;
    }

    final CallSiteDescriptor descriptor = linkRequest.getCallSiteDescriptor();
    if(!CallSiteDescriptorFactory.tokenizeOperators(descriptor).contains(GET_METHOD)) {
        // We only handle getMethod
        return null;
    }

    final Object adapter = ((JavaSuperAdapter)objSuperAdapter).getAdapter();

    // Replace argument (javaSuperAdapter, ...) => (adapter, ...) when delegating to BeansLinker
    final Object[] args = linkRequest.getArguments();
    args[0] = adapter;

    // Use R(T0, ...) => R(adapter.class, ...) call site type when delegating to BeansLinker.
    final MethodType type = descriptor.getMethodType();
    final Class<?> adapterClass = adapter.getClass();
    final boolean hasFixedName = descriptor.getNameTokenCount() > 2;
    final String opName = hasFixedName ? (DYN_GET_METHOD_FIXED + descriptor.getNameToken(
            CallSiteDescriptor.NAME_OPERAND)) : DYN_GET_METHOD;

    final CallSiteDescriptor newDescriptor = NashornCallSiteDescriptor.get(descriptor.getLookup(), opName,
            type.changeParameterType(0, adapterClass), 0);

    // Delegate to BeansLinker
    final GuardedInvocation guardedInv = NashornBeansLinker.getGuardedInvocation(
            BeansLinker.getLinkerForClass(adapterClass), linkRequest.replaceArguments(newDescriptor, args),
            linkerServices);

    final MethodHandle guard = IS_ADAPTER_OF_CLASS.bindTo(adapterClass);
    if(guardedInv == null) {
        // Short circuit the lookup here for non-existent methods by linking an empty getter. If we just returned
        // null instead, BeansLinker would find final methods on the JavaSuperAdapter instead: getClass() and
        // wait().
        return new GuardedInvocation(MethodHandles.dropArguments(EMPTY_GETTER, 1,type.parameterList().subList(1,
                type.parameterCount())), guard).asType(descriptor);
    }

    final MethodHandle invocation = guardedInv.getInvocation();
    final MethodType invType = invocation.type();
    // For invocation typed R(T0, ...) create a dynamic method binder of type R(R, T0)
    final MethodHandle typedBinder = BIND_DYNAMIC_METHOD.asType(MethodType.methodType(invType.returnType(),
            invType.returnType(), invType.parameterType(0)));
    // For invocation typed R(T0, T1, ...) create a dynamic method binder of type R(R, T0, T1, ...)
    final MethodHandle droppingBinder = MethodHandles.dropArguments(typedBinder, 2,
            invType.parameterList().subList(1, invType.parameterCount()));
    // Finally, fold the invocation into the binder to produce a method handle that will bind every returned
    // DynamicMethod object from dyn:getMethod calls to the actual receiver
    // R(R(T0, T1, ...), T0, T1, ...)
    final MethodHandle bindingInvocation = MethodHandles.foldArguments(droppingBinder, invocation);

    final MethodHandle typedGetAdapter = asFilterType(GET_ADAPTER, 0, invType, type);
    final MethodHandle adaptedInvocation;
    if(hasFixedName) {
        adaptedInvocation = MethodHandles.filterArguments(bindingInvocation, 0, typedGetAdapter);
    } else {
        // Add a filter that'll prepend "super$" to each name passed to the variable-name "dyn:getMethod".
        final MethodHandle typedAddPrefix = asFilterType(ADD_PREFIX_TO_METHOD_NAME, 1, invType, type);
        adaptedInvocation = MethodHandles.filterArguments(bindingInvocation, 0, typedGetAdapter, typedAddPrefix);
    }

    return guardedInv.replaceMethods(adaptedInvocation, guard).asType(descriptor);
}
 
Example 19
Source File: NashornBottomLinker.java    From jdk8u_nashorn with GNU General Public License v2.0 4 votes vote down vote up
private static GuardedInvocation linkBean(final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception {
    final NashornCallSiteDescriptor desc = (NashornCallSiteDescriptor)linkRequest.getCallSiteDescriptor();
    final Object self = linkRequest.getReceiver();
    final String operator = desc.getFirstOperator();
    switch (operator) {
    case "new":
        if(BeansLinker.isDynamicConstructor(self)) {
            throw typeError("no.constructor.matches.args", ScriptRuntime.safeToString(self));
        }
        if(BeansLinker.isDynamicMethod(self)) {
            throw typeError("method.not.constructor", ScriptRuntime.safeToString(self));
        }
        throw typeError("not.a.function", desc.getFunctionErrorMessage(self));
    case "call":
        if(BeansLinker.isDynamicConstructor(self)) {
            throw typeError("constructor.requires.new", ScriptRuntime.safeToString(self));
        }
        if(BeansLinker.isDynamicMethod(self)) {
            throw typeError("no.method.matches.args", ScriptRuntime.safeToString(self));
        }
        throw typeError("not.a.function", desc.getFunctionErrorMessage(self));
    case "callMethod":
        throw typeError("no.such.function", getArgument(linkRequest), ScriptRuntime.safeToString(self));
    case "getMethod":
        // evaluate to undefined, later on Undefined will take care of throwing TypeError
        return getInvocation(MH.dropArguments(GET_UNDEFINED.get(TYPE_OBJECT_INDEX), 0, Object.class), self, linkerServices, desc);
    case "getProp":
    case "getElem":
        if(NashornCallSiteDescriptor.isOptimistic(desc)) {
            throw new UnwarrantedOptimismException(UNDEFINED, NashornCallSiteDescriptor.getProgramPoint(desc), Type.OBJECT);
        }
        if (desc.getOperand() != null) {
            return getInvocation(EMPTY_PROP_GETTER, self, linkerServices, desc);
        }
        return getInvocation(EMPTY_ELEM_GETTER, self, linkerServices, desc);
    case "setProp":
    case "setElem": {
        final boolean strict = NashornCallSiteDescriptor.isStrict(desc);
        if (strict) {
            throw typeError("cant.set.property", getArgument(linkRequest), ScriptRuntime.safeToString(self));
        }
        if (desc.getOperand() != null) {
            return getInvocation(EMPTY_PROP_SETTER, self, linkerServices, desc);
        }
        return getInvocation(EMPTY_ELEM_SETTER, self, linkerServices, desc);
    }
    default:
        break;
    }
    throw new AssertionError("unknown call type " + desc);
}
 
Example 20
Source File: BoundCallableLinker.java    From jdk8u60 with GNU General Public License v2.0 4 votes vote down vote up
@Override
public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception {
    final Object objBoundCallable = linkRequest.getReceiver();
    if(!(objBoundCallable instanceof BoundCallable)) {
        return null;
    }

    final CallSiteDescriptor descriptor = linkRequest.getCallSiteDescriptor();
    if (descriptor.getNameTokenCount() < 2 || !"dyn".equals(descriptor.getNameToken(CallSiteDescriptor.SCHEME))) {
        return null;
    }
    final String operation = descriptor.getNameToken(CallSiteDescriptor.OPERATOR);
    // We need to distinguish "dyn:new" from "dyn:call" because "dyn:call" sites have parameter list of the form
    // "callee, this, args", while "dyn:call" sites have "callee, args" -- they lack the "this" parameter.
    final boolean isCall;
    if ("new".equals(operation)) {
        isCall = false;
    } else if ("call".equals(operation)) {
        isCall = true;
    } else {
        // Only dyn:call and dyn:new are supported.
        return null;
    }
    final BoundCallable boundCallable = (BoundCallable)objBoundCallable;
    final Object callable = boundCallable.getCallable();
    final Object boundThis = boundCallable.getBoundThis();

    // We need to ask the linker services for a delegate invocation on the target callable.

    // Replace arguments (boundCallable[, this], args) => (callable[, boundThis], boundArgs, args) when delegating
    final Object[] args = linkRequest.getArguments();
    final Object[] boundArgs = boundCallable.getBoundArgs();
    final int argsLen = args.length;
    final int boundArgsLen = boundArgs.length;
    final Object[] newArgs = new Object[argsLen + boundArgsLen];
    newArgs[0] = callable;
    final int firstArgIndex;
    if (isCall) {
        newArgs[1] = boundThis;
        firstArgIndex = 2;
    } else {
        firstArgIndex = 1;
    }
    System.arraycopy(boundArgs, 0, newArgs, firstArgIndex, boundArgsLen);
    System.arraycopy(args, firstArgIndex, newArgs, firstArgIndex + boundArgsLen, argsLen - firstArgIndex);

    // Use R(T0, T1, T2, ...) => R(callable.class, boundThis.class, boundArg0.class, ..., boundArgn.class, T2, ...)
    // call site type when delegating to underlying linker (for dyn:new, there's no this).
    final MethodType type = descriptor.getMethodType();
    // Use R(T0, ...) => R(callable.class, ...)
    MethodType newMethodType = descriptor.getMethodType().changeParameterType(0, callable.getClass());
    if (isCall) {
        // R(callable.class, T1, ...) => R(callable.class, boundThis.class, ...)
        newMethodType = newMethodType.changeParameterType(1, boundThis == null? Object.class : boundThis.getClass());
    }
    // R(callable.class[, boundThis.class], T2, ...) => R(callable.class[, boundThis.class], boundArg0.class, ..., boundArgn.class, T2, ...)
    for(int i = boundArgs.length; i-- > 0;) {
        newMethodType = newMethodType.insertParameterTypes(firstArgIndex, boundArgs[i] == null ? Object.class : boundArgs[i].getClass());
    }
    final CallSiteDescriptor newDescriptor = descriptor.changeMethodType(newMethodType);

    // Delegate to target's linker
    final GuardedInvocation inv = linkerServices.getGuardedInvocation(linkRequest.replaceArguments(newDescriptor, newArgs));
    if(inv == null) {
        return null;
    }

    // Bind (callable[, boundThis], boundArgs) to the delegate handle
    final MethodHandle boundHandle = MethodHandles.insertArguments(inv.getInvocation(), 0,
            Arrays.copyOf(newArgs, firstArgIndex + boundArgs.length));
    final Class<?> p0Type = type.parameterType(0);
    final MethodHandle droppingHandle;
    if (isCall) {
        // Ignore incoming boundCallable and this
        droppingHandle = MethodHandles.dropArguments(boundHandle, 0, p0Type, type.parameterType(1));
    } else {
        // Ignore incoming boundCallable
        droppingHandle = MethodHandles.dropArguments(boundHandle, 0, p0Type);
    }
    // Identity guard on boundCallable object
    final MethodHandle newGuard = Guards.getIdentityGuard(boundCallable);
    return inv.replaceMethods(droppingHandle, newGuard.asType(newGuard.type().changeParameterType(0, p0Type)));
}