Java Code Examples for java.lang.invoke.MethodHandle#type()

The following examples show how to use java.lang.invoke.MethodHandle#type() . These examples are extracted from open source projects. 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
public CatchExceptionTest(TestCase testCase, final boolean isVararg, final int argsCount,
        final int catchDrops) {
    this.testCase = testCase;
    this.dropped = catchDrops;
    MethodHandle thrower = testCase.thrower;
    int throwerLen = thrower.type().parameterCount();
    List<Class<?>> classes;
    int extra = Math.max(0, argsCount - throwerLen);
    classes = getThrowerParams(isVararg, extra);
    this.argsCount = throwerLen + classes.size();
    thrower = Helper.addTrailingArgs(thrower, this.argsCount, classes);
    if (isVararg && argsCount > throwerLen) {
        MethodType mt = thrower.type();
        Class<?> lastParam = mt.parameterType(mt.parameterCount() - 1);
        thrower = thrower.asVarargsCollector(lastParam);
    }
    this.thrower = thrower;
    this.dropped = Math.min(this.argsCount, catchDrops);
    catcher = testCase.getCatcher(getCatcherParams());
    nargs = Math.max(2, this.argsCount);
}
 
Example 2
private static MethodHandle bindToNameIfNeeded(final MethodHandle methodHandle, final String bindName) {
    if (bindName == null) {
        return methodHandle;
    }

    // if it is vararg method, we need to extend argument array with
    // a new zeroth element that is set to bindName value.
    final MethodType methodType = methodHandle.type();
    final int parameterCount = methodType.parameterCount();
    final boolean isVarArg = parameterCount > 0 && methodType.parameterType(parameterCount - 1).isArray();

    if (isVarArg) {
        return MH.filterArguments(methodHandle, 1, MH.insertArguments(ADD_ZEROTH_ELEMENT, 1, bindName));
    }
    return MH.insertArguments(methodHandle, 1, bindName);
}
 
Example 3
private static MethodHandle bindToNameIfNeeded(final MethodHandle methodHandle, final String bindName) {
    if (bindName == null) {
        return methodHandle;
    }

    // if it is vararg method, we need to extend argument array with
    // a new zeroth element that is set to bindName value.
    final MethodType methodType = methodHandle.type();
    final int parameterCount = methodType.parameterCount();
    final boolean isVarArg = parameterCount > 0 && methodType.parameterType(parameterCount - 1).isArray();

    if (isVarArg) {
        return MH.filterArguments(methodHandle, 1, MH.insertArguments(ADD_ZEROTH_ELEMENT, 1, bindName));
    }
    return MH.insertArguments(methodHandle, 1, bindName);
}
 
Example 4
/**
 * This method is used to create the immutable portion of a bound function.
 * See {@link ScriptFunction#makeBoundFunction(Object, Object[])}
 *
 * @param fn the original function being bound
 * @param self this reference to bind. Can be null.
 * @param args additional arguments to bind. Can be null.
 */
ScriptFunctionData makeBoundFunctionData(final ScriptFunction fn, final Object self, final Object[] args) {
    ensureCodeGenerated();

    final Object[] allArgs = args == null ? ScriptRuntime.EMPTY_ARRAY : args;
    final int length = args == null ? 0 : args.length;

    CompiledFunctions boundList = new CompiledFunctions();
    if (code.size() == 1) {
        // only one variant - bind that
        boundList.add(bind(code.first(), fn, self, allArgs));
    } else {
        // There are specialized versions. Get the most generic one.
        // This is to avoid ambiguous overloaded versions of bound and
        // specialized variants and choosing wrong overload.
        final MethodHandle genInvoker = getGenericInvoker();
        final CompiledFunction inv = new CompiledFunction(genInvoker.type(), genInvoker, getGenericConstructor());
        boundList.add(bind(inv, fn, self, allArgs));
    }

    ScriptFunctionData boundData = new FinalScriptFunctionData(name, arity == -1 ? -1 : Math.max(0, arity - length), boundList, isStrict(), isBuiltin(), isConstructor());
    return boundData;
}
 
Example 5
static MethodPair matchReturnTypes(final MethodHandle m1, final MethodHandle m2) {
    final MethodType type1 = m1.type();
    final MethodType type2 = m2.type();
    final Class<?> commonRetType = InternalTypeUtilities.getCommonLosslessConversionType(type1.returnType(),
            type2.returnType());
    return new MethodPair(
            m1.asType(type1.changeReturnType(commonRetType)),
            m2.asType(type2.changeReturnType(commonRetType)));
}
 
Example 6
Source Project: es6draft   File: Properties.java    License: MIT License 5 votes vote down vote up
private static MethodHandle getComputedValueMethodHandle(Lookup lookup, Method method)
        throws IllegalAccessException {
    // check: (ExecutionContext) -> Object
    MethodHandle handle = lookup.unreflect(method);
    MethodType type = handle.type();
    if (type.parameterCount() != 1 || !ExecutionContext.class.equals(type.parameterType(0))) {
        throw new IllegalArgumentException(handle.toString());
    }
    if (!Object.class.equals(type.returnType())) {
        throw new IllegalArgumentException(handle.toString());
    }
    return handle;
}
 
Example 7
/**
 * Compose a constructor given a primordial constructor handle.
 *
 * @param ctor primordial constructor handle
 * @return the composed constructor
 */
protected MethodHandle composeConstructor(final MethodHandle ctor) {
    // If it was (callee, this, args...), permute it to (this, callee, args...). We're doing this because having
    // "this" in the first argument position is what allows the elegant folded composition of
    // (newFilter x constructor x allocator) further down below in the code. Also, ensure the composite constructor
    // always returns Object.
    final boolean needsCallee = needsCallee(ctor);
    MethodHandle composedCtor = needsCallee ? swapCalleeAndThis(ctor) : ctor;

    composedCtor = changeReturnTypeToObject(composedCtor);

    final MethodType ctorType = composedCtor.type();

    // Construct a dropping type list for NEWFILTER, but don't include constructor "this" into it, so it's actually
    // captured as "allocation" parameter of NEWFILTER after we fold the constructor into it.
    // (this, [callee, ]args...) => ([callee, ]args...)
    final Class<?>[] ctorArgs = ctorType.dropParameterTypes(0, 1).parameterArray();

    // Fold constructor into newFilter that replaces the return value from the constructor with the originally
    // allocated value when the originally allocated value is a primitive.
    // (result, this, [callee, ]args...) x (this, [callee, ]args...) => (this, [callee, ]args...)
    composedCtor = MH.foldArguments(MH.dropArguments(NEWFILTER, 2, ctorArgs), composedCtor);

    // allocate() takes a ScriptFunction and returns a newly allocated ScriptObject...
    if (needsCallee) {
        // ...we either fold it into the previous composition, if we need both the ScriptFunction callee object and
        // the newly allocated object in the arguments, so (this, callee, args...) x (callee) => (callee, args...),
        // or...
        return MH.foldArguments(composedCtor, ScriptFunction.ALLOCATE);
    }

    // ...replace the ScriptFunction argument with the newly allocated object, if it doesn't need the callee
    // (this, args...) filter (callee) => (callee, args...)
    return MH.filterArguments(composedCtor, 0, ScriptFunction.ALLOCATE);
}
 
Example 8
/**
 * Compose a constructor from an invoker.
 *
 * @param invoker         invoker
 * @return the composed constructor
 */
private static MethodHandle createConstructorFromInvoker(final MethodHandle invoker) {
    final boolean needsCallee = ScriptFunctionData.needsCallee(invoker);
    // If it was (callee, this, args...), permute it to (this, callee, args...). We're doing this because having
    // "this" in the first argument position is what allows the elegant folded composition of
    // (newFilter x constructor x allocator) further down below in the code. Also, ensure the composite constructor
    // always returns Object.
    final MethodHandle swapped = needsCallee ? swapCalleeAndThis(invoker) : invoker;

    final MethodHandle returnsObject = MH.asType(swapped, swapped.type().changeReturnType(Object.class));

    final MethodType ctorType = returnsObject.type();

    // Construct a dropping type list for NEWFILTER, but don't include constructor "this" into it, so it's actually
    // captured as "allocation" parameter of NEWFILTER after we fold the constructor into it.
    // (this, [callee, ]args...) => ([callee, ]args...)
    final Class<?>[] ctorArgs = ctorType.dropParameterTypes(0, 1).parameterArray();

    // Fold constructor into newFilter that replaces the return value from the constructor with the originally
    // allocated value when the originally allocated value is a JS primitive (String, Boolean, Number).
    // (result, this, [callee, ]args...) x (this, [callee, ]args...) => (this, [callee, ]args...)
    final MethodHandle filtered = MH.foldArguments(MH.dropArguments(NEWFILTER, 2, ctorArgs), returnsObject);

    // allocate() takes a ScriptFunction and returns a newly allocated ScriptObject...
    if (needsCallee) {
        // ...we either fold it into the previous composition, if we need both the ScriptFunction callee object and
        // the newly allocated object in the arguments, so (this, callee, args...) x (callee) => (callee, args...),
        // or...
        return MH.foldArguments(filtered, ScriptFunction.ALLOCATE);
    }

    // ...replace the ScriptFunction argument with the newly allocated object, if it doesn't need the callee
    // (this, args...) filter (callee) => (callee, args...)
    return MH.filterArguments(filtered, 0, ScriptFunction.ALLOCATE);
}
 
Example 9
private MethodHandle getFallbackLoggingRelink(final MethodHandle relink) {
    if (!getNashornDescriptor().isTraceMisses()) {
        // If we aren't tracing misses, just return relink as-is
        return relink;
    }
    final MethodType type = relink.type();
    return MH.foldArguments(relink, MH.asType(MH.asCollector(MH.insertArguments(TRACEMISS, 0, this, "MISS " + getScriptLocation() + " "), Object[].class, type.parameterCount()), type.changeReturnType(void.class)));
}
 
Example 10
CompiledFunction bind(final CompiledFunction originalInv, final ScriptFunction fn, final Object self, final Object[] args) {
    final MethodHandle boundInvoker = bindInvokeHandle(originalInv.getInvoker(), fn, self, args);

    //TODO the boundinvoker.type() could actually be more specific here
    if (isConstructor()) {
        ensureConstructor(originalInv);
        return new CompiledFunction(boundInvoker.type(), boundInvoker, bindConstructHandle(originalInv.getConstructor(), fn, args));
    }

    return new CompiledFunction(boundInvoker.type(), boundInvoker);
}
 
Example 11
private static GuardedInvocation fixExpressionCallSite(final CallSiteDescriptor 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 (NashornCallSiteDescriptor.getBaseOperation(desc) != StandardOperation.GET || !NashornCallSiteDescriptor.isMethodFirstOperation(desc)) {
        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 12
Source Project: hottub   File: WithObject.java    License: 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 13
/**
 * Given a method handle and an expected return type, perform return value filtering
 * according to the optimistic type coercion rules
 * @param mh method handle
 * @param expectedReturnType expected return type
 * @param programPoint program point
 * @return filtered method
 */
public static MethodHandle filterOptimisticReturnValue(final MethodHandle mh, final Class<?> expectedReturnType, final int programPoint) {
    if(!isValid(programPoint)) {
        return mh;
    }

    final MethodType type = mh.type();
    final Class<?> actualReturnType = type.returnType();
    if(TypeUtilities.isConvertibleWithoutLoss(actualReturnType, expectedReturnType)) {
        return mh;
    }

    final MethodHandle guard = getOptimisticTypeGuard(expectedReturnType, actualReturnType);
    return guard == null ? mh : MH.filterReturnValue(mh, MH.insertArguments(guard, guard.type().parameterCount() - 1, programPoint));
}
 
Example 14
private static CompiledFunction makeGeneric(final CompiledFunction func) {
    final MethodHandle invoker = composeGenericMethod(func.getInvoker());
    final MethodHandle constructor = func.hasConstructor() ? composeGenericMethod(func.getConstructor()) : null;
    return new CompiledFunction(invoker.type(), invoker, constructor);
}
 
Example 15
private static void assertType(MethodHandle mh, MethodType type) {
    if(!mh.type().equals(type)) {
        throw new WrongMethodTypeException("Expected type: " + type + " actual type: " + mh.type());
    }
}
 
Example 16
/**
 * Make sure arguments are paired correctly, with respect to more parameters than declared,
 * fewer parameters than declared and other things that JavaScript allows. This might involve
 * creating collectors.
 *
 * Make sure arguments are paired correctly.
 * @param methodHandle MethodHandle to adjust.
 * @param callType     MethodType of the call site.
 * @param callerVarArg true if the caller is vararg, false otherwise, null if it should be inferred from the
 * {@code callType}; basically, if the last parameter type of the call site is an array, it'll be considered a
 * variable arity call site. These are ordinarily rare; Nashorn code generator creates variable arity call sites
 * when the call has more than {@link LinkerCallSite#ARGLIMIT} parameters.
 *
 * @return method handle with adjusted arguments
 */
public static MethodHandle pairArguments(final MethodHandle methodHandle, final MethodType callType, final Boolean callerVarArg) {
    final MethodType methodType = methodHandle.type();
    if (methodType.equals(callType.changeReturnType(methodType.returnType()))) {
        return methodHandle;
    }

    final int parameterCount = methodType.parameterCount();
    final int callCount      = callType.parameterCount();

    final boolean isCalleeVarArg = parameterCount > 0 && methodType.parameterType(parameterCount - 1).isArray();
    final boolean isCallerVarArg = callerVarArg != null ? callerVarArg : callCount > 0 &&
            callType.parameterType(callCount - 1).isArray();

    if (isCalleeVarArg) {
        return isCallerVarArg ?
            methodHandle :
            MH.asCollector(methodHandle, Object[].class, callCount - parameterCount + 1);
    }

    if (isCallerVarArg) {
        return adaptHandleToVarArgCallSite(methodHandle, callCount);
    }

    if (callCount < parameterCount) {
        final int      missingArgs = parameterCount - callCount;
        final Object[] fillers     = new Object[missingArgs];

        Arrays.fill(fillers, UNDEFINED);

        if (isCalleeVarArg) {
            fillers[missingArgs - 1] = ScriptRuntime.EMPTY_ARRAY;
        }

        return MH.insertArguments(
            methodHandle,
            parameterCount - missingArgs,
            fillers);
    }

    if (callCount > parameterCount) {
        final int discardedArgs = callCount - parameterCount;

        final Class<?>[] discards = new Class<?>[discardedArgs];
        Arrays.fill(discards, Object.class);

        return MH.dropArguments(methodHandle, callCount - discardedArgs, discards);
    }

    return methodHandle;
}
 
Example 17
/**
 * Make sure arguments are paired correctly, with respect to more parameters than declared,
 * fewer parameters than declared and other things that JavaScript allows. This might involve
 * creating collectors.
 *
 * Make sure arguments are paired correctly.
 * @param methodHandle MethodHandle to adjust.
 * @param callType     MethodType of the call site.
 * @param callerVarArg true if the caller is vararg, false otherwise, null if it should be inferred from the
 * {@code callType}; basically, if the last parameter type of the call site is an array, it'll be considered a
 * variable arity call site. These are ordinarily rare; Nashorn code generator creates variable arity call sites
 * when the call has more than {@link LinkerCallSite#ARGLIMIT} parameters.
 *
 * @return method handle with adjusted arguments
 */
public static MethodHandle pairArguments(final MethodHandle methodHandle, final MethodType callType, final Boolean callerVarArg) {
    final MethodType methodType = methodHandle.type();
    if (methodType.equals(callType.changeReturnType(methodType.returnType()))) {
        return methodHandle;
    }

    final int parameterCount = methodType.parameterCount();
    final int callCount      = callType.parameterCount();

    final boolean isCalleeVarArg = parameterCount > 0 && methodType.parameterType(parameterCount - 1).isArray();
    final boolean isCallerVarArg = callerVarArg != null ? callerVarArg : callCount > 0 &&
            callType.parameterType(callCount - 1).isArray();

    if (isCalleeVarArg) {
        return isCallerVarArg ?
            methodHandle :
            MH.asCollector(methodHandle, Object[].class, callCount - parameterCount + 1);
    }

    if (isCallerVarArg) {
        return adaptHandleToVarArgCallSite(methodHandle, callCount);
    }

    if (callCount < parameterCount) {
        final int      missingArgs = parameterCount - callCount;
        final Object[] fillers     = new Object[missingArgs];

        Arrays.fill(fillers, UNDEFINED);

        if (isCalleeVarArg) {
            fillers[missingArgs - 1] = ScriptRuntime.EMPTY_ARRAY;
        }

        return MH.insertArguments(
            methodHandle,
            parameterCount - missingArgs,
            fillers);
    }

    if (callCount > parameterCount) {
        final int discardedArgs = callCount - parameterCount;

        final Class<?>[] discards = new Class<?>[discardedArgs];
        Arrays.fill(discards, Object.class);

        return MH.dropArguments(methodHandle, callCount - discardedArgs, discards);
    }

    return methodHandle;
}
 
Example 18
@Override
MethodType getMethodType(final MethodHandle t) {
    return t.type();
}
 
Example 19
/**
 * Make sure arguments are paired correctly, with respect to more parameters than declared,
 * fewer parameters than declared and other things that JavaScript allows. This might involve
 * creating collectors.
 *
 * Make sure arguments are paired correctly.
 * @param methodHandle MethodHandle to adjust.
 * @param callType     MethodType of the call site.
 * @param callerVarArg true if the caller is vararg, false otherwise, null if it should be inferred from the
 * {@code callType}; basically, if the last parameter type of the call site is an array, it'll be considered a
 * variable arity call site. These are ordinarily rare; Nashorn code generator creates variable arity call sites
 * when the call has more than {@link LinkerCallSite#ARGLIMIT} parameters.
 *
 * @return method handle with adjusted arguments
 */
public static MethodHandle pairArguments(final MethodHandle methodHandle, final MethodType callType, final Boolean callerVarArg) {
    final MethodType methodType = methodHandle.type();
    if (methodType.equals(callType.changeReturnType(methodType.returnType()))) {
        return methodHandle;
    }

    final int parameterCount = methodType.parameterCount();
    final int callCount      = callType.parameterCount();

    final boolean isCalleeVarArg = parameterCount > 0 && methodType.parameterType(parameterCount - 1).isArray();
    final boolean isCallerVarArg = callerVarArg != null ? callerVarArg : callCount > 0 &&
            callType.parameterType(callCount - 1).isArray();

    if (isCalleeVarArg) {
        return isCallerVarArg ?
            methodHandle :
            MH.asCollector(methodHandle, Object[].class, callCount - parameterCount + 1);
    }

    if (isCallerVarArg) {
        return adaptHandleToVarArgCallSite(methodHandle, callCount);
    }

    if (callCount < parameterCount) {
        final int      missingArgs = parameterCount - callCount;
        final Object[] fillers     = new Object[missingArgs];

        Arrays.fill(fillers, UNDEFINED);

        if (isCalleeVarArg) {
            fillers[missingArgs - 1] = ScriptRuntime.EMPTY_ARRAY;
        }

        return MH.insertArguments(
            methodHandle,
            parameterCount - missingArgs,
            fillers);
    }

    if (callCount > parameterCount) {
        final int discardedArgs = callCount - parameterCount;

        final Class<?>[] discards = new Class<?>[discardedArgs];
        Arrays.fill(discards, Object.class);

        return MH.dropArguments(methodHandle, callCount - discardedArgs, discards);
    }

    return methodHandle;
}
 
Example 20
/**
 * Adapts the method handle so its return type is {@code Object}. If the handle's return type is already
 * {@code Object}, the handle is returned unchanged.
 *
 * @param mh the handle to adapt
 * @return the adapted handle
 */
private static MethodHandle changeReturnTypeToObject(final MethodHandle mh) {
    final MethodType type = mh.type();
    return (type.returnType() == Object.class) ? mh : MH.asType(mh, type.changeReturnType(Object.class));
}