Search in sources :

Example 26 with BytecodeNode

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

the class MapFilterFunction method generateFilter.

private static MethodHandle generateFilter(Type keyType, Type valueType) {
    CallSiteBinder binder = new CallSiteBinder();
    MapType mapType = new MapType(keyType, valueType);
    Class<?> keyJavaType = Primitives.wrap(keyType.getJavaType());
    Class<?> valueJavaType = Primitives.wrap(valueType.getJavaType());
    ClassDefinition definition = new ClassDefinition(a(PUBLIC, FINAL), makeClassName("MapFilter"), type(Object.class));
    definition.declareDefaultConstructor(a(PRIVATE));
    Parameter block = arg("block", Block.class);
    Parameter function = arg("function", MethodHandle.class);
    MethodDefinition method = definition.declareMethod(a(PUBLIC, STATIC), "filter", type(Block.class), ImmutableList.of(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 keyElement = scope.declareVariable(keyJavaType, "keyElement");
    Variable valueElement = scope.declareVariable(valueJavaType, "valueElement");
    Variable keep = scope.declareVariable(Boolean.class, "keep");
    // invoke block.getPositionCount()
    body.append(positionCount.set(block.invoke("getPositionCount", int.class)));
    // create the interleaved block builder
    body.append(blockBuilder.set(newInstance(InterleavedBlockBuilder.class, constantType(binder, mapType).invoke("getTypeParameters", List.class), newInstance(BlockBuilderStatus.class), positionCount)));
    SqlTypeBytecodeExpression keySqlType = constantType(binder, keyType);
    BytecodeNode loadKeyElement;
    if (!keyType.equals(UNKNOWN)) {
        // key element must be non-null
        loadKeyElement = new BytecodeBlock().append(keyElement.set(keySqlType.getValue(block, position).cast(keyJavaType)));
    } else {
        loadKeyElement = new BytecodeBlock().append(keyElement.set(constantNull(keyJavaType)));
    }
    SqlTypeBytecodeExpression valueSqlType = constantType(binder, valueType);
    BytecodeNode loadValueElement;
    if (!valueType.equals(UNKNOWN)) {
        loadValueElement = new IfStatement().condition(block.invoke("isNull", boolean.class, add(position, constantInt(1)))).ifTrue(valueElement.set(constantNull(valueJavaType))).ifFalse(valueElement.set(valueSqlType.getValue(block, add(position, constantInt(1))).cast(valueJavaType)));
    } else {
        loadValueElement = new BytecodeBlock().append(valueElement.set(constantNull(valueJavaType)));
    }
    body.append(new ForLoop().initialize(position.set(constantInt(0))).condition(lessThan(position, positionCount)).update(incrementVariable(position, (byte) 2)).body(new BytecodeBlock().append(loadKeyElement).append(loadValueElement).append(keep.set(function.invoke("invokeExact", Boolean.class, keyElement, valueElement))).append(new IfStatement("if (keep != null && keep) ...").condition(and(notEqual(keep, constantNull(Boolean.class)), keep.cast(boolean.class))).ifTrue(new BytecodeBlock().append(keySqlType.invoke("appendTo", void.class, block, position, blockBuilder)).append(valueSqlType.invoke("appendTo", void.class, block, add(position, constantInt(1)), blockBuilder))))));
    body.append(blockBuilder.invoke("build", Block.class).ret());
    Class<?> generatedClass = defineClass(definition, Object.class, binder.getBindings(), MapFilterFunction.class.getClassLoader());
    return methodHandle(generatedClass, "filter", Block.class, MethodHandle.class);
}
Also used : Variable(com.facebook.presto.bytecode.Variable) Signature.typeVariable(com.facebook.presto.metadata.Signature.typeVariable) VariableInstruction.incrementVariable(com.facebook.presto.bytecode.instruction.VariableInstruction.incrementVariable) ForLoop(com.facebook.presto.bytecode.control.ForLoop) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) ClassDefinition(com.facebook.presto.bytecode.ClassDefinition) MapType(com.facebook.presto.type.MapType) 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) List(java.util.List) ImmutableList(com.google.common.collect.ImmutableList) BytecodeNode(com.facebook.presto.bytecode.BytecodeNode) BlockBuilderStatus(com.facebook.presto.spi.block.BlockBuilderStatus) SqlTypeBytecodeExpression(com.facebook.presto.sql.gen.SqlTypeBytecodeExpression)

Example 27 with BytecodeNode

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

the class FunctionCallCodeGenerator method generateExpression.

@Override
public BytecodeNode generateExpression(Signature signature, BytecodeGeneratorContext context, Type returnType, List<RowExpression> arguments) {
    FunctionRegistry registry = context.getRegistry();
    ScalarFunctionImplementation function = registry.getScalarFunctionImplementation(signature);
    List<BytecodeNode> argumentsBytecode = new ArrayList<>();
    for (RowExpression argument : arguments) {
        argumentsBytecode.add(context.generate(argument));
    }
    return context.generateCall(signature.getName(), function, argumentsBytecode);
}
Also used : ScalarFunctionImplementation(com.facebook.presto.operator.scalar.ScalarFunctionImplementation) FunctionRegistry(com.facebook.presto.metadata.FunctionRegistry) ArrayList(java.util.ArrayList) RowExpression(com.facebook.presto.sql.relational.RowExpression) BytecodeNode(com.facebook.presto.bytecode.BytecodeNode)

Example 28 with BytecodeNode

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

the class InCodeGenerator method buildInCase.

private static BytecodeBlock buildInCase(BytecodeGeneratorContext generatorContext, Scope scope, Type type, LabelNode caseLabel, LabelNode matchLabel, LabelNode noMatchLabel, Collection<BytecodeNode> testValues, boolean checkForNulls) {
    // caseWasNull is set to true the first time a null in `testValues` is encountered
    Variable caseWasNull = null;
    if (checkForNulls) {
        caseWasNull = scope.createTempVariable(boolean.class);
    }
    BytecodeBlock caseBlock = new BytecodeBlock().visitLabel(caseLabel);
    if (checkForNulls) {
        caseBlock.putVariable(caseWasNull, false);
    }
    LabelNode elseLabel = new LabelNode("else");
    BytecodeBlock elseBlock = new BytecodeBlock().visitLabel(elseLabel);
    Variable wasNull = generatorContext.wasNull();
    if (checkForNulls) {
        elseBlock.append(wasNull.set(caseWasNull));
    }
    elseBlock.gotoLabel(noMatchLabel);
    ScalarFunctionImplementation operator = generatorContext.getRegistry().getScalarFunctionImplementation(internalOperator(EQUAL, BOOLEAN, ImmutableList.of(type, type)));
    Binding equalsFunction = generatorContext.getCallSiteBinder().bind(operator.getMethodHandle());
    BytecodeNode elseNode = elseBlock;
    for (BytecodeNode testNode : testValues) {
        LabelNode testLabel = new LabelNode("test");
        IfStatement test = new IfStatement();
        test.condition().visitLabel(testLabel).dup(type.getJavaType()).append(testNode);
        if (checkForNulls) {
            IfStatement wasNullCheck = new IfStatement("if wasNull, set caseWasNull to true, clear wasNull, pop 2 values of type, and goto next test value");
            wasNullCheck.condition(wasNull);
            wasNullCheck.ifTrue(new BytecodeBlock().append(caseWasNull.set(constantTrue())).append(wasNull.set(constantFalse())).pop(type.getJavaType()).pop(type.getJavaType()).gotoLabel(elseLabel));
            test.condition().append(wasNullCheck);
        }
        test.condition().append(invoke(equalsFunction, EQUAL.name()));
        test.ifTrue().gotoLabel(matchLabel);
        test.ifFalse(elseNode);
        elseNode = test;
        elseLabel = testLabel;
    }
    caseBlock.append(elseNode);
    return caseBlock;
}
Also used : LabelNode(com.facebook.presto.bytecode.instruction.LabelNode) ScalarFunctionImplementation(com.facebook.presto.operator.scalar.ScalarFunctionImplementation) IfStatement(com.facebook.presto.bytecode.control.IfStatement) Variable(com.facebook.presto.bytecode.Variable) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) BytecodeNode(com.facebook.presto.bytecode.BytecodeNode)

Example 29 with BytecodeNode

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

the class BytecodeGeneratorContext method generateCall.

/**
     * Generates a function call with null handling, automatic binding of session parameter, etc.
     */
public BytecodeNode generateCall(String name, ScalarFunctionImplementation function, List<BytecodeNode> arguments) {
    Binding binding = callSiteBinder.bind(function.getMethodHandle());
    Optional<BytecodeNode> instance = Optional.empty();
    if (function.getInstanceFactory().isPresent()) {
        FieldDefinition field = cachedInstanceBinder.getCachedInstance(function.getInstanceFactory().get());
        instance = Optional.of(scope.getThis().getField(field));
    }
    return generateInvocation(scope, name, function, instance, arguments, binding);
}
Also used : FieldDefinition(com.facebook.presto.bytecode.FieldDefinition) BytecodeNode(com.facebook.presto.bytecode.BytecodeNode)

Example 30 with BytecodeNode

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

the class AccumulatorCompiler method generateInputForLoop.

private static BytecodeBlock generateInputForLoop(FieldDefinition stateField, List<ParameterMetadata> parameterMetadatas, MethodHandle inputFunction, Scope scope, List<Variable> parameterVariables, Variable masksBlock, CallSiteBinder callSiteBinder, boolean grouped) {
    // For-loop over rows
    Variable page = scope.getVariable("page");
    Variable positionVariable = scope.declareVariable(int.class, "position");
    Variable rowsVariable = scope.declareVariable(int.class, "rows");
    BytecodeBlock block = new BytecodeBlock().append(page).invokeVirtual(Page.class, "getPositionCount", int.class).putVariable(rowsVariable).initializeVariable(positionVariable);
    BytecodeNode loopBody = generateInvokeInputFunction(scope, stateField, positionVariable, parameterVariables, parameterMetadatas, inputFunction, callSiteBinder, grouped);
    //  Wrap with null checks
    List<Boolean> nullable = new ArrayList<>();
    for (ParameterMetadata metadata : parameterMetadatas) {
        switch(metadata.getParameterType()) {
            case INPUT_CHANNEL:
            case BLOCK_INPUT_CHANNEL:
                nullable.add(false);
                break;
            case NULLABLE_BLOCK_INPUT_CHANNEL:
                nullable.add(true);
                break;
            // do nothing
            default:
        }
    }
    checkState(nullable.size() == parameterVariables.size(), "Number of parameters does not match");
    for (int i = 0; i < parameterVariables.size(); i++) {
        if (!nullable.get(i)) {
            Variable variableDefinition = parameterVariables.get(i);
            loopBody = new IfStatement("if(!%s.isNull(position))", variableDefinition.getName()).condition(new BytecodeBlock().getVariable(variableDefinition).getVariable(positionVariable).invokeInterface(Block.class, "isNull", boolean.class, int.class)).ifFalse(loopBody);
        }
    }
    loopBody = new IfStatement("if(testMask(%s, position))", masksBlock.getName()).condition(new BytecodeBlock().getVariable(masksBlock).getVariable(positionVariable).invokeStatic(CompilerOperations.class, "testMask", boolean.class, Block.class, int.class)).ifTrue(loopBody);
    block.append(new ForLoop().initialize(new BytecodeBlock().putVariable(positionVariable, 0)).condition(new BytecodeBlock().getVariable(positionVariable).getVariable(rowsVariable).invokeStatic(CompilerOperations.class, "lessThan", boolean.class, int.class, int.class)).update(new BytecodeBlock().incrementVariable(positionVariable, (byte) 1)).body(loopBody));
    return block;
}
Also used : IfStatement(com.facebook.presto.bytecode.control.IfStatement) Variable(com.facebook.presto.bytecode.Variable) ForLoop(com.facebook.presto.bytecode.control.ForLoop) CompilerOperations(com.facebook.presto.sql.gen.CompilerOperations) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) ArrayList(java.util.ArrayList) Block(com.facebook.presto.spi.block.Block) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) GroupByIdBlock(com.facebook.presto.operator.GroupByIdBlock) BytecodeNode(com.facebook.presto.bytecode.BytecodeNode) ParameterMetadata(com.facebook.presto.operator.aggregation.AggregationMetadata.ParameterMetadata)

Aggregations

BytecodeNode (com.facebook.presto.bytecode.BytecodeNode)42 Variable (com.facebook.presto.bytecode.Variable)33 BytecodeBlock (com.facebook.presto.bytecode.BytecodeBlock)29 IfStatement (com.facebook.presto.bytecode.control.IfStatement)23 Scope (com.facebook.presto.bytecode.Scope)21 MethodDefinition (com.facebook.presto.bytecode.MethodDefinition)19 Parameter (com.facebook.presto.bytecode.Parameter)16 LabelNode (com.facebook.presto.bytecode.instruction.LabelNode)12 ClassDefinition (com.facebook.presto.bytecode.ClassDefinition)7 ForLoop (com.facebook.presto.bytecode.control.ForLoop)7 RowExpression (com.facebook.presto.sql.relational.RowExpression)7 ArrayList (java.util.ArrayList)6 FieldDefinition (com.facebook.presto.bytecode.FieldDefinition)5 BytecodeExpression (com.facebook.presto.bytecode.expression.BytecodeExpression)5 Block (com.facebook.presto.common.block.Block)5 Type (com.facebook.presto.common.type.Type)5 FunctionHandle (com.facebook.presto.spi.function.FunctionHandle)5 RowExpression (com.facebook.presto.spi.relation.RowExpression)5 SqlTypeBytecodeExpression (com.facebook.presto.sql.gen.SqlTypeBytecodeExpression)5 ImmutableList (com.google.common.collect.ImmutableList)5