use of com.facebook.presto.hive.functions.scalar.ScalarFunctionInvoker in project presto by prestodb.
the class ScalarMethodHandles method generateUnbound.
/**
* Generates an unbound MethodHandle by {@code signature}.
* <p>
* For example, if {@code signature} describes a method like
* <pre>
* {@code
* IntegerType func(
* IntegerType i,
* VarcharType j)
* }
* </pre>,
* a method is generated as
* <pre>
* {@code
* static Long callEvaluate(
* ScalarFunctionInvoker invoker,
* Long input_0,
* Slice input_1) {
* return (Long) Invoker.evaluate(input_0, input_1);
* }
* }
* </pre>,
* and its MethodHandle returns.
*/
public static MethodHandle generateUnbound(Signature signature, TypeManager typeManager) {
Class<?> returnType = Primitives.wrap(typeManager.getType(signature.getReturnType()).getJavaType());
List<TypeSignature> argumentTypes = signature.getArgumentTypes();
List<Class<?>> argumentJavaTypes = argumentTypes.stream().map(t -> typeManager.getType(t).getJavaType()).map(Primitives::wrap).collect(toImmutableList());
ClassDefinition definition = new ClassDefinition(a(PUBLIC, FINAL), makeClassName(CLASS_NAME), ParameterizedType.type(Object.class));
// Step 1: Declare default constructor
definition.declareDefaultConstructor(a(PRIVATE));
// Step 2: Declare method
Parameter[] declareParameters = new Parameter[argumentTypes.size() + 1];
declareParameters[0] = arg("invoker", ScalarFunctionInvoker.class);
for (int i = 0; i < argumentTypes.size(); i++) {
declareParameters[i + 1] = arg("input_" + i, argumentJavaTypes.get(i));
}
MethodDefinition method = definition.declareMethod(a(PUBLIC, STATIC), METHOD_NAME, ParameterizedType.type(returnType), declareParameters);
// Step 3: Implement method body
BytecodeExpression[] evaluateInputs = new BytecodeExpression[argumentTypes.size()];
for (int i = 0; i < argumentTypes.size(); i++) {
evaluateInputs[i] = declareParameters[i + 1];
}
method.getBody().append(declareParameters[0].invoke("evaluate", Object.class, newArray(type(Object[].class), evaluateInputs)).cast(returnType).ret());
// Step 4: Generate class
Class<?> generatedClass = defineClass(definition, Object.class, Collections.emptyMap(), ScalarMethodHandles.class.getClassLoader());
// Step 5: Lookup MethodHandle
Class<?>[] lookupClasses = new Class[argumentTypes.size() + 1];
lookupClasses[0] = ScalarFunctionInvoker.class;
for (int i = 0; i < argumentTypes.size(); i++) {
lookupClasses[i + 1] = Primitives.wrap(typeManager.getType(argumentTypes.get(i)).getJavaType());
}
return methodHandle(generatedClass, METHOD_NAME, lookupClasses);
}
Aggregations