Search in sources :

Example 1 with MethodType

use of java.lang.invoke.MethodType in project groovy by apache.

the class IndyArrayAccess method buildGetter.

private static MethodHandle buildGetter(Class arrayClass) {
    MethodHandle get = MethodHandles.arrayElementGetter(arrayClass);
    MethodHandle fallback = MethodHandles.explicitCastArguments(get, get.type().changeParameterType(0, Object.class));
    fallback = MethodHandles.dropArguments(fallback, 2, int.class);
    MethodType reorderType = fallback.type().insertParameterTypes(0, int.class).dropParameterTypes(2, 3);
    fallback = MethodHandles.permuteArguments(fallback, reorderType, 1, 0, 0);
    fallback = MethodHandles.foldArguments(fallback, normalizeIndex);
    fallback = MethodHandles.explicitCastArguments(fallback, get.type());
    MethodHandle guard = MethodHandles.dropArguments(notNegative, 0, arrayClass);
    MethodHandle handle = MethodHandles.guardWithTest(guard, get, fallback);
    return handle;
}
Also used : MethodType(java.lang.invoke.MethodType) MethodHandle(java.lang.invoke.MethodHandle)

Example 2 with MethodType

use of java.lang.invoke.MethodType in project groovy by apache.

the class IndyArrayAccess method buildSetter.

private static MethodHandle buildSetter(Class arrayClass) {
    MethodHandle set = MethodHandles.arrayElementSetter(arrayClass);
    MethodHandle fallback = MethodHandles.explicitCastArguments(set, set.type().changeParameterType(0, Object.class));
    fallback = MethodHandles.dropArguments(fallback, 3, int.class);
    MethodType reorderType = fallback.type().insertParameterTypes(0, int.class).dropParameterTypes(4, 5);
    fallback = MethodHandles.permuteArguments(fallback, reorderType, 1, 0, 3, 0);
    fallback = MethodHandles.foldArguments(fallback, normalizeIndex);
    fallback = MethodHandles.explicitCastArguments(fallback, set.type());
    MethodHandle guard = MethodHandles.dropArguments(notNegative, 0, arrayClass);
    MethodHandle handle = MethodHandles.guardWithTest(guard, set, fallback);
    return handle;
}
Also used : MethodType(java.lang.invoke.MethodType) MethodHandle(java.lang.invoke.MethodHandle)

Example 3 with MethodType

use of java.lang.invoke.MethodType in project elasticsearch by elastic.

the class Def method lookupMethod.

/**
     * Looks up handle for a dynamic method call, with lambda replacement
     * <p>
     * A dynamic method call for variable {@code x} of type {@code def} looks like:
     * {@code x.method(args...)}
     * <p>
     * This method traverses {@code recieverClass}'s class hierarchy (including interfaces)
     * until it finds a matching whitelisted method. If one is not found, it throws an exception.
     * Otherwise it returns a handle to the matching method.
     * <p>
     * @param lookup caller's lookup
     * @param callSiteType callsite's type
     * @param receiverClass Class of the object to invoke the method on.
     * @param name Name of the method.
     * @param args bootstrap args passed to callsite
     * @return pointer to matching method to invoke. never returns null.
     * @throws IllegalArgumentException if no matching whitelisted method was found.
     * @throws Throwable if a method reference cannot be converted to an functional interface
     */
static MethodHandle lookupMethod(Lookup lookup, MethodType callSiteType, Class<?> receiverClass, String name, Object[] args) throws Throwable {
    String recipeString = (String) args[0];
    int numArguments = callSiteType.parameterCount();
    // simple case: no lambdas
    if (recipeString.isEmpty()) {
        return lookupMethodInternal(receiverClass, name, numArguments - 1).handle;
    }
    // convert recipe string to a bitset for convenience (the code below should be refactored...)
    BitSet lambdaArgs = new BitSet();
    for (int i = 0; i < recipeString.length(); i++) {
        lambdaArgs.set(recipeString.charAt(i));
    }
    // otherwise: first we have to compute the "real" arity. This is because we have extra arguments:
    // e.g. f(a, g(x), b, h(y), i()) looks like f(a, g, x, b, h, y, i). 
    int arity = callSiteType.parameterCount() - 1;
    int upTo = 1;
    for (int i = 1; i < numArguments; i++) {
        if (lambdaArgs.get(i - 1)) {
            String signature = (String) args[upTo++];
            int numCaptures = Integer.parseInt(signature.substring(signature.indexOf(',') + 1));
            arity -= numCaptures;
        }
    }
    // lookup the method with the proper arity, then we know everything (e.g. interface types of parameters).
    // based on these we can finally link any remaining lambdas that were deferred.
    Method method = lookupMethodInternal(receiverClass, name, arity);
    MethodHandle handle = method.handle;
    int replaced = 0;
    upTo = 1;
    for (int i = 1; i < numArguments; i++) {
        // its a functional reference, replace the argument with an impl
        if (lambdaArgs.get(i - 1)) {
            // decode signature of form 'type.call,2' 
            String signature = (String) args[upTo++];
            int separator = signature.lastIndexOf('.');
            int separator2 = signature.indexOf(',');
            String type = signature.substring(1, separator);
            String call = signature.substring(separator + 1, separator2);
            int numCaptures = Integer.parseInt(signature.substring(separator2 + 1));
            Class<?>[] captures = new Class<?>[numCaptures];
            for (int capture = 0; capture < captures.length; capture++) {
                captures[capture] = callSiteType.parameterType(i + 1 + capture);
            }
            MethodHandle filter;
            Definition.Type interfaceType = method.arguments.get(i - 1 - replaced);
            if (signature.charAt(0) == 'S') {
                // the implementation is strongly typed, now that we know the interface type,
                // we have everything.
                filter = lookupReferenceInternal(lookup, interfaceType, type, call, captures);
            } else if (signature.charAt(0) == 'D') {
                // the interface type is now known, but we need to get the implementation.
                // this is dynamically based on the receiver type (and cached separately, underneath
                // this cache). It won't blow up since we never nest here (just references)
                MethodType nestedType = MethodType.methodType(interfaceType.clazz, captures);
                CallSite nested = DefBootstrap.bootstrap(lookup, call, nestedType, 0, DefBootstrap.REFERENCE, interfaceType.name);
                filter = nested.dynamicInvoker();
            } else {
                throw new AssertionError();
            }
            // the filter now ignores the signature (placeholder) on the stack
            filter = MethodHandles.dropArguments(filter, 0, String.class);
            handle = MethodHandles.collectArguments(handle, i, filter);
            i += numCaptures;
            replaced += numCaptures;
        }
    }
    return handle;
}
Also used : MethodType(java.lang.invoke.MethodType) BitSet(java.util.BitSet) RuntimeClass(org.elasticsearch.painless.Definition.RuntimeClass) CallSite(java.lang.invoke.CallSite) Method(org.elasticsearch.painless.Definition.Method) MethodHandle(java.lang.invoke.MethodHandle)

Example 4 with MethodType

use of java.lang.invoke.MethodType in project elasticsearch by elastic.

the class DefMath method cast.

/** Forces a cast to class A for target (only if types differ) */
public static MethodHandle cast(Class<?> classA, MethodHandle target) {
    MethodType newType = MethodType.methodType(classA).unwrap();
    MethodType targetType = MethodType.methodType(target.type().returnType()).unwrap();
    // but we do it explicitly, to make the boolean check simpler
    if (newType.returnType() == targetType.returnType()) {
        return target;
    }
    // we don't allow the to/from boolean conversions of explicitCastArguments
    if (newType.returnType() == boolean.class || targetType.returnType() == boolean.class) {
        throw new ClassCastException("Cannot cast " + targetType.returnType() + " to " + newType.returnType());
    }
    // null return values are not possible for our arguments.
    return MethodHandles.explicitCastArguments(target, target.type().changeReturnType(newType.returnType()));
}
Also used : MethodType(java.lang.invoke.MethodType)

Example 5 with MethodType

use of java.lang.invoke.MethodType in project presto by prestodb.

the class TryCodeGenerator method defineTryMethod.

public static MethodDefinition defineTryMethod(BytecodeExpressionVisitor innerExpressionVisitor, ClassDefinition classDefinition, String methodName, List<Parameter> inputParameters, Class<?> returnType, RowExpression innerRowExpression, CallSiteBinder callSiteBinder) {
    MethodDefinition method = classDefinition.declareMethod(a(PUBLIC), methodName, type(returnType), inputParameters);
    Scope calleeMethodScope = method.getScope();
    Variable wasNull = calleeMethodScope.declareVariable(boolean.class, "wasNull");
    BytecodeNode innerExpression = innerRowExpression.accept(innerExpressionVisitor, calleeMethodScope);
    MethodType exceptionHandlerType = methodType(returnType, PrestoException.class);
    MethodHandle exceptionHandler = methodHandle(TryCodeGenerator.class, EXCEPTION_HANDLER_NAME, PrestoException.class).asType(exceptionHandlerType);
    Binding binding = callSiteBinder.bind(exceptionHandler);
    method.comment("Try projection: %s", innerRowExpression.toString());
    method.getBody().append(wasNull.set(constantBoolean(false))).append(new TryCatch(new BytecodeBlock().append(innerExpression).append(boxPrimitiveIfNecessary(calleeMethodScope, returnType)), new BytecodeBlock().append(invoke(binding, EXCEPTION_HANDLER_NAME)), ParameterizedType.type(PrestoException.class))).ret(returnType);
    return method;
}
Also used : MethodType(java.lang.invoke.MethodType) TryCatch(com.facebook.presto.bytecode.control.TryCatch) Variable(com.facebook.presto.bytecode.Variable) Scope(com.facebook.presto.bytecode.Scope) MethodDefinition(com.facebook.presto.bytecode.MethodDefinition) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) BytecodeNode(com.facebook.presto.bytecode.BytecodeNode) PrestoException(com.facebook.presto.spi.PrestoException) MethodHandle(java.lang.invoke.MethodHandle)

Aggregations

MethodType (java.lang.invoke.MethodType)102 MethodHandle (java.lang.invoke.MethodHandle)36 Test (org.junit.Test)6 MethodHandles (java.lang.invoke.MethodHandles)5 ArrayList (java.util.ArrayList)4 BytecodeBlock (com.facebook.presto.bytecode.BytecodeBlock)3 ScriptObject (com.github.anba.es6draft.runtime.types.ScriptObject)3 OrdinaryObject (com.github.anba.es6draft.runtime.types.builtins.OrdinaryObject)3 CallSite (java.lang.invoke.CallSite)3 LambdaReceiver_A (LambdaReceiver_anotherpkg.LambdaReceiver_A)2 MethodDefinition (com.facebook.presto.bytecode.MethodDefinition)2 ConnectorSession (com.facebook.presto.spi.ConnectorSession)2 PrestoException (com.facebook.presto.spi.PrestoException)2 Map (java.util.Map)2 Session (com.facebook.presto.Session)1 BytecodeNode (com.facebook.presto.bytecode.BytecodeNode)1 ClassDefinition (com.facebook.presto.bytecode.ClassDefinition)1 Parameter (com.facebook.presto.bytecode.Parameter)1 Scope (com.facebook.presto.bytecode.Scope)1 Variable (com.facebook.presto.bytecode.Variable)1