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

The following examples show how to use java.lang.invoke.MethodHandle#isVarargsCollector() . 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
Source Project: es6draft   File: NativeCalls.java    License: MIT License 6 votes vote down vote up
private static MethodHandle adaptNativeMethodHandle(MethodHandle mh) {
    MethodType type = mh.type();
    boolean varargs = mh.isVarargsCollector();
    // Allow to omit execution context argument.
    if (type.parameterCount() == 0 || !type.parameterType(0).equals(ExecutionContext.class)) {
        mh = MethodHandles.dropArguments(mh, 0, ExecutionContext.class);
    }
    // Allow void return type.
    if (type.returnType() == void.class) {
        mh = MethodHandles.filterReturnValue(mh, MethodHandles.constant(Object.class, UNDEFINED));
    }
    // Restore var-args flag.
    if (varargs && !mh.isVarargsCollector()) {
        mh = mh.asVarargsCollector(mh.type().parameterType(mh.type().parameterCount() - 1));
    }
    return mh;
}
 
Example 2
Source Project: es6draft   File: NativeCalls.java    License: MIT License 6 votes vote down vote up
private static MethodHandle forSpreadCall(MethodHandle mh, MethodType type) {
    int expectedParameters = mh.type().parameterCount();
    int actualParameters = type.parameterCount();
    if (!mh.isVarargsCollector() || !mh.type().parameterType(expectedParameters - 1).equals(Object[].class)) {
        throw new WrongMethodTypeException("Not Object[] var-args collector");
    }
    if (expectedParameters > actualParameters) {
        throw new WrongMethodTypeException("Too few arguments");
    }
    if (expectedParameters < actualParameters) {
        int fixedCount = actualParameters - expectedParameters;
        int firstFixed = expectedParameters - 1;
        List<Class<?>> fixed = type.parameterList().subList(firstFixed, firstFixed + fixedCount);
        mh = MethodHandles.collectArguments(mh, firstFixed, combineArraysMH);
        mh = MethodHandles.collectArguments(mh, firstFixed, toObjectArray(fixed));
    }
    return mh.asType(type);
}
 
Example 3
private static MethodHandle dropReceiver(final MethodHandle mh, final Class<?> receiverClass) {
    MethodHandle newHandle = MethodHandles.dropArguments(mh, 0, receiverClass);
    // NOTE: this is a workaround for the fact that dropArguments doesn't preserve vararg collector state.
    if(mh.isVarargsCollector() && !newHandle.isVarargsCollector()) {
        final MethodType type = mh.type();
        newHandle = newHandle.asVarargsCollector(type.parameterType(type.parameterCount() - 1));
    }
    return newHandle;
}
 
Example 4
OverloadedMethod(final List<MethodHandle> methodHandles, final OverloadedDynamicMethod parent, final MethodType callSiteType,
        final LinkerServices linkerServices) {
    this.parent = parent;
    final Class<?> commonRetType = getCommonReturnType(methodHandles);
    this.callSiteType = callSiteType.changeReturnType(commonRetType);
    this.linkerServices = linkerServices;

    fixArgMethods = new ArrayList<>(methodHandles.size());
    varArgMethods = new ArrayList<>(methodHandles.size());
    final int argNum = callSiteType.parameterCount();
    for(MethodHandle mh: methodHandles) {
        if(mh.isVarargsCollector()) {
            final MethodHandle asFixed = mh.asFixedArity();
            if(argNum == asFixed.type().parameterCount()) {
                fixArgMethods.add(asFixed);
            }
            varArgMethods.add(mh);
        } else {
            fixArgMethods.add(mh);
        }
    }
    fixArgMethods.trimToSize();
    varArgMethods.trimToSize();

    final MethodHandle bound = SELECT_METHOD.bindTo(this);
    final MethodHandle collecting = SingleDynamicMethod.collectArguments(bound, argNum).asType(
            callSiteType.changeReturnType(MethodHandle.class));
    invoker = linkerServices.asTypeLosslessReturn(MethodHandles.foldArguments(
            MethodHandles.exactInvoker(this.callSiteType), collecting), callSiteType);
}
 
Example 5
private static MethodHandle dropReceiver(final MethodHandle mh, final Class<?> receiverClass) {
    MethodHandle newHandle = MethodHandles.dropArguments(mh, 0, receiverClass);
    // NOTE: this is a workaround for the fact that dropArguments doesn't preserve vararg collector state.
    if(mh.isVarargsCollector() && !newHandle.isVarargsCollector()) {
        final MethodType type = mh.type();
        newHandle = newHandle.asVarargsCollector(type.parameterType(type.parameterCount() - 1));
    }
    return newHandle;
}
 
Example 6
OverloadedMethod(final List<MethodHandle> methodHandles, final OverloadedDynamicMethod parent, final MethodType callSiteType,
        final LinkerServices linkerServices) {
    this.parent = parent;
    final Class<?> commonRetType = getCommonReturnType(methodHandles);
    this.callSiteType = callSiteType.changeReturnType(commonRetType);
    this.linkerServices = linkerServices;

    fixArgMethods = new ArrayList<>(methodHandles.size());
    varArgMethods = new ArrayList<>(methodHandles.size());
    final int argNum = callSiteType.parameterCount();
    for(MethodHandle mh: methodHandles) {
        if(mh.isVarargsCollector()) {
            final MethodHandle asFixed = mh.asFixedArity();
            if(argNum == asFixed.type().parameterCount()) {
                fixArgMethods.add(asFixed);
            }
            varArgMethods.add(mh);
        } else {
            fixArgMethods.add(mh);
        }
    }
    fixArgMethods.trimToSize();
    varArgMethods.trimToSize();

    final MethodHandle bound = SELECT_METHOD.bindTo(this);
    final MethodHandle collecting = SingleDynamicMethod.collectArguments(bound, argNum).asType(
            callSiteType.changeReturnType(MethodHandle.class));
    invoker = linkerServices.asTypeLosslessReturn(MethodHandles.foldArguments(
            MethodHandles.exactInvoker(this.callSiteType), collecting), callSiteType);
}
 
Example 7
OverloadedMethod(final List<MethodHandle> methodHandles, final OverloadedDynamicMethod parent, final MethodType callSiteType,
        final LinkerServices linkerServices) {
    this.parent = parent;
    final Class<?> commonRetType = getCommonReturnType(methodHandles);
    this.callSiteType = callSiteType.changeReturnType(commonRetType);
    this.linkerServices = linkerServices;

    fixArgMethods = new ArrayList<>(methodHandles.size());
    varArgMethods = new ArrayList<>(methodHandles.size());
    final int argNum = callSiteType.parameterCount();
    for(MethodHandle mh: methodHandles) {
        if(mh.isVarargsCollector()) {
            final MethodHandle asFixed = mh.asFixedArity();
            if(argNum == asFixed.type().parameterCount()) {
                fixArgMethods.add(asFixed);
            }
            varArgMethods.add(mh);
        } else {
            fixArgMethods.add(mh);
        }
    }
    fixArgMethods.trimToSize();
    varArgMethods.trimToSize();

    final MethodHandle bound = SELECT_METHOD.bindTo(this);
    final MethodHandle collecting = SingleDynamicMethod.collectArguments(bound, argNum).asType(
            callSiteType.changeReturnType(MethodHandle.class));
    invoker = linkerServices.asTypeLosslessReturn(MethodHandles.foldArguments(
            MethodHandles.exactInvoker(this.callSiteType), collecting), callSiteType);
}
 
Example 8
private static MethodHandle dropReceiver(final MethodHandle mh, final Class<?> receiverClass) {
    MethodHandle newHandle = MethodHandles.dropArguments(mh, 0, receiverClass);
    // NOTE: this is a workaround for the fact that dropArguments doesn't preserve vararg collector state.
    if(mh.isVarargsCollector() && !newHandle.isVarargsCollector()) {
        final MethodType type = mh.type();
        newHandle = newHandle.asVarargsCollector(type.parameterType(type.parameterCount() - 1));
    }
    return newHandle;
}
 
Example 9
OverloadedMethod(final List<MethodHandle> methodHandles, final OverloadedDynamicMethod parent, final MethodType callSiteType,
        final LinkerServices linkerServices) {
    this.parent = parent;
    final Class<?> commonRetType = getCommonReturnType(methodHandles);
    this.callSiteType = callSiteType.changeReturnType(commonRetType);
    this.linkerServices = linkerServices;

    fixArgMethods = new ArrayList<>(methodHandles.size());
    varArgMethods = new ArrayList<>(methodHandles.size());
    final int argNum = callSiteType.parameterCount();
    for(MethodHandle mh: methodHandles) {
        if(mh.isVarargsCollector()) {
            final MethodHandle asFixed = mh.asFixedArity();
            if(argNum == asFixed.type().parameterCount()) {
                fixArgMethods.add(asFixed);
            }
            varArgMethods.add(mh);
        } else {
            fixArgMethods.add(mh);
        }
    }
    fixArgMethods.trimToSize();
    varArgMethods.trimToSize();

    final MethodHandle bound = SELECT_METHOD.bindTo(this);
    final MethodHandle collecting = SingleDynamicMethod.collectArguments(bound, argNum).asType(
            callSiteType.changeReturnType(MethodHandle.class));
    invoker = linkerServices.asTypeLosslessReturn(MethodHandles.foldArguments(
            MethodHandles.exactInvoker(this.callSiteType), collecting), callSiteType);
}
 
Example 10
private static MethodHandle dropReceiver(final MethodHandle mh, final Class<?> receiverClass) {
    MethodHandle newHandle = MethodHandles.dropArguments(mh, 0, receiverClass);
    // NOTE: this is a workaround for the fact that dropArguments doesn't preserve vararg collector state.
    if(mh.isVarargsCollector() && !newHandle.isVarargsCollector()) {
        final MethodType type = mh.type();
        newHandle = newHandle.asVarargsCollector(type.parameterType(type.parameterCount() - 1));
    }
    return newHandle;
}
 
Example 11
private static MethodHandle dropReceiver(final MethodHandle mh, final Class<?> receiverClass) {
    MethodHandle newHandle = MethodHandles.dropArguments(mh, 0, receiverClass);
    // NOTE: this is a workaround for the fact that dropArguments doesn't preserve vararg collector state.
    if(mh.isVarargsCollector() && !newHandle.isVarargsCollector()) {
        final MethodType type = mh.type();
        newHandle = newHandle.asVarargsCollector(type.parameterType(type.parameterCount() - 1));
    }
    return newHandle;
}
 
Example 12
OverloadedMethod(final List<MethodHandle> methodHandles, final OverloadedDynamicMethod parent, final MethodType callSiteType,
        final LinkerServices linkerServices) {
    this.parent = parent;
    final Class<?> commonRetType = getCommonReturnType(methodHandles);
    this.callSiteType = callSiteType.changeReturnType(commonRetType);
    this.linkerServices = linkerServices;

    fixArgMethods = new ArrayList<>(methodHandles.size());
    varArgMethods = new ArrayList<>(methodHandles.size());
    final int argNum = callSiteType.parameterCount();
    for(MethodHandle mh: methodHandles) {
        if(mh.isVarargsCollector()) {
            final MethodHandle asFixed = mh.asFixedArity();
            if(argNum == asFixed.type().parameterCount()) {
                fixArgMethods.add(asFixed);
            }
            varArgMethods.add(mh);
        } else {
            fixArgMethods.add(mh);
        }
    }
    fixArgMethods.trimToSize();
    varArgMethods.trimToSize();

    final MethodHandle bound = SELECT_METHOD.bindTo(this);
    final MethodHandle collecting = SingleDynamicMethod.collectArguments(bound, argNum).asType(
            callSiteType.changeReturnType(MethodHandle.class));
    invoker = linkerServices.asTypeLosslessReturn(MethodHandles.foldArguments(
            MethodHandles.exactInvoker(this.callSiteType), collecting), callSiteType);
}
 
Example 13
OverloadedMethod(List<MethodHandle> methodHandles, OverloadedDynamicMethod parent, MethodType callSiteType,
        LinkerServices linkerServices) {
    this.parent = parent;
    this.callSiteType = callSiteType;
    this.linkerServices = linkerServices;

    fixArgMethods = new ArrayList<>(methodHandles.size());
    varArgMethods = new ArrayList<>(methodHandles.size());
    final int argNum = callSiteType.parameterCount();
    for(MethodHandle mh: methodHandles) {
        if(mh.isVarargsCollector()) {
            final MethodHandle asFixed = mh.asFixedArity();
            if(argNum == asFixed.type().parameterCount()) {
                fixArgMethods.add(asFixed);
            }
            varArgMethods.add(mh);
        } else {
            fixArgMethods.add(mh);
        }
    }
    fixArgMethods.trimToSize();
    varArgMethods.trimToSize();

    final MethodHandle bound = SELECT_METHOD.bindTo(this);
    final MethodHandle collecting = SingleDynamicMethod.collectArguments(bound, argNum).asType(
            callSiteType.changeReturnType(MethodHandle.class));
    invoker = MethodHandles.foldArguments(MethodHandles.exactInvoker(callSiteType), collecting);
}
 
Example 14
OverloadedMethod(List<MethodHandle> methodHandles, OverloadedDynamicMethod parent, MethodType callSiteType,
        LinkerServices linkerServices) {
    this.parent = parent;
    this.callSiteType = callSiteType;
    this.linkerServices = linkerServices;

    fixArgMethods = new ArrayList<>(methodHandles.size());
    varArgMethods = new ArrayList<>(methodHandles.size());
    final int argNum = callSiteType.parameterCount();
    for(MethodHandle mh: methodHandles) {
        if(mh.isVarargsCollector()) {
            final MethodHandle asFixed = mh.asFixedArity();
            if(argNum == asFixed.type().parameterCount()) {
                fixArgMethods.add(asFixed);
            }
            varArgMethods.add(mh);
        } else {
            fixArgMethods.add(mh);
        }
    }
    fixArgMethods.trimToSize();
    varArgMethods.trimToSize();

    final MethodHandle bound = SELECT_METHOD.bindTo(this);
    final MethodHandle collecting = SingleDynamicMethod.collectArguments(bound, argNum).asType(
            callSiteType.changeReturnType(MethodHandle.class));
    invoker = MethodHandles.foldArguments(MethodHandles.exactInvoker(callSiteType), collecting);
}
 
Example 15
private static MethodHandle dropReceiver(final MethodHandle mh, final Class<?> receiverClass) {
    MethodHandle newHandle = MethodHandles.dropArguments(mh, 0, receiverClass);
    // NOTE: this is a workaround for the fact that dropArguments doesn't preserve vararg collector state.
    if(mh.isVarargsCollector() && !newHandle.isVarargsCollector()) {
        final MethodType type = mh.type();
        newHandle = newHandle.asVarargsCollector(type.parameterType(type.parameterCount() - 1));
    }
    return newHandle;
}
 
Example 16
OverloadedMethod(List<MethodHandle> methodHandles, OverloadedDynamicMethod parent, MethodType callSiteType,
        LinkerServices linkerServices) {
    this.parent = parent;
    this.callSiteType = callSiteType;
    this.linkerServices = linkerServices;

    fixArgMethods = new ArrayList<>(methodHandles.size());
    varArgMethods = new ArrayList<>(methodHandles.size());
    final int argNum = callSiteType.parameterCount();
    for(MethodHandle mh: methodHandles) {
        if(mh.isVarargsCollector()) {
            final MethodHandle asFixed = mh.asFixedArity();
            if(argNum == asFixed.type().parameterCount()) {
                fixArgMethods.add(asFixed);
            }
            varArgMethods.add(mh);
        } else {
            fixArgMethods.add(mh);
        }
    }
    fixArgMethods.trimToSize();
    varArgMethods.trimToSize();

    final MethodHandle bound = SELECT_METHOD.bindTo(this);
    final MethodHandle collecting = SingleDynamicMethod.collectArguments(bound, argNum).asType(
            callSiteType.changeReturnType(MethodHandle.class));
    invoker = MethodHandles.foldArguments(MethodHandles.exactInvoker(callSiteType), collecting);
}
 
Example 17
OverloadedMethod(final List<MethodHandle> methodHandles, final OverloadedDynamicMethod parent, final MethodType callSiteType,
        final LinkerServices linkerServices) {
    this.parent = parent;
    final Class<?> commonRetType = getCommonReturnType(methodHandles);
    this.callSiteType = callSiteType.changeReturnType(commonRetType);
    this.linkerServices = linkerServices;

    fixArgMethods = new ArrayList<>(methodHandles.size());
    varArgMethods = new ArrayList<>(methodHandles.size());
    final int argNum = callSiteType.parameterCount();
    for(MethodHandle mh: methodHandles) {
        if(mh.isVarargsCollector()) {
            final MethodHandle asFixed = mh.asFixedArity();
            if(argNum == asFixed.type().parameterCount()) {
                fixArgMethods.add(asFixed);
            }
            varArgMethods.add(mh);
        } else {
            fixArgMethods.add(mh);
        }
    }
    fixArgMethods.trimToSize();
    varArgMethods.trimToSize();

    final MethodHandle bound = SELECT_METHOD.bindTo(this);
    final MethodHandle collecting = SingleDynamicMethod.collectArguments(bound, argNum).asType(
            callSiteType.changeReturnType(MethodHandle.class));
    invoker = linkerServices.asTypeLosslessReturn(MethodHandles.foldArguments(
            MethodHandles.exactInvoker(this.callSiteType), collecting), callSiteType);
}
 
Example 18
private static MethodHandle dropReceiver(final MethodHandle mh, final Class<?> receiverClass) {
    MethodHandle newHandle = MethodHandles.dropArguments(mh, 0, receiverClass);
    // NOTE: this is a workaround for the fact that dropArguments doesn't preserve vararg collector state.
    if(mh.isVarargsCollector() && !newHandle.isVarargsCollector()) {
        final MethodType type = mh.type();
        newHandle = newHandle.asVarargsCollector(type.parameterType(type.parameterCount() - 1));
    }
    return newHandle;
}
 
Example 19
Source Project: es6draft   File: Properties.java    License: MIT License 4 votes vote down vote up
private static MethodHandle getStaticMethodHandle(Lookup lookup, Method method) throws IllegalAccessException {
    MethodHandle handle = lookup.unreflect(method);
    MethodType type = handle.type();
    Class<?>[] params = type.parameterArray();
    int p = 0, pcount = type.parameterCount();
    boolean callerContext = false;

    // First three parameters are (ExecutionContext, ExecutionContext?, Object=ThisValue)
    if (!(p < pcount && ExecutionContext.class.equals(params[p++]))) {
        throw new IllegalArgumentException(type.toString());
    }
    if (p < pcount && ExecutionContext.class.equals(params[p])) {
        callerContext = true;
        p++;
    }
    if (!(p < pcount && Object.class.equals(params[p++]))) {
        throw new IllegalArgumentException(type.toString());
    }
    // Always required to return Object (for now at least)
    if (!Object.class.equals(type.returnType())) {
        throw new IllegalArgumentException(type.toString());
    }
    // Collect remaining arguments into Object[]
    if (!(p + 1 == pcount && Object[].class.equals(params[p]))) {
        final int fixedArguments = callerContext ? 3 : 2;
        final boolean varargs = handle.isVarargsCollector();
        // Otherwise all trailing arguments need to be of type Object or Object[]
        for (; p < pcount; ++p) {
            if (Object.class.equals(params[p])) {
                continue;
            }
            if (p + 1 == pcount && Object[].class.equals(params[p]) && varargs) {
                continue;
            }
            throw new IllegalArgumentException(type.toString());
        }
        // Trailing Object[] arguments are no longer spread in var-args methods (jdk8u40, jdk9).
        if (varargs) {
            handle = handle.asFixedArity();
        }
        // Convert to (ExecutionContext, Object, ...) -> Object handle
        handle = toCanonical(handle, fixedArguments, varargs, method);
    }
    if (!callerContext) {
        handle = MethodHandles.dropArguments(handle, 1, ExecutionContext.class);
    }

    // assert handle.type().parameterCount() == 4;
    // assert handle.type().parameterType(0) == ExecutionContext.class;
    // assert handle.type().parameterType(1) == ExecutionContext.class;
    // assert handle.type().parameterType(2) == Object.class;
    // assert handle.type().parameterType(3) == Object[].class;
    // assert handle.type().returnType() == Object.class;

    return handle;
}
 
Example 20
/**
 * Given a method handle and a call site type, adapts the method handle to the call site type. Performs type
 * conversions as needed using the specified linker services, and in case that the method handle is a vararg
 * collector, matches it to the arity of the call site.
 * @param target the method handle to adapt
 * @param callSiteType the type of the call site
 * @param linkerServices the linker services used for type conversions
 * @return the adapted method handle.
 */
static MethodHandle getInvocation(MethodHandle target, MethodType callSiteType, LinkerServices linkerServices) {
    final MethodType methodType = target.type();
    final int paramsLen = methodType.parameterCount();
    final boolean varArgs = target.isVarargsCollector();
    final MethodHandle fixTarget = varArgs ? target.asFixedArity() : target;
    final int fixParamsLen = varArgs ? paramsLen - 1 : paramsLen;
    final int argsLen = callSiteType.parameterCount();
    if(argsLen < fixParamsLen) {
        // Less actual arguments than number of fixed declared arguments; can't invoke.
        return null;
    }
    // Method handle has the same number of fixed arguments as the call site type
    if(argsLen == fixParamsLen) {
        // Method handle that matches the number of actual arguments as the number of fixed arguments
        final MethodHandle matchedMethod;
        if(varArgs) {
            // If vararg, add a zero-length array of the expected type as the last argument to signify no variable
            // arguments.
            matchedMethod = MethodHandles.insertArguments(fixTarget, fixParamsLen, Array.newInstance(
                    methodType.parameterType(fixParamsLen).getComponentType(), 0));
        } else {
            // Otherwise, just use the method
            matchedMethod = fixTarget;
        }
        return createConvertingInvocation(matchedMethod, linkerServices, callSiteType);
    }

    // What's below only works for varargs
    if(!varArgs) {
        return null;
    }

    final Class<?> varArgType = methodType.parameterType(fixParamsLen);
    // Handle a somewhat sinister corner case: caller passes exactly one argument in the vararg position, and we
    // must handle both a prepacked vararg array as well as a genuine 1-long vararg sequence.
    if(argsLen == paramsLen) {
        final Class<?> callSiteLastArgType = callSiteType.parameterType(fixParamsLen);
        if(varArgType.isAssignableFrom(callSiteLastArgType)) {
            // Call site signature guarantees we'll always be passed a single compatible array; just link directly
            // to the method, introducing necessary conversions. Also, preserve it being a variable arity method.
            return createConvertingInvocation(target, linkerServices, callSiteType).asVarargsCollector(
                    callSiteLastArgType);
        }
        if(!linkerServices.canConvert(callSiteLastArgType, varArgType)) {
            // Call site signature guarantees the argument can definitely not be an array (i.e. it is primitive);
            // link immediately to a vararg-packing method handle.
            return createConvertingInvocation(collectArguments(fixTarget, argsLen), linkerServices, callSiteType);
        }
        // Call site signature makes no guarantees that the single argument in the vararg position will be
        // compatible across all invocations. Need to insert an appropriate guard and fall back to generic vararg
        // method when it is not.
        return MethodHandles.guardWithTest(Guards.isInstance(varArgType, fixParamsLen, callSiteType),
                createConvertingInvocation(fixTarget, linkerServices, callSiteType),
                createConvertingInvocation(collectArguments(fixTarget, argsLen), linkerServices, callSiteType));
    }

    // Remaining case: more than one vararg.
    return createConvertingInvocation(collectArguments(fixTarget, argsLen), linkerServices, callSiteType);
}