presto-main/src/main/java/io/prestosql/sql/gen/VarArgsToArrayAdapterGenerator.java/VarArgsToArrayAdapterGenerator/generateVarArgsToArrayAdapter
class VarArgsToArrayAdapterGenerator:    public static MethodHandleAndConstructor generateVarArgsToArrayAdapter(
            Class<?> returnType,
            Class<?> javaType,
            int argsLength,
            MethodHandle function,
            MethodHandle userStateFactory)
    {
        requireNonNull(returnType, "returnType is null");
        requireNonNull(javaType, "javaType is null");
        requireNonNull(function, "function is null");
        requireNonNull(userStateFactory, "userStateFactory is null");

        checkCondition(argsLength <= 253, NOT_SUPPORTED, "Too many arguments for vararg function");

        MethodType methodType = function.type();
        Class<?> javaArrayType = toArrayClass(javaType);
        checkArgument(methodType.returnType() == returnType, "returnType does not match");
        checkArgument(methodType.parameterList().equals(ImmutableList.of(Object.class, javaArrayType)), "parameter types do not match");

        CallSiteBinder callSiteBinder = new CallSiteBinder();
        ClassDefinition classDefinition = new ClassDefinition(a(PUBLIC, FINAL), makeClassName("VarArgsToListAdapter"), type(Object.class));
        classDefinition.declareDefaultConstructor(a(PRIVATE));

        // generate userState constructor
        MethodDefinition stateFactoryDefinition = classDefinition.declareMethod(a(PUBLIC, STATIC), "createState", type(VarArgsToArrayAdapterState.class));

        stateFactoryDefinition.getBody()
                .comment("create userState for current instance")
                .append(
                        newInstance(
                                VarArgsToArrayAdapterState.class,
                                loadConstant(callSiteBinder, userStateFactory, MethodHandle.class).invoke("invokeExact", Object.class),
                                newArray(type(javaArrayType), argsLength).cast(Object.class)).ret());

        // generate adapter method
        ImmutableList.Builder<Parameter> parameterListBuilder = ImmutableList.builder();
        parameterListBuilder.add(arg("userState", VarArgsToArrayAdapterState.class));
        for (int i = 0; i < argsLength; i++) {
            parameterListBuilder.add(arg("input_" + i, javaType));
        }
        ImmutableList<Parameter> parameterList = parameterListBuilder.build();

        MethodDefinition methodDefinition = classDefinition.declareMethod(a(PUBLIC, STATIC), "varArgsToArray", type(returnType), parameterList);
        BytecodeBlock body = methodDefinition.getBody();

        BytecodeExpression userState = parameterList.get(0).getField("userState", Object.class);
        BytecodeExpression args = parameterList.get(0).getField("args", Object.class).cast(javaArrayType);
        for (int i = 0; i < argsLength; i++) {
            body.append(args.setElement(i, parameterList.get(i + 1)));
        }

        body.append(
                loadConstant(callSiteBinder, function, MethodHandle.class)
                        .invoke("invokeExact", returnType, userState, args)
                        .ret());

        // define class
        Class<?> generatedClass = defineClass(classDefinition, Object.class, callSiteBinder.getBindings(), VarArgsToArrayAdapterGenerator.class.getClassLoader());
        return new MethodHandleAndConstructor(
                Reflection.methodHandle(
                        generatedClass,
                        "varArgsToArray",
                        ImmutableList.builder()
                                .add(VarArgsToArrayAdapterState.class)
                                .addAll(nCopies(argsLength, javaType))
                                .build()
                                .toArray(new Class<?>[argsLength])),
                Reflection.methodHandle(generatedClass, "createState"));
    }