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;
}
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;
}
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;
}
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()));
}
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;
}
Aggregations