Search in sources :

Example 36 with MethodDefinition

use of com.facebook.presto.bytecode.MethodDefinition in project presto by prestodb.

the class RowToRowCast method generateRowCast.

private static Class<?> generateRowCast(Type fromType, Type toType, FunctionRegistry functionRegistry) {
    List<Type> toTypes = toType.getTypeParameters();
    List<Type> fromTypes = fromType.getTypeParameters();
    CallSiteBinder binder = new CallSiteBinder();
    // Embed the MD5 hash code of input and output types into the generated class name instead of the raw type names,
    // which could prevent the class name from hitting the length limitation and invalid characters.
    byte[] md5Suffix = Hashing.md5().hashBytes((fromType + "$" + toType).getBytes()).asBytes();
    ClassDefinition definition = new ClassDefinition(a(PUBLIC, FINAL), CompilerUtils.makeClassName(Joiner.on("$").join("RowCast", BaseEncoding.base16().encode(md5Suffix))), type(Object.class));
    Parameter session = arg("session", ConnectorSession.class);
    Parameter value = arg("value", Block.class);
    MethodDefinition method = definition.declareMethod(a(PUBLIC, STATIC), "castRow", type(Block.class), session, value);
    Scope scope = method.getScope();
    BytecodeBlock body = method.getBody();
    Variable wasNull = scope.declareVariable(boolean.class, "wasNull");
    Variable blockBuilder = scope.createTempVariable(BlockBuilder.class);
    body.append(wasNull.set(constantBoolean(false)));
    CachedInstanceBinder cachedInstanceBinder = new CachedInstanceBinder(definition, binder);
    // create the interleave block builder
    body.newObject(InterleavedBlockBuilder.class).dup().append(constantType(binder, toType).invoke("getTypeParameters", List.class)).append(newInstance(BlockBuilderStatus.class)).append(constantInt(toTypes.size())).invokeConstructor(InterleavedBlockBuilder.class, List.class, BlockBuilderStatus.class, int.class).putVariable(blockBuilder);
    // loop through to append member blocks
    for (int i = 0; i < toTypes.size(); i++) {
        Signature signature = internalOperator(CAST.name(), toTypes.get(i).getTypeSignature(), ImmutableList.of(fromTypes.get(i).getTypeSignature()));
        ScalarFunctionImplementation function = functionRegistry.getScalarFunctionImplementation(signature);
        Type currentFromType = fromTypes.get(i);
        if (currentFromType.equals(UNKNOWN)) {
            body.append(blockBuilder.invoke("appendNull", BlockBuilder.class).pop());
            continue;
        }
        BytecodeExpression fromElement = constantType(binder, currentFromType).getValue(value, constantInt(i));
        BytecodeExpression toElement = invokeFunction(scope, cachedInstanceBinder, signature.getName(), function, fromElement);
        IfStatement ifElementNull = new IfStatement("if the element in the row type is null...");
        ifElementNull.condition(value.invoke("isNull", boolean.class, constantInt(i))).ifTrue(blockBuilder.invoke("appendNull", BlockBuilder.class).pop()).ifFalse(constantType(binder, toTypes.get(i)).writeValue(blockBuilder, toElement));
        body.append(ifElementNull);
    }
    // call blockBuilder.build()
    body.append(blockBuilder.invoke("build", Block.class)).retObject();
    // create constructor
    MethodDefinition constructorDefinition = definition.declareConstructor(a(PUBLIC));
    BytecodeBlock constructorBody = constructorDefinition.getBody();
    Variable thisVariable = constructorDefinition.getThis();
    constructorBody.comment("super();").append(thisVariable).invokeConstructor(Object.class);
    cachedInstanceBinder.generateInitializations(thisVariable, constructorBody);
    constructorBody.ret();
    return defineClass(definition, Object.class, binder.getBindings(), RowToRowCast.class.getClassLoader());
}
Also used : Variable(com.facebook.presto.bytecode.Variable) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) ClassDefinition(com.facebook.presto.bytecode.ClassDefinition) InterleavedBlockBuilder(com.facebook.presto.spi.block.InterleavedBlockBuilder) IfStatement(com.facebook.presto.bytecode.control.IfStatement) Type(com.facebook.presto.spi.type.Type) SqlTypeBytecodeExpression.constantType(com.facebook.presto.sql.gen.SqlTypeBytecodeExpression.constantType) CachedInstanceBinder(com.facebook.presto.sql.gen.CachedInstanceBinder) Scope(com.facebook.presto.bytecode.Scope) MethodDefinition(com.facebook.presto.bytecode.MethodDefinition) CallSiteBinder(com.facebook.presto.sql.gen.CallSiteBinder) Signature(com.facebook.presto.metadata.Signature) TypeSignature.parseTypeSignature(com.facebook.presto.spi.type.TypeSignature.parseTypeSignature) Parameter(com.facebook.presto.bytecode.Parameter) Block(com.facebook.presto.spi.block.Block) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) List(java.util.List) ImmutableList(com.google.common.collect.ImmutableList) BytecodeExpression(com.facebook.presto.bytecode.expression.BytecodeExpression) BlockBuilderStatus(com.facebook.presto.spi.block.BlockBuilderStatus) BlockBuilder(com.facebook.presto.spi.block.BlockBuilder) InterleavedBlockBuilder(com.facebook.presto.spi.block.InterleavedBlockBuilder)

Example 37 with MethodDefinition

use of com.facebook.presto.bytecode.MethodDefinition in project presto by prestodb.

the class ArrayTransformFunction method generateTransform.

private static Class<?> generateTransform(Type inputType, Type outputType) {
    CallSiteBinder binder = new CallSiteBinder();
    Class<?> inputJavaType = Primitives.wrap(inputType.getJavaType());
    Class<?> outputJavaType = Primitives.wrap(outputType.getJavaType());
    ClassDefinition definition = new ClassDefinition(a(PUBLIC, FINAL), makeClassName("ArrayTransform"), type(Object.class));
    definition.declareDefaultConstructor(a(PRIVATE));
    // define createPageBuilder
    MethodDefinition createPageBuilderMethod = definition.declareMethod(a(PUBLIC, STATIC), "createPageBuilder", type(PageBuilder.class));
    createPageBuilderMethod.getBody().append(newInstance(PageBuilder.class, constantType(binder, new ArrayType(outputType)).invoke("getTypeParameters", List.class)).ret());
    // define transform method
    Parameter pageBuilder = arg("pageBuilder", PageBuilder.class);
    Parameter block = arg("block", Block.class);
    Parameter function = arg("function", MethodHandle.class);
    MethodDefinition method = definition.declareMethod(a(PUBLIC, STATIC), "transform", type(Block.class), ImmutableList.of(pageBuilder, block, function));
    BytecodeBlock body = method.getBody();
    Scope scope = method.getScope();
    Variable positionCount = scope.declareVariable(int.class, "positionCount");
    Variable position = scope.declareVariable(int.class, "position");
    Variable blockBuilder = scope.declareVariable(BlockBuilder.class, "blockBuilder");
    Variable inputElement = scope.declareVariable(inputJavaType, "inputElement");
    Variable outputElement = scope.declareVariable(outputJavaType, "outputElement");
    // invoke block.getPositionCount()
    body.append(positionCount.set(block.invoke("getPositionCount", int.class)));
    // reset page builder if it is full
    body.append(new IfStatement().condition(pageBuilder.invoke("isFull", boolean.class)).ifTrue(pageBuilder.invoke("reset", void.class)));
    // get block builder
    body.append(blockBuilder.set(pageBuilder.invoke("getBlockBuilder", BlockBuilder.class, constantInt(0))));
    BytecodeNode loadInputElement;
    if (!inputType.equals(UNKNOWN)) {
        loadInputElement = new IfStatement().condition(block.invoke("isNull", boolean.class, position)).ifTrue(inputElement.set(constantNull(inputJavaType))).ifFalse(inputElement.set(constantType(binder, inputType).getValue(block, position).cast(inputJavaType)));
    } else {
        loadInputElement = new BytecodeBlock().append(inputElement.set(constantNull(inputJavaType)));
    }
    BytecodeNode writeOutputElement;
    if (!outputType.equals(UNKNOWN)) {
        writeOutputElement = new IfStatement().condition(equal(outputElement, constantNull(outputJavaType))).ifTrue(blockBuilder.invoke("appendNull", BlockBuilder.class).pop()).ifFalse(constantType(binder, outputType).writeValue(blockBuilder, outputElement.cast(outputType.getJavaType())));
    } else {
        writeOutputElement = new BytecodeBlock().append(blockBuilder.invoke("appendNull", BlockBuilder.class).pop());
    }
    body.append(new ForLoop().initialize(position.set(constantInt(0))).condition(lessThan(position, positionCount)).update(incrementVariable(position, (byte) 1)).body(new BytecodeBlock().append(loadInputElement).append(outputElement.set(function.invoke("invokeExact", outputJavaType, inputElement))).append(writeOutputElement)));
    body.append(pageBuilder.invoke("declarePositions", void.class, positionCount));
    body.append(blockBuilder.invoke("getRegion", Block.class, subtract(blockBuilder.invoke("getPositionCount", int.class), positionCount), positionCount).ret());
    return defineClass(definition, Object.class, binder.getBindings(), ArrayTransformFunction.class.getClassLoader());
}
Also used : Signature.typeVariable(com.facebook.presto.metadata.Signature.typeVariable) Variable(com.facebook.presto.bytecode.Variable) VariableInstruction.incrementVariable(com.facebook.presto.bytecode.instruction.VariableInstruction.incrementVariable) ForLoop(com.facebook.presto.bytecode.control.ForLoop) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) PageBuilder(com.facebook.presto.spi.PageBuilder) ClassDefinition(com.facebook.presto.bytecode.ClassDefinition) ArrayType(com.facebook.presto.type.ArrayType) IfStatement(com.facebook.presto.bytecode.control.IfStatement) Scope(com.facebook.presto.bytecode.Scope) MethodDefinition(com.facebook.presto.bytecode.MethodDefinition) CallSiteBinder(com.facebook.presto.sql.gen.CallSiteBinder) Parameter(com.facebook.presto.bytecode.Parameter) Block(com.facebook.presto.spi.block.Block) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) ImmutableList(com.google.common.collect.ImmutableList) List(java.util.List) BytecodeNode(com.facebook.presto.bytecode.BytecodeNode) BlockBuilder(com.facebook.presto.spi.block.BlockBuilder)

Example 38 with MethodDefinition

use of com.facebook.presto.bytecode.MethodDefinition in project presto by prestodb.

the class VarArgsToArrayAdapterGenerator method generateVarArgsToArrayAdapter.

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");
    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"));
}
Also used : MethodType(java.lang.invoke.MethodType) ImmutableList(com.google.common.collect.ImmutableList) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) ClassDefinition(com.facebook.presto.bytecode.ClassDefinition) MethodDefinition(com.facebook.presto.bytecode.MethodDefinition) Parameter(com.facebook.presto.bytecode.Parameter) BytecodeExpression(com.facebook.presto.bytecode.expression.BytecodeExpression) MethodHandle(java.lang.invoke.MethodHandle)

Example 39 with MethodDefinition

use of com.facebook.presto.bytecode.MethodDefinition in project presto by prestodb.

the class PageProcessorCompiler method generateMethods.

@Override
public void generateMethods(ClassDefinition classDefinition, CallSiteBinder callSiteBinder, RowExpression filter, List<RowExpression> projections) {
    CachedInstanceBinder cachedInstanceBinder = new CachedInstanceBinder(classDefinition, callSiteBinder);
    ImmutableList.Builder<MethodDefinition> projectMethods = ImmutableList.builder();
    ImmutableList.Builder<MethodDefinition> projectColumnarMethods = ImmutableList.builder();
    ImmutableList.Builder<MethodDefinition> projectDictionaryMethods = ImmutableList.builder();
    for (int i = 0; i < projections.size(); i++) {
        MethodDefinition project = generateProjectMethod(classDefinition, callSiteBinder, cachedInstanceBinder, "project_" + i, projections.get(i));
        MethodDefinition projectColumnar = generateProjectColumnarMethod(classDefinition, callSiteBinder, "projectColumnar_" + i, projections.get(i), project);
        MethodDefinition projectRLE = generateProjectRLEMethod(classDefinition, "projectRLE_" + i, projections.get(i), project, projectColumnar);
        MethodDefinition projectDictionary = generateProjectDictionaryMethod(classDefinition, "projectDictionary_" + i, projections.get(i), project, projectColumnar, projectRLE);
        projectMethods.add(project);
        projectColumnarMethods.add(projectColumnar);
        projectDictionaryMethods.add(projectDictionary);
    }
    List<MethodDefinition> projectMethodDefinitions = projectMethods.build();
    List<MethodDefinition> projectColumnarMethodDefinitions = projectColumnarMethods.build();
    List<MethodDefinition> projectDictionaryMethodDefinitions = projectDictionaryMethods.build();
    generateProcessMethod(classDefinition, filter, projections, projectMethodDefinitions);
    generateGetNonLazyPageMethod(classDefinition, filter, projections);
    generateProcessColumnarMethod(classDefinition, projections, projectColumnarMethodDefinitions);
    generateProcessColumnarDictionaryMethod(classDefinition, projections, projectDictionaryMethodDefinitions);
    generateFilterPageMethod(classDefinition, filter);
    generateFilterMethod(classDefinition, callSiteBinder, cachedInstanceBinder, filter);
    generateConstructor(classDefinition, cachedInstanceBinder, projections.size());
}
Also used : ImmutableList(com.google.common.collect.ImmutableList) MethodDefinition(com.facebook.presto.bytecode.MethodDefinition)

Example 40 with MethodDefinition

use of com.facebook.presto.bytecode.MethodDefinition in project presto by prestodb.

the class PageProcessorCompiler method generateFilterPageMethod.

private void generateFilterPageMethod(ClassDefinition classDefinition, RowExpression filter) {
    Parameter session = arg("session", ConnectorSession.class);
    Parameter page = arg("page", Page.class);
    MethodDefinition method = classDefinition.declareMethod(a(PUBLIC), "filterPage", type(int[].class), session, page);
    method.comment("Filter: %s rows in the page", filter.toString());
    Scope scope = method.getScope();
    Variable thisVariable = method.getThis();
    BytecodeBlock body = method.getBody();
    Variable positionCount = scope.declareVariable("positionCount", body, page.invoke("getPositionCount", int.class));
    Variable selectedPositions = scope.declareVariable("selectedPositions", body, newArray(type(int[].class), positionCount));
    Variable selectedCount = scope.declareVariable("selectedCount", body, constantInt(0));
    Variable position = scope.declareVariable(int.class, "position");
    List<Integer> filterChannels = getInputChannels(filter);
    // extract block variables
    ImmutableList.Builder<Variable> blockVariablesBuilder = ImmutableList.builder();
    for (int channel : filterChannels) {
        Variable blockVariable = scope.declareVariable("block_" + channel, body, page.invoke("getBlock", Block.class, constantInt(channel)));
        blockVariablesBuilder.add(blockVariable);
    }
    List<Variable> blockVariables = blockVariablesBuilder.build();
    if (filterChannels.size() == 1 && determinismEvaluator.isDeterministic(filter)) {
        BytecodeBlock ifFilterOnDictionaryBlock = getBytecodeFilterOnDictionary(session, scope, blockVariables.get(0));
        BytecodeBlock ifFilterOnRLEBlock = getBytecodeFilterOnRLE(session, scope, blockVariables.get(0));
        body.append(new IfStatement().condition(blockVariables.get(0).instanceOf(DictionaryBlock.class)).ifTrue(ifFilterOnDictionaryBlock));
        body.append(new IfStatement().condition(blockVariables.get(0).instanceOf(RunLengthEncodedBlock.class)).ifTrue(ifFilterOnRLEBlock));
    }
    body.append(new ForLoop().initialize(position.set(constantInt(0))).condition(lessThan(position, positionCount)).update(position.increment()).body(new IfStatement().condition(invokeFilter(thisVariable, session, blockVariables, position)).ifTrue(new BytecodeBlock().append(selectedPositions.setElement(selectedCount, position)).append(selectedCount.increment()))));
    body.append(invokeStatic(Arrays.class, "copyOf", int[].class, selectedPositions, selectedCount).ret());
}
Also used : Variable(com.facebook.presto.bytecode.Variable) ForLoop(com.facebook.presto.bytecode.control.ForLoop) ImmutableList(com.google.common.collect.ImmutableList) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) DictionaryBlock(com.facebook.presto.spi.block.DictionaryBlock) IfStatement(com.facebook.presto.bytecode.control.IfStatement) Scope(com.facebook.presto.bytecode.Scope) MethodDefinition(com.facebook.presto.bytecode.MethodDefinition) Parameter(com.facebook.presto.bytecode.Parameter) Block(com.facebook.presto.spi.block.Block) DictionaryBlock(com.facebook.presto.spi.block.DictionaryBlock) LazyBlock(com.facebook.presto.spi.block.LazyBlock) RunLengthEncodedBlock(com.facebook.presto.spi.block.RunLengthEncodedBlock) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) RunLengthEncodedBlock(com.facebook.presto.spi.block.RunLengthEncodedBlock)

Aggregations

MethodDefinition (com.facebook.presto.bytecode.MethodDefinition)74 Parameter (com.facebook.presto.bytecode.Parameter)56 Variable (com.facebook.presto.bytecode.Variable)54 BytecodeBlock (com.facebook.presto.bytecode.BytecodeBlock)45 Scope (com.facebook.presto.bytecode.Scope)30 IfStatement (com.facebook.presto.bytecode.control.IfStatement)27 BytecodeExpression (com.facebook.presto.bytecode.expression.BytecodeExpression)24 Block (com.facebook.presto.spi.block.Block)20 ImmutableList (com.google.common.collect.ImmutableList)16 ClassDefinition (com.facebook.presto.bytecode.ClassDefinition)14 FieldDefinition (com.facebook.presto.bytecode.FieldDefinition)11 BytecodeNode (com.facebook.presto.bytecode.BytecodeNode)10 Type (com.facebook.presto.spi.type.Type)10 ForLoop (com.facebook.presto.bytecode.control.ForLoop)9 LabelNode (com.facebook.presto.bytecode.instruction.LabelNode)9 BlockBuilder (com.facebook.presto.spi.block.BlockBuilder)9 DictionaryBlock (com.facebook.presto.spi.block.DictionaryBlock)9 LazyBlock (com.facebook.presto.spi.block.LazyBlock)9 RunLengthEncodedBlock (com.facebook.presto.spi.block.RunLengthEncodedBlock)9 List (java.util.List)9