Java Code Examples for jdk.internal.dynalink.linker.GuardedInvocation#getInvocation()

The following examples show how to use jdk.internal.dynalink.linker.GuardedInvocation#getInvocation() . 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: WithObject.java    From nashorn with GNU General Public License v2.0 6 votes vote down vote up
private static GuardedInvocation fixExpressionCallSite(final NashornCallSiteDescriptor desc, final GuardedInvocation link) {
    // If it's not a getMethod, just add an expression filter that converts WithObject in "this" position to its
    // expression.
    if(!"getMethod".equals(desc.getFirstOperator())) {
        return fixReceiverType(link, WITHEXPRESSIONFILTER).filterArguments(0, WITHEXPRESSIONFILTER);
    }

    final MethodHandle linkInvocation = link.getInvocation();
    final MethodType linkType = linkInvocation.type();
    final boolean linkReturnsFunction = ScriptFunction.class.isAssignableFrom(linkType.returnType());
    return link.replaceMethods(
            // Make sure getMethod will bind the script functions it receives to WithObject.expression
            MH.foldArguments(linkReturnsFunction ? BIND_TO_EXPRESSION_FN : BIND_TO_EXPRESSION_OBJ,
                    filter(linkInvocation.asType(linkType.changeReturnType(
                            linkReturnsFunction ? ScriptFunction.class : Object.class)), WITHEXPRESSIONFILTER)),
            // No clever things for the guard -- it is still identically filtered.
            filterGuard(link, WITHEXPRESSIONFILTER));
}
 
Example 2
Source File: WithObject.java    From openjdk-8 with GNU General Public License v2.0 6 votes vote down vote up
private static GuardedInvocation fixExpressionCallSite(final NashornCallSiteDescriptor desc, final GuardedInvocation link) {
    // If it's not a getMethod, just add an expression filter that converts WithObject in "this" position to its
    // expression.
    if(!"getMethod".equals(desc.getFirstOperator())) {
        return fixReceiverType(link, WITHEXPRESSIONFILTER).filterArguments(0, WITHEXPRESSIONFILTER);
    }

    final MethodHandle linkInvocation = link.getInvocation();
    final MethodType linkType = linkInvocation.type();
    final boolean linkReturnsFunction = ScriptFunction.class.isAssignableFrom(linkType.returnType());
    return link.replaceMethods(
            // Make sure getMethod will bind the script functions it receives to WithObject.expression
            MH.foldArguments(linkReturnsFunction ? BIND_TO_EXPRESSION_FN : BIND_TO_EXPRESSION_OBJ,
                    filter(linkInvocation.asType(linkType.changeReturnType(
                            linkReturnsFunction ? ScriptFunction.class : Object.class)), WITHEXPRESSIONFILTER)),
            // No clever things for the guard -- it is still identically filtered.
            filterGuard(link, WITHEXPRESSIONFILTER));
}
 
Example 3
Source File: WithObject.java    From openjdk-8-source with GNU General Public License v2.0 6 votes vote down vote up
private static GuardedInvocation fixExpressionCallSite(final NashornCallSiteDescriptor desc, final GuardedInvocation link) {
    // If it's not a getMethod, just add an expression filter that converts WithObject in "this" position to its
    // expression.
    if(!"getMethod".equals(desc.getFirstOperator())) {
        return fixReceiverType(link, WITHEXPRESSIONFILTER).filterArguments(0, WITHEXPRESSIONFILTER);
    }

    final MethodHandle linkInvocation = link.getInvocation();
    final MethodType linkType = linkInvocation.type();
    final boolean linkReturnsFunction = ScriptFunction.class.isAssignableFrom(linkType.returnType());
    return link.replaceMethods(
            // Make sure getMethod will bind the script functions it receives to WithObject.expression
            MH.foldArguments(linkReturnsFunction ? BIND_TO_EXPRESSION_FN : BIND_TO_EXPRESSION_OBJ,
                    filter(linkInvocation.asType(linkType.changeReturnType(
                            linkReturnsFunction ? ScriptFunction.class : Object.class)), WITHEXPRESSIONFILTER)),
            // No clever things for the guard -- it is still identically filtered.
            filterGuard(link, WITHEXPRESSIONFILTER));
}
 
Example 4
Source File: WithObject.java    From TencentKona-8 with GNU General Public License v2.0 5 votes vote down vote up
private static GuardedInvocation fixExpressionCallSite(final NashornCallSiteDescriptor desc, final GuardedInvocation link) {
    // If it's not a getMethod, just add an expression filter that converts WithObject in "this" position to its
    // expression.
    if (!"getMethod".equals(desc.getFirstOperator())) {
        return fixReceiverType(link, WITHEXPRESSIONFILTER).filterArguments(0, WITHEXPRESSIONFILTER);
    }

    final MethodHandle linkInvocation      = link.getInvocation();
    final MethodType   linkType            = linkInvocation.type();
    final boolean      linkReturnsFunction = ScriptFunction.class.isAssignableFrom(linkType.returnType());

    return link.replaceMethods(
            // Make sure getMethod will bind the script functions it receives to WithObject.expression
            MH.foldArguments(
                    linkReturnsFunction ?
                            BIND_TO_EXPRESSION_FN :
                            BIND_TO_EXPRESSION_OBJ,
                    filterReceiver(
                            linkInvocation.asType(
                                    linkType.changeReturnType(
                                            linkReturnsFunction ?
                                                    ScriptFunction.class :
                                                    Object.class).
                                                        changeParameterType(
                                                                0,
                                                                Object.class)),
                                    WITHEXPRESSIONFILTER)),
                     filterGuardReceiver(link, WITHEXPRESSIONFILTER));
 // No clever things for the guard -- it is still identically filtered.

}
 
Example 5
Source File: WithObject.java    From jdk8u60 with GNU General Public License v2.0 5 votes vote down vote up
private static GuardedInvocation fixExpressionCallSite(final NashornCallSiteDescriptor desc, final GuardedInvocation link) {
    // If it's not a getMethod, just add an expression filter that converts WithObject in "this" position to its
    // expression.
    if (!"getMethod".equals(desc.getFirstOperator())) {
        return fixReceiverType(link, WITHEXPRESSIONFILTER).filterArguments(0, WITHEXPRESSIONFILTER);
    }

    final MethodHandle linkInvocation      = link.getInvocation();
    final MethodType   linkType            = linkInvocation.type();
    final boolean      linkReturnsFunction = ScriptFunction.class.isAssignableFrom(linkType.returnType());

    return link.replaceMethods(
            // Make sure getMethod will bind the script functions it receives to WithObject.expression
            MH.foldArguments(
                    linkReturnsFunction ?
                            BIND_TO_EXPRESSION_FN :
                            BIND_TO_EXPRESSION_OBJ,
                    filterReceiver(
                            linkInvocation.asType(
                                    linkType.changeReturnType(
                                            linkReturnsFunction ?
                                                    ScriptFunction.class :
                                                    Object.class).
                                                        changeParameterType(
                                                                0,
                                                                Object.class)),
                                    WITHEXPRESSIONFILTER)),
                     filterGuardReceiver(link, WITHEXPRESSIONFILTER));
 // No clever things for the guard -- it is still identically filtered.

}
 
Example 6
Source File: DynamicLinker.java    From jdk8u_nashorn with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Relinks a call site conforming to the invocation arguments.
 *
 * @param callSite the call site itself
 * @param arguments arguments to the invocation
 *
 * @return return the method handle for the invocation
 *
 * @throws Exception rethrows any exception thrown by the linkers
 */
@SuppressWarnings("unused")
private MethodHandle relink(final RelinkableCallSite callSite, final int relinkCount, final Object... arguments) throws Exception {
    final CallSiteDescriptor callSiteDescriptor = callSite.getDescriptor();
    final boolean unstableDetectionEnabled = unstableRelinkThreshold > 0;
    final boolean callSiteUnstable = unstableDetectionEnabled && relinkCount >= unstableRelinkThreshold;
    final LinkRequest linkRequest =
            runtimeContextArgCount == 0 ?
                    new LinkRequestImpl(callSiteDescriptor, callSite, relinkCount, callSiteUnstable, arguments) :
                    new RuntimeContextLinkRequestImpl(callSiteDescriptor, callSite, relinkCount, callSiteUnstable, arguments, runtimeContextArgCount);

    GuardedInvocation guardedInvocation = linkerServices.getGuardedInvocation(linkRequest);

    // None found - throw an exception
    if(guardedInvocation == null) {
        throw new NoSuchDynamicMethodException(callSiteDescriptor.toString());
    }

    // If our call sites have a runtime context, and the linker produced a context-stripped invocation, adapt the
    // produced invocation into contextual invocation (by dropping the context...)
    if(runtimeContextArgCount > 0) {
        final MethodType origType = callSiteDescriptor.getMethodType();
        final MethodHandle invocation = guardedInvocation.getInvocation();
        if(invocation.type().parameterCount() == origType.parameterCount() - runtimeContextArgCount) {
            final List<Class<?>> prefix = origType.parameterList().subList(1, runtimeContextArgCount + 1);
            final MethodHandle guard = guardedInvocation.getGuard();
            guardedInvocation = guardedInvocation.dropArguments(1, prefix);
        }
    }

    // Make sure we filter the invocation before linking it into the call site. This is typically used to match the
    // return type of the invocation to the call site.
    guardedInvocation = prelinkFilter.filter(guardedInvocation, linkRequest, linkerServices);
    Objects.requireNonNull(guardedInvocation);

    int newRelinkCount = relinkCount;
    // Note that the short-circuited "&&" evaluation below ensures we'll increment the relinkCount until
    // threshold + 1 but not beyond that. Threshold + 1 is treated as a special value to signal that resetAndRelink
    // has already executed once for the unstable call site; we only want the call site to throw away its current
    // linkage once, when it transitions to unstable.
    if(unstableDetectionEnabled && newRelinkCount <= unstableRelinkThreshold && newRelinkCount++ == unstableRelinkThreshold) {
        callSite.resetAndRelink(guardedInvocation, createRelinkAndInvokeMethod(callSite, newRelinkCount));
    } else {
        callSite.relink(guardedInvocation, createRelinkAndInvokeMethod(callSite, newRelinkCount));
    }
    if(syncOnRelink) {
        MutableCallSite.syncAll(new MutableCallSite[] { (MutableCallSite)callSite });
    }
    return guardedInvocation.getInvocation();
}
 
Example 7
Source File: BeanLinker.java    From openjdk-8 with GNU General Public License v2.0 4 votes vote down vote up
private GuardedInvocationComponent getElementSetter(CallSiteDescriptor callSiteDescriptor,
        LinkerServices linkerServices, List<String> operations) throws Exception {
    final MethodType callSiteType = callSiteDescriptor.getMethodType();
    final Class<?> declaredType = callSiteType.parameterType(0);

    final GuardedInvocationComponent gic;
    // If declared type of receiver at the call site is already an array, a list or map, bind without guard. Thing
    // is, it'd be quite stupid of a call site creator to go though invokedynamic when it knows in advance they're
    // dealing with an array, or a list or map, but hey...
    // Note that for arrays and lists, using LinkerServices.asType() will ensure that any language specific linkers
    // in use will get a chance to perform any (if there's any) implicit conversion to integer for the indices.
    final boolean isMap;
    if(declaredType.isArray()) {
        gic = new GuardedInvocationComponent(MethodHandles.arrayElementSetter(declaredType));
        isMap = false;
    } else if(List.class.isAssignableFrom(declaredType)) {
        gic = new GuardedInvocationComponent(SET_LIST_ELEMENT);
        isMap = false;
    } else if(Map.class.isAssignableFrom(declaredType)) {
        gic = new GuardedInvocationComponent(PUT_MAP_ELEMENT);
        isMap = true;
    } else if(clazz.isArray()) {
        gic = getClassGuardedInvocationComponent(MethodHandles.arrayElementSetter(clazz), callSiteType);
        isMap = false;
    } else if(List.class.isAssignableFrom(clazz)) {
        gic = new GuardedInvocationComponent(SET_LIST_ELEMENT, Guards.asType(LIST_GUARD, callSiteType), List.class,
                ValidationType.INSTANCE_OF);
        isMap = false;
    } else if(Map.class.isAssignableFrom(clazz)) {
        gic = new GuardedInvocationComponent(PUT_MAP_ELEMENT, Guards.asType(MAP_GUARD, callSiteType), Map.class,
                ValidationType.INSTANCE_OF);
        isMap = true;
    } else {
        // Can't set elements for objects that are neither arrays, nor list, nor maps.
        gic = null;
        isMap = false;
    }

    // In contrast to, say, getElementGetter, we only compute the nextComponent if the target object is not a map,
    // as maps will always succeed in setting the element and will never need to fall back to the next component
    // operation.
    final GuardedInvocationComponent nextComponent = isMap ? null : getGuardedInvocationComponent(
            callSiteDescriptor, linkerServices, operations);
    if(gic == null) {
        return nextComponent;
    }

    // We can have "dyn:setElem:foo", especially in composites, i.e. "dyn:setElem|setProp:foo"
    final String fixedKey = getFixedKey(callSiteDescriptor);
    // Convert the key to a number if we're working with a list or array
    final Object typedFixedKey;
    if(!isMap && fixedKey != null) {
        typedFixedKey = convertKeyToInteger(fixedKey, linkerServices);
        if(typedFixedKey == null) {
            // key is not numeric, it can never succeed
            return nextComponent;
        }
    } else {
        typedFixedKey = fixedKey;
    }

    final GuardedInvocation gi = gic.getGuardedInvocation();
    final Binder binder = new Binder(linkerServices, callSiteType, typedFixedKey);
    final MethodHandle invocation = gi.getInvocation();

    if(nextComponent == null) {
        return gic.replaceInvocation(binder.bind(invocation));
    }

    final MethodHandle checkGuard = convertArgToInt(invocation == SET_LIST_ELEMENT ? RANGE_CHECK_LIST :
        RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor);
    return nextComponent.compose(MethodHandles.guardWithTest(binder.bindTest(checkGuard),
            binder.bind(invocation), nextComponent.getGuardedInvocation().getInvocation()), gi.getGuard(),
            gic.getValidatorClass(), gic.getValidationType());
}
 
Example 8
Source File: DynamicLinker.java    From jdk8u60 with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Relinks a call site conforming to the invocation arguments.
 *
 * @param callSite the call site itself
 * @param arguments arguments to the invocation
 *
 * @return return the method handle for the invocation
 *
 * @throws Exception rethrows any exception thrown by the linkers
 */
@SuppressWarnings("unused")
private MethodHandle relink(final RelinkableCallSite callSite, final int relinkCount, final Object... arguments) throws Exception {
    final CallSiteDescriptor callSiteDescriptor = callSite.getDescriptor();
    final boolean unstableDetectionEnabled = unstableRelinkThreshold > 0;
    final boolean callSiteUnstable = unstableDetectionEnabled && relinkCount >= unstableRelinkThreshold;
    final LinkRequest linkRequest =
            runtimeContextArgCount == 0 ?
                    new LinkRequestImpl(callSiteDescriptor, callSite, relinkCount, callSiteUnstable, arguments) :
                    new RuntimeContextLinkRequestImpl(callSiteDescriptor, callSite, relinkCount, callSiteUnstable, arguments, runtimeContextArgCount);

    GuardedInvocation guardedInvocation = linkerServices.getGuardedInvocation(linkRequest);

    // None found - throw an exception
    if(guardedInvocation == null) {
        throw new NoSuchDynamicMethodException(callSiteDescriptor.toString());
    }

    // If our call sites have a runtime context, and the linker produced a context-stripped invocation, adapt the
    // produced invocation into contextual invocation (by dropping the context...)
    if(runtimeContextArgCount > 0) {
        final MethodType origType = callSiteDescriptor.getMethodType();
        final MethodHandle invocation = guardedInvocation.getInvocation();
        if(invocation.type().parameterCount() == origType.parameterCount() - runtimeContextArgCount) {
            final List<Class<?>> prefix = origType.parameterList().subList(1, runtimeContextArgCount + 1);
            final MethodHandle guard = guardedInvocation.getGuard();
            guardedInvocation = guardedInvocation.dropArguments(1, prefix);
        }
    }

    // Make sure we filter the invocation before linking it into the call site. This is typically used to match the
    // return type of the invocation to the call site.
    guardedInvocation = prelinkFilter.filter(guardedInvocation, linkRequest, linkerServices);
    Objects.requireNonNull(guardedInvocation);

    int newRelinkCount = relinkCount;
    // Note that the short-circuited "&&" evaluation below ensures we'll increment the relinkCount until
    // threshold + 1 but not beyond that. Threshold + 1 is treated as a special value to signal that resetAndRelink
    // has already executed once for the unstable call site; we only want the call site to throw away its current
    // linkage once, when it transitions to unstable.
    if(unstableDetectionEnabled && newRelinkCount <= unstableRelinkThreshold && newRelinkCount++ == unstableRelinkThreshold) {
        callSite.resetAndRelink(guardedInvocation, createRelinkAndInvokeMethod(callSite, newRelinkCount));
    } else {
        callSite.relink(guardedInvocation, createRelinkAndInvokeMethod(callSite, newRelinkCount));
    }
    if(syncOnRelink) {
        MutableCallSite.syncAll(new MutableCallSite[] { (MutableCallSite)callSite });
    }
    return guardedInvocation.getInvocation();
}
 
Example 9
Source File: JavaSuperAdapterLinker.java    From openjdk-jdk8u 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 Object(R, T0)
    final MethodHandle typedBinder = BIND_DYNAMIC_METHOD.asType(MethodType.methodType(Object.class,
            invType.returnType(), invType.parameterType(0)));
    // For invocation typed R(T0, T1, ...) create a dynamic method binder of type Object(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
    // Object(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 10
Source File: JavaSuperAdapterLinker.java    From jdk8u_nashorn 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 Object(R, T0)
    final MethodHandle typedBinder = BIND_DYNAMIC_METHOD.asType(MethodType.methodType(Object.class,
            invType.returnType(), invType.parameterType(0)));
    // For invocation typed R(T0, T1, ...) create a dynamic method binder of type Object(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
    // Object(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 11
Source File: DynamicLinker.java    From TencentKona-8 with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Relinks a call site conforming to the invocation arguments.
 *
 * @param callSite the call site itself
 * @param arguments arguments to the invocation
 *
 * @return return the method handle for the invocation
 *
 * @throws Exception rethrows any exception thrown by the linkers
 */
@SuppressWarnings("unused")
private MethodHandle relink(final RelinkableCallSite callSite, final int relinkCount, final Object... arguments) throws Exception {
    final CallSiteDescriptor callSiteDescriptor = callSite.getDescriptor();
    final boolean unstableDetectionEnabled = unstableRelinkThreshold > 0;
    final boolean callSiteUnstable = unstableDetectionEnabled && relinkCount >= unstableRelinkThreshold;
    final LinkRequest linkRequest =
            runtimeContextArgCount == 0 ?
                    new LinkRequestImpl(callSiteDescriptor, callSite, relinkCount, callSiteUnstable, arguments) :
                    new RuntimeContextLinkRequestImpl(callSiteDescriptor, callSite, relinkCount, callSiteUnstable, arguments, runtimeContextArgCount);

    GuardedInvocation guardedInvocation = linkerServices.getGuardedInvocation(linkRequest);

    // None found - throw an exception
    if(guardedInvocation == null) {
        throw new NoSuchDynamicMethodException(callSiteDescriptor.toString());
    }

    // If our call sites have a runtime context, and the linker produced a context-stripped invocation, adapt the
    // produced invocation into contextual invocation (by dropping the context...)
    if(runtimeContextArgCount > 0) {
        final MethodType origType = callSiteDescriptor.getMethodType();
        final MethodHandle invocation = guardedInvocation.getInvocation();
        if(invocation.type().parameterCount() == origType.parameterCount() - runtimeContextArgCount) {
            final List<Class<?>> prefix = origType.parameterList().subList(1, runtimeContextArgCount + 1);
            final MethodHandle guard = guardedInvocation.getGuard();
            guardedInvocation = guardedInvocation.dropArguments(1, prefix);
        }
    }

    // Make sure we filter the invocation before linking it into the call site. This is typically used to match the
    // return type of the invocation to the call site.
    guardedInvocation = prelinkFilter.filter(guardedInvocation, linkRequest, linkerServices);
    Objects.requireNonNull(guardedInvocation);

    int newRelinkCount = relinkCount;
    // Note that the short-circuited "&&" evaluation below ensures we'll increment the relinkCount until
    // threshold + 1 but not beyond that. Threshold + 1 is treated as a special value to signal that resetAndRelink
    // has already executed once for the unstable call site; we only want the call site to throw away its current
    // linkage once, when it transitions to unstable.
    if(unstableDetectionEnabled && newRelinkCount <= unstableRelinkThreshold && newRelinkCount++ == unstableRelinkThreshold) {
        callSite.resetAndRelink(guardedInvocation, createRelinkAndInvokeMethod(callSite, newRelinkCount));
    } else {
        callSite.relink(guardedInvocation, createRelinkAndInvokeMethod(callSite, newRelinkCount));
    }
    if(syncOnRelink) {
        MutableCallSite.syncAll(new MutableCallSite[] { (MutableCallSite)callSite });
    }
    return guardedInvocation.getInvocation();
}
 
Example 12
Source File: DynamicLinker.java    From openjdk-jdk8u with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Relinks a call site conforming to the invocation arguments.
 *
 * @param callSite the call site itself
 * @param arguments arguments to the invocation
 *
 * @return return the method handle for the invocation
 *
 * @throws Exception rethrows any exception thrown by the linkers
 */
@SuppressWarnings("unused")
private MethodHandle relink(final RelinkableCallSite callSite, final int relinkCount, final Object... arguments) throws Exception {
    final CallSiteDescriptor callSiteDescriptor = callSite.getDescriptor();
    final boolean unstableDetectionEnabled = unstableRelinkThreshold > 0;
    final boolean callSiteUnstable = unstableDetectionEnabled && relinkCount >= unstableRelinkThreshold;
    final LinkRequest linkRequest =
            runtimeContextArgCount == 0 ?
                    new LinkRequestImpl(callSiteDescriptor, callSite, relinkCount, callSiteUnstable, arguments) :
                    new RuntimeContextLinkRequestImpl(callSiteDescriptor, callSite, relinkCount, callSiteUnstable, arguments, runtimeContextArgCount);

    GuardedInvocation guardedInvocation = linkerServices.getGuardedInvocation(linkRequest);

    // None found - throw an exception
    if(guardedInvocation == null) {
        throw new NoSuchDynamicMethodException(callSiteDescriptor.toString());
    }

    // If our call sites have a runtime context, and the linker produced a context-stripped invocation, adapt the
    // produced invocation into contextual invocation (by dropping the context...)
    if(runtimeContextArgCount > 0) {
        final MethodType origType = callSiteDescriptor.getMethodType();
        final MethodHandle invocation = guardedInvocation.getInvocation();
        if(invocation.type().parameterCount() == origType.parameterCount() - runtimeContextArgCount) {
            final List<Class<?>> prefix = origType.parameterList().subList(1, runtimeContextArgCount + 1);
            final MethodHandle guard = guardedInvocation.getGuard();
            guardedInvocation = guardedInvocation.dropArguments(1, prefix);
        }
    }

    // Make sure we filter the invocation before linking it into the call site. This is typically used to match the
    // return type of the invocation to the call site.
    guardedInvocation = prelinkFilter.filter(guardedInvocation, linkRequest, linkerServices);
    Objects.requireNonNull(guardedInvocation);

    int newRelinkCount = relinkCount;
    // Note that the short-circuited "&&" evaluation below ensures we'll increment the relinkCount until
    // threshold + 1 but not beyond that. Threshold + 1 is treated as a special value to signal that resetAndRelink
    // has already executed once for the unstable call site; we only want the call site to throw away its current
    // linkage once, when it transitions to unstable.
    if(unstableDetectionEnabled && newRelinkCount <= unstableRelinkThreshold && newRelinkCount++ == unstableRelinkThreshold) {
        callSite.resetAndRelink(guardedInvocation, createRelinkAndInvokeMethod(callSite, newRelinkCount));
    } else {
        callSite.relink(guardedInvocation, createRelinkAndInvokeMethod(callSite, newRelinkCount));
    }
    if(syncOnRelink) {
        MutableCallSite.syncAll(new MutableCallSite[] { (MutableCallSite)callSite });
    }
    return guardedInvocation.getInvocation();
}
 
Example 13
Source File: JavaSuperAdapterLinker.java    From nashorn 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 = BeansLinker.getLinkerForClass(adapterClass).getGuardedInvocation(
            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 14
Source File: DynamicLinker.java    From openjdk-8 with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Relinks a call site conforming to the invocation arguments.
 *
 * @param callSite the call site itself
 * @param arguments arguments to the invocation
 * @return return the method handle for the invocation
 * @throws Exception rethrows any exception thrown by the linkers
 */
@SuppressWarnings("unused")
private MethodHandle relink(RelinkableCallSite callSite, int relinkCount, Object... arguments) throws Exception {
    final CallSiteDescriptor callSiteDescriptor = callSite.getDescriptor();
    final boolean unstableDetectionEnabled = unstableRelinkThreshold > 0;
    final boolean callSiteUnstable = unstableDetectionEnabled && relinkCount >= unstableRelinkThreshold;
    final LinkRequest linkRequest =
            runtimeContextArgCount == 0 ? new LinkRequestImpl(callSiteDescriptor, callSiteUnstable, arguments)
                    : new RuntimeContextLinkRequestImpl(callSiteDescriptor, callSiteUnstable, arguments,
                            runtimeContextArgCount);

    // Find a suitable method handle with a guard
    GuardedInvocation guardedInvocation = linkerServices.getGuardedInvocation(linkRequest);

    // None found - throw an exception
    if(guardedInvocation == null) {
        throw new NoSuchDynamicMethodException(callSiteDescriptor.toString());
    }

    // If our call sites have a runtime context, and the linker produced a context-stripped invocation, adapt the
    // produced invocation into contextual invocation (by dropping the context...)
    if(runtimeContextArgCount > 0) {
        final MethodType origType = callSiteDescriptor.getMethodType();
        final MethodHandle invocation = guardedInvocation.getInvocation();
        if(invocation.type().parameterCount() == origType.parameterCount() - runtimeContextArgCount) {
            final List<Class<?>> prefix = origType.parameterList().subList(1, runtimeContextArgCount + 1);
            final MethodHandle guard = guardedInvocation.getGuard();
            guardedInvocation = guardedInvocation.dropArguments(1, prefix);
        }
    }

    int newRelinkCount = relinkCount;
    // Note that the short-circuited "&&" evaluation below ensures we'll increment the relinkCount until
    // threshold + 1 but not beyond that. Threshold + 1 is treated as a special value to signal that resetAndRelink
    // has already executed once for the unstable call site; we only want the call site to throw away its current
    // linkage once, when it transitions to unstable.
    if(unstableDetectionEnabled && newRelinkCount <= unstableRelinkThreshold && newRelinkCount++ == unstableRelinkThreshold) {
        callSite.resetAndRelink(guardedInvocation, createRelinkAndInvokeMethod(callSite, newRelinkCount));
    } else {
        callSite.relink(guardedInvocation, createRelinkAndInvokeMethod(callSite, newRelinkCount));
    }
    if(syncOnRelink) {
        MutableCallSite.syncAll(new MutableCallSite[] { (MutableCallSite)callSite });
    }
    return guardedInvocation.getInvocation();
}
 
Example 15
Source File: BeanLinker.java    From openjdk-8 with GNU General Public License v2.0 4 votes vote down vote up
private GuardedInvocationComponent getElementGetter(final CallSiteDescriptor callSiteDescriptor,
        final LinkerServices linkerServices, List<String> operations) throws Exception {
    final MethodType callSiteType = callSiteDescriptor.getMethodType();
    final Class<?> declaredType = callSiteType.parameterType(0);
    final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor,
            linkerServices, operations);

    // If declared type of receiver at the call site is already an array, a list or map, bind without guard. Thing
    // is, it'd be quite stupid of a call site creator to go though invokedynamic when it knows in advance they're
    // dealing with an array, or a list or map, but hey...
    // Note that for arrays and lists, using LinkerServices.asType() will ensure that any language specific linkers
    // in use will get a chance to perform any (if there's any) implicit conversion to integer for the indices.
    final GuardedInvocationComponent gic;
    final boolean isMap;
    if(declaredType.isArray()) {
        gic = new GuardedInvocationComponent(MethodHandles.arrayElementGetter(declaredType));
        isMap = false;
    } else if(List.class.isAssignableFrom(declaredType)) {
        gic = new GuardedInvocationComponent(GET_LIST_ELEMENT);
        isMap = false;
    } else if(Map.class.isAssignableFrom(declaredType)) {
        gic = new GuardedInvocationComponent(GET_MAP_ELEMENT);
        isMap = true;
    } else if(clazz.isArray()) {
        gic = getClassGuardedInvocationComponent(MethodHandles.arrayElementGetter(clazz), callSiteType);
        isMap = false;
    } else if(List.class.isAssignableFrom(clazz)) {
        gic = new GuardedInvocationComponent(GET_LIST_ELEMENT, Guards.asType(LIST_GUARD, callSiteType), List.class,
                ValidationType.INSTANCE_OF);
        isMap = false;
    } else if(Map.class.isAssignableFrom(clazz)) {
        gic = new GuardedInvocationComponent(GET_MAP_ELEMENT, Guards.asType(MAP_GUARD, callSiteType), Map.class,
                ValidationType.INSTANCE_OF);
        isMap = true;
    } else {
        // Can't retrieve elements for objects that are neither arrays, nor list, nor maps.
        return nextComponent;
    }

    // We can have "dyn:getElem:foo", especially in composites, i.e. "dyn:getElem|getProp|getMethod:foo"
    final String fixedKey = getFixedKey(callSiteDescriptor);
    // Convert the key to a number if we're working with a list or array
    final Object typedFixedKey;
    if(!isMap && fixedKey != null) {
        typedFixedKey = convertKeyToInteger(fixedKey, linkerServices);
        if(typedFixedKey == null) {
            // key is not numeric, it can never succeed
            return nextComponent;
        }
    } else {
        typedFixedKey = fixedKey;
    }

    final GuardedInvocation gi = gic.getGuardedInvocation();
    final Binder binder = new Binder(linkerServices, callSiteType, typedFixedKey);
    final MethodHandle invocation = gi.getInvocation();

    if(nextComponent == null) {
        return gic.replaceInvocation(binder.bind(invocation));
    }

    final MethodHandle checkGuard;
    if(invocation == GET_LIST_ELEMENT) {
        checkGuard = convertArgToInt(RANGE_CHECK_LIST, linkerServices, callSiteDescriptor);
    } else if(invocation == GET_MAP_ELEMENT) {
        // TODO: A more complex solution could be devised for maps, one where we do a get() first, and fold it
        // into a GWT that tests if it returned null, and if it did, do another GWT with containsKey()
        // that returns constant null (on true), or falls back to next component (on false)
        checkGuard = CONTAINS_MAP;
    } else {
        checkGuard = convertArgToInt(RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor);
    }
    return nextComponent.compose(MethodHandles.guardWithTest(binder.bindTest(checkGuard),
            binder.bind(invocation), nextComponent.getGuardedInvocation().getInvocation()), gi.getGuard(),
            gic.getValidatorClass(), gic.getValidationType());
}
 
Example 16
Source File: DynamicLinker.java    From openjdk-jdk8u-backup with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Relinks a call site conforming to the invocation arguments.
 *
 * @param callSite the call site itself
 * @param arguments arguments to the invocation
 *
 * @return return the method handle for the invocation
 *
 * @throws Exception rethrows any exception thrown by the linkers
 */
@SuppressWarnings("unused")
private MethodHandle relink(final RelinkableCallSite callSite, final int relinkCount, final Object... arguments) throws Exception {
    final CallSiteDescriptor callSiteDescriptor = callSite.getDescriptor();
    final boolean unstableDetectionEnabled = unstableRelinkThreshold > 0;
    final boolean callSiteUnstable = unstableDetectionEnabled && relinkCount >= unstableRelinkThreshold;
    final LinkRequest linkRequest =
            runtimeContextArgCount == 0 ?
                    new LinkRequestImpl(callSiteDescriptor, callSite, relinkCount, callSiteUnstable, arguments) :
                    new RuntimeContextLinkRequestImpl(callSiteDescriptor, callSite, relinkCount, callSiteUnstable, arguments, runtimeContextArgCount);

    GuardedInvocation guardedInvocation = linkerServices.getGuardedInvocation(linkRequest);

    // None found - throw an exception
    if(guardedInvocation == null) {
        throw new NoSuchDynamicMethodException(callSiteDescriptor.toString());
    }

    // If our call sites have a runtime context, and the linker produced a context-stripped invocation, adapt the
    // produced invocation into contextual invocation (by dropping the context...)
    if(runtimeContextArgCount > 0) {
        final MethodType origType = callSiteDescriptor.getMethodType();
        final MethodHandle invocation = guardedInvocation.getInvocation();
        if(invocation.type().parameterCount() == origType.parameterCount() - runtimeContextArgCount) {
            final List<Class<?>> prefix = origType.parameterList().subList(1, runtimeContextArgCount + 1);
            final MethodHandle guard = guardedInvocation.getGuard();
            guardedInvocation = guardedInvocation.dropArguments(1, prefix);
        }
    }

    // Make sure we filter the invocation before linking it into the call site. This is typically used to match the
    // return type of the invocation to the call site.
    guardedInvocation = prelinkFilter.filter(guardedInvocation, linkRequest, linkerServices);
    Objects.requireNonNull(guardedInvocation);

    int newRelinkCount = relinkCount;
    // Note that the short-circuited "&&" evaluation below ensures we'll increment the relinkCount until
    // threshold + 1 but not beyond that. Threshold + 1 is treated as a special value to signal that resetAndRelink
    // has already executed once for the unstable call site; we only want the call site to throw away its current
    // linkage once, when it transitions to unstable.
    if(unstableDetectionEnabled && newRelinkCount <= unstableRelinkThreshold && newRelinkCount++ == unstableRelinkThreshold) {
        callSite.resetAndRelink(guardedInvocation, createRelinkAndInvokeMethod(callSite, newRelinkCount));
    } else {
        callSite.relink(guardedInvocation, createRelinkAndInvokeMethod(callSite, newRelinkCount));
    }
    if(syncOnRelink) {
        MutableCallSite.syncAll(new MutableCallSite[] { (MutableCallSite)callSite });
    }
    return guardedInvocation.getInvocation();
}
 
Example 17
Source File: JavaSuperAdapterLinker.java    From hottub 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 Object(R, T0)
    final MethodHandle typedBinder = BIND_DYNAMIC_METHOD.asType(MethodType.methodType(Object.class,
            invType.returnType(), invType.parameterType(0)));
    // For invocation typed R(T0, T1, ...) create a dynamic method binder of type Object(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
    // Object(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 18
Source File: BeanLinker.java    From jdk8u_nashorn with GNU General Public License v2.0 4 votes vote down vote up
private GuardedInvocationComponent getElementGetter(final CallSiteDescriptor callSiteDescriptor,
        final LinkerServices linkerServices, final List<String> operations) throws Exception {
    final MethodType callSiteType = callSiteDescriptor.getMethodType();
    final Class<?> declaredType = callSiteType.parameterType(0);
    final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor,
            linkerServices, operations);

    // If declared type of receiver at the call site is already an array, a list or map, bind without guard. Thing
    // is, it'd be quite stupid of a call site creator to go though invokedynamic when it knows in advance they're
    // dealing with an array, or a list or map, but hey...
    // Note that for arrays and lists, using LinkerServices.asType() will ensure that any language specific linkers
    // in use will get a chance to perform any (if there's any) implicit conversion to integer for the indices.
    final GuardedInvocationComponent gic;
    final CollectionType collectionType;
    if(declaredType.isArray()) {
        gic = createInternalFilteredGuardedInvocationComponent(MethodHandles.arrayElementGetter(declaredType), linkerServices);
        collectionType = CollectionType.ARRAY;
    } else if(List.class.isAssignableFrom(declaredType)) {
        gic = createInternalFilteredGuardedInvocationComponent(GET_LIST_ELEMENT, linkerServices);
        collectionType = CollectionType.LIST;
    } else if(Map.class.isAssignableFrom(declaredType)) {
        gic = createInternalFilteredGuardedInvocationComponent(GET_MAP_ELEMENT, linkerServices);
        collectionType = CollectionType.MAP;
    } else if(clazz.isArray()) {
        gic = getClassGuardedInvocationComponent(linkerServices.filterInternalObjects(MethodHandles.arrayElementGetter(clazz)), callSiteType);
        collectionType = CollectionType.ARRAY;
    } else if(List.class.isAssignableFrom(clazz)) {
        gic = createInternalFilteredGuardedInvocationComponent(GET_LIST_ELEMENT, Guards.asType(LIST_GUARD, callSiteType), List.class, ValidationType.INSTANCE_OF,
                linkerServices);
        collectionType = CollectionType.LIST;
    } else if(Map.class.isAssignableFrom(clazz)) {
        gic = createInternalFilteredGuardedInvocationComponent(GET_MAP_ELEMENT, Guards.asType(MAP_GUARD, callSiteType), Map.class, ValidationType.INSTANCE_OF,
                linkerServices);
        collectionType = CollectionType.MAP;
    } else {
        // Can't retrieve elements for objects that are neither arrays, nor list, nor maps.
        return nextComponent;
    }

    // We can have "dyn:getElem:foo", especially in composites, i.e. "dyn:getElem|getProp|getMethod:foo"
    final String fixedKey = getFixedKey(callSiteDescriptor);
    // Convert the key to a number if we're working with a list or array
    final Object typedFixedKey;
    if(collectionType != CollectionType.MAP && fixedKey != null) {
        typedFixedKey = convertKeyToInteger(fixedKey, linkerServices);
        if(typedFixedKey == null) {
            // key is not numeric, it can never succeed
            return nextComponent;
        }
    } else {
        typedFixedKey = fixedKey;
    }

    final GuardedInvocation gi = gic.getGuardedInvocation();
    final Binder binder = new Binder(linkerServices, callSiteType, typedFixedKey);
    final MethodHandle invocation = gi.getInvocation();

    if(nextComponent == null) {
        return gic.replaceInvocation(binder.bind(invocation));
    }

    final MethodHandle checkGuard;
    switch(collectionType) {
    case LIST:
        checkGuard = convertArgToInt(RANGE_CHECK_LIST, linkerServices, callSiteDescriptor);
        break;
    case MAP:
        // TODO: A more complex solution could be devised for maps, one where we do a get() first, and fold it
        // into a GWT that tests if it returned null, and if it did, do another GWT with containsKey()
        // that returns constant null (on true), or falls back to next component (on false)
        checkGuard = linkerServices.filterInternalObjects(CONTAINS_MAP);
        break;
    case ARRAY:
        checkGuard = convertArgToInt(RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor);
        break;
    default:
        throw new AssertionError();
    }
    final MethodPair matchedInvocations = matchReturnTypes(binder.bind(invocation),
            nextComponent.getGuardedInvocation().getInvocation());
    return nextComponent.compose(matchedInvocations.guardWithTest(binder.bindTest(checkGuard)), gi.getGuard(),
            gic.getValidatorClass(), gic.getValidationType());
}
 
Example 19
Source File: BeanLinker.java    From hottub with GNU General Public License v2.0 4 votes vote down vote up
private GuardedInvocationComponent getElementGetter(final CallSiteDescriptor callSiteDescriptor,
        final LinkerServices linkerServices, final List<String> operations) throws Exception {
    final MethodType callSiteType = callSiteDescriptor.getMethodType();
    final Class<?> declaredType = callSiteType.parameterType(0);
    final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor,
            linkerServices, operations);

    // If declared type of receiver at the call site is already an array, a list or map, bind without guard. Thing
    // is, it'd be quite stupid of a call site creator to go though invokedynamic when it knows in advance they're
    // dealing with an array, or a list or map, but hey...
    // Note that for arrays and lists, using LinkerServices.asType() will ensure that any language specific linkers
    // in use will get a chance to perform any (if there's any) implicit conversion to integer for the indices.
    final GuardedInvocationComponent gic;
    final CollectionType collectionType;
    if(declaredType.isArray()) {
        gic = createInternalFilteredGuardedInvocationComponent(MethodHandles.arrayElementGetter(declaredType), linkerServices);
        collectionType = CollectionType.ARRAY;
    } else if(List.class.isAssignableFrom(declaredType)) {
        gic = createInternalFilteredGuardedInvocationComponent(GET_LIST_ELEMENT, linkerServices);
        collectionType = CollectionType.LIST;
    } else if(Map.class.isAssignableFrom(declaredType)) {
        gic = createInternalFilteredGuardedInvocationComponent(GET_MAP_ELEMENT, linkerServices);
        collectionType = CollectionType.MAP;
    } else if(clazz.isArray()) {
        gic = getClassGuardedInvocationComponent(linkerServices.filterInternalObjects(MethodHandles.arrayElementGetter(clazz)), callSiteType);
        collectionType = CollectionType.ARRAY;
    } else if(List.class.isAssignableFrom(clazz)) {
        gic = createInternalFilteredGuardedInvocationComponent(GET_LIST_ELEMENT, Guards.asType(LIST_GUARD, callSiteType), List.class, ValidationType.INSTANCE_OF,
                linkerServices);
        collectionType = CollectionType.LIST;
    } else if(Map.class.isAssignableFrom(clazz)) {
        gic = createInternalFilteredGuardedInvocationComponent(GET_MAP_ELEMENT, Guards.asType(MAP_GUARD, callSiteType), Map.class, ValidationType.INSTANCE_OF,
                linkerServices);
        collectionType = CollectionType.MAP;
    } else {
        // Can't retrieve elements for objects that are neither arrays, nor list, nor maps.
        return nextComponent;
    }

    // We can have "dyn:getElem:foo", especially in composites, i.e. "dyn:getElem|getProp|getMethod:foo"
    final String fixedKey = getFixedKey(callSiteDescriptor);
    // Convert the key to a number if we're working with a list or array
    final Object typedFixedKey;
    if(collectionType != CollectionType.MAP && fixedKey != null) {
        typedFixedKey = convertKeyToInteger(fixedKey, linkerServices);
        if(typedFixedKey == null) {
            // key is not numeric, it can never succeed
            return nextComponent;
        }
    } else {
        typedFixedKey = fixedKey;
    }

    final GuardedInvocation gi = gic.getGuardedInvocation();
    final Binder binder = new Binder(linkerServices, callSiteType, typedFixedKey);
    final MethodHandle invocation = gi.getInvocation();

    if(nextComponent == null) {
        return gic.replaceInvocation(binder.bind(invocation));
    }

    final MethodHandle checkGuard;
    switch(collectionType) {
    case LIST:
        checkGuard = convertArgToInt(RANGE_CHECK_LIST, linkerServices, callSiteDescriptor);
        break;
    case MAP:
        // TODO: A more complex solution could be devised for maps, one where we do a get() first, and fold it
        // into a GWT that tests if it returned null, and if it did, do another GWT with containsKey()
        // that returns constant null (on true), or falls back to next component (on false)
        checkGuard = linkerServices.filterInternalObjects(CONTAINS_MAP);
        break;
    case ARRAY:
        checkGuard = convertArgToInt(RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor);
        break;
    default:
        throw new AssertionError();
    }
    final MethodPair matchedInvocations = matchReturnTypes(binder.bind(invocation),
            nextComponent.getGuardedInvocation().getInvocation());
    return nextComponent.compose(matchedInvocations.guardWithTest(binder.bindTest(checkGuard)), gi.getGuard(),
            gic.getValidatorClass(), gic.getValidationType());
}
 
Example 20
Source File: DynamicLinker.java    From hottub with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Relinks a call site conforming to the invocation arguments.
 *
 * @param callSite the call site itself
 * @param arguments arguments to the invocation
 *
 * @return return the method handle for the invocation
 *
 * @throws Exception rethrows any exception thrown by the linkers
 */
@SuppressWarnings("unused")
private MethodHandle relink(final RelinkableCallSite callSite, final int relinkCount, final Object... arguments) throws Exception {
    final CallSiteDescriptor callSiteDescriptor = callSite.getDescriptor();
    final boolean unstableDetectionEnabled = unstableRelinkThreshold > 0;
    final boolean callSiteUnstable = unstableDetectionEnabled && relinkCount >= unstableRelinkThreshold;
    final LinkRequest linkRequest =
            runtimeContextArgCount == 0 ?
                    new LinkRequestImpl(callSiteDescriptor, callSite, relinkCount, callSiteUnstable, arguments) :
                    new RuntimeContextLinkRequestImpl(callSiteDescriptor, callSite, relinkCount, callSiteUnstable, arguments, runtimeContextArgCount);

    GuardedInvocation guardedInvocation = linkerServices.getGuardedInvocation(linkRequest);

    // None found - throw an exception
    if(guardedInvocation == null) {
        throw new NoSuchDynamicMethodException(callSiteDescriptor.toString());
    }

    // If our call sites have a runtime context, and the linker produced a context-stripped invocation, adapt the
    // produced invocation into contextual invocation (by dropping the context...)
    if(runtimeContextArgCount > 0) {
        final MethodType origType = callSiteDescriptor.getMethodType();
        final MethodHandle invocation = guardedInvocation.getInvocation();
        if(invocation.type().parameterCount() == origType.parameterCount() - runtimeContextArgCount) {
            final List<Class<?>> prefix = origType.parameterList().subList(1, runtimeContextArgCount + 1);
            final MethodHandle guard = guardedInvocation.getGuard();
            guardedInvocation = guardedInvocation.dropArguments(1, prefix);
        }
    }

    // Make sure we filter the invocation before linking it into the call site. This is typically used to match the
    // return type of the invocation to the call site.
    guardedInvocation = prelinkFilter.filter(guardedInvocation, linkRequest, linkerServices);
    Objects.requireNonNull(guardedInvocation);

    int newRelinkCount = relinkCount;
    // Note that the short-circuited "&&" evaluation below ensures we'll increment the relinkCount until
    // threshold + 1 but not beyond that. Threshold + 1 is treated as a special value to signal that resetAndRelink
    // has already executed once for the unstable call site; we only want the call site to throw away its current
    // linkage once, when it transitions to unstable.
    if(unstableDetectionEnabled && newRelinkCount <= unstableRelinkThreshold && newRelinkCount++ == unstableRelinkThreshold) {
        callSite.resetAndRelink(guardedInvocation, createRelinkAndInvokeMethod(callSite, newRelinkCount));
    } else {
        callSite.relink(guardedInvocation, createRelinkAndInvokeMethod(callSite, newRelinkCount));
    }
    if(syncOnRelink) {
        MutableCallSite.syncAll(new MutableCallSite[] { (MutableCallSite)callSite });
    }
    return guardedInvocation.getInvocation();
}