Search in sources :

Example 1 with ScalarFunctionInvoker

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);
}
Also used : ScalarFunctionInvoker(com.facebook.presto.hive.functions.scalar.ScalarFunctionInvoker) ClassDefinition(com.facebook.presto.bytecode.ClassDefinition) TypeSignature(com.facebook.presto.common.type.TypeSignature) MethodDefinition(com.facebook.presto.bytecode.MethodDefinition) Parameter(com.facebook.presto.bytecode.Parameter) CompilerUtils.defineClass(com.facebook.presto.hive.functions.gen.CompilerUtils.defineClass) BytecodeExpression(com.facebook.presto.bytecode.expression.BytecodeExpression)

Aggregations

ClassDefinition (com.facebook.presto.bytecode.ClassDefinition)1 MethodDefinition (com.facebook.presto.bytecode.MethodDefinition)1 Parameter (com.facebook.presto.bytecode.Parameter)1 BytecodeExpression (com.facebook.presto.bytecode.expression.BytecodeExpression)1 TypeSignature (com.facebook.presto.common.type.TypeSignature)1 CompilerUtils.defineClass (com.facebook.presto.hive.functions.gen.CompilerUtils.defineClass)1 ScalarFunctionInvoker (com.facebook.presto.hive.functions.scalar.ScalarFunctionInvoker)1