Search in sources :

Example 51 with BytecodeBlock

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

the class PageProcessorCompiler method getBytecodeFilterOnDictionary.

private static BytecodeBlock getBytecodeFilterOnDictionary(Parameter session, Scope scope, Variable blockVariable) {
    Variable position = scope.getVariable("position");
    Variable positionCount = scope.getVariable("positionCount");
    Variable selectedCount = scope.getVariable("selectedCount");
    Variable selectedPositions = scope.getVariable("selectedPositions");
    Variable thisVariable = scope.getThis();
    BytecodeExpression inputFilterDictionary = thisVariable.getField("inputFilterDictionary", Block.class);
    BytecodeExpression filterResult = thisVariable.getField("filterResult", boolean[].class);
    BytecodeBlock ifFilterOnDictionaryBlock = new BytecodeBlock();
    Variable dictionaryBlock = scope.declareVariable("dictionaryBlock", ifFilterOnDictionaryBlock, blockVariable.cast(DictionaryBlock.class));
    Variable dictionary = scope.declareVariable("dictionary", ifFilterOnDictionaryBlock, dictionaryBlock.invoke("getDictionary", Block.class));
    Variable dictionaryPositionCount = scope.declareVariable("dictionaryPositionCount", ifFilterOnDictionaryBlock, dictionary.invoke("getPositionCount", int.class));
    Variable selectedDictionaryPositions = scope.declareVariable("selectedDictionaryPositions", ifFilterOnDictionaryBlock, newArray(type(boolean[].class), dictionaryPositionCount));
    // if cached value is available use it else filter dictionary and cache it
    ifFilterOnDictionaryBlock.append(new IfStatement().condition(equal(dictionary, inputFilterDictionary)).ifTrue(selectedDictionaryPositions.set(filterResult)).ifFalse(new BytecodeBlock().append(new ForLoop().initialize(position.set(constantInt(0))).condition(lessThan(position, dictionaryPositionCount)).update(position.increment()).body(selectedDictionaryPositions.setElement(position, invokeFilter(thisVariable, session, singletonList(dictionary), position)))).append(thisVariable.setField("inputFilterDictionary", dictionary)).append(thisVariable.setField("filterResult", selectedDictionaryPositions))));
    // create selected positions
    ifFilterOnDictionaryBlock.append(new ForLoop().initialize(position.set(constantInt(0))).condition(lessThan(position, positionCount)).update(position.increment()).body(new IfStatement().condition(selectedDictionaryPositions.getElement(dictionaryBlock.invoke("getId", int.class, position))).ifTrue(new BytecodeBlock().append(selectedPositions.setElement(selectedCount, position)).append(selectedCount.increment()))));
    // return selectedPositions
    ifFilterOnDictionaryBlock.append(invokeStatic(Arrays.class, "copyOf", int[].class, selectedPositions, selectedCount).ret());
    return ifFilterOnDictionaryBlock;
}
Also used : IfStatement(com.facebook.presto.bytecode.control.IfStatement) Variable(com.facebook.presto.bytecode.Variable) ForLoop(com.facebook.presto.bytecode.control.ForLoop) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) DictionaryBlock(com.facebook.presto.spi.block.DictionaryBlock) 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) BytecodeExpression(com.facebook.presto.bytecode.expression.BytecodeExpression)

Example 52 with BytecodeBlock

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

the class PageProcessorCompiler method generateProcessColumnarMethod.

private static void generateProcessColumnarMethod(ClassDefinition classDefinition, List<RowExpression> projections, List<MethodDefinition> projectColumnarMethods) {
    Parameter session = arg("session", ConnectorSession.class);
    Parameter page = arg("page", Page.class);
    Parameter types = arg("types", List.class);
    MethodDefinition method = classDefinition.declareMethod(a(PUBLIC), "processColumnar", type(Page.class), session, page, types);
    Scope scope = method.getScope();
    BytecodeBlock body = method.getBody();
    Variable thisVariable = method.getThis();
    Variable selectedPositions = scope.declareVariable("selectedPositions", body, thisVariable.invoke("filterPage", int[].class, session, page));
    Variable cardinality = scope.declareVariable("cardinality", body, selectedPositions.length());
    body.comment("if no rows selected return null").append(new IfStatement().condition(equal(cardinality, constantInt(0))).ifTrue(constantNull(Page.class).ret()));
    if (projections.isEmpty()) {
        // if no projections, return new page with selected rows
        body.append(newInstance(Page.class, cardinality, newArray(type(Block[].class), 0)).ret());
        return;
    }
    Variable pageBuilder = scope.declareVariable("pageBuilder", body, newInstance(PageBuilder.class, cardinality, types));
    Variable outputBlocks = scope.declareVariable("outputBlocks", body, newArray(type(Block[].class), projections.size()));
    for (int projectionIndex = 0; projectionIndex < projections.size(); projectionIndex++) {
        List<BytecodeExpression> params = ImmutableList.<BytecodeExpression>builder().add(session).add(page).add(selectedPositions).add(pageBuilder).add(constantInt(projectionIndex)).build();
        body.append(outputBlocks.setElement(projectionIndex, thisVariable.invoke(projectColumnarMethods.get(projectionIndex), params)));
    }
    // create new page from outputBlocks
    body.append(newInstance(Page.class, cardinality, outputBlocks).ret());
}
Also used : IfStatement(com.facebook.presto.bytecode.control.IfStatement) Variable(com.facebook.presto.bytecode.Variable) Scope(com.facebook.presto.bytecode.Scope) MethodDefinition(com.facebook.presto.bytecode.MethodDefinition) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) 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) Page(com.facebook.presto.spi.Page) PageBuilder(com.facebook.presto.spi.PageBuilder) BytecodeExpression(com.facebook.presto.bytecode.expression.BytecodeExpression)

Example 53 with BytecodeBlock

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

the class PageProcessorCompiler method generateProcessMethod.

private static void generateProcessMethod(ClassDefinition classDefinition, RowExpression filter, List<RowExpression> projections, List<MethodDefinition> projectionMethods) {
    Parameter session = arg("session", ConnectorSession.class);
    Parameter page = arg("page", Page.class);
    Parameter start = arg("start", int.class);
    Parameter end = arg("end", int.class);
    Parameter pageBuilder = arg("pageBuilder", PageBuilder.class);
    MethodDefinition method = classDefinition.declareMethod(a(PUBLIC), "process", type(int.class), session, page, start, end, pageBuilder);
    Scope scope = method.getScope();
    BytecodeBlock body = method.getBody();
    Variable thisVariable = method.getThis();
    // extract blocks
    List<Integer> allInputChannels = getInputChannels(concat(projections, ImmutableList.of(filter)));
    ImmutableMap.Builder<Integer, Variable> builder = ImmutableMap.builder();
    for (int channel : allInputChannels) {
        Variable blockVariable = scope.declareVariable("block_" + channel, body, page.invoke("getBlock", Block.class, constantInt(channel)));
        builder.put(channel, blockVariable);
    }
    Map<Integer, Variable> channelBlocks = builder.build();
    Map<RowExpression, List<Variable>> expressionInputBlocks = getExpressionInputBlocks(projections, filter, channelBlocks);
    // projection body
    Variable position = scope.declareVariable(int.class, "position");
    BytecodeBlock project = new BytecodeBlock().append(pageBuilder.invoke("declarePosition", void.class));
    for (int projectionIndex = 0; projectionIndex < projections.size(); projectionIndex++) {
        RowExpression projection = projections.get(projectionIndex);
        project.append(invokeProject(thisVariable, session, expressionInputBlocks.get(projection), position, pageBuilder, constantInt(projectionIndex), projectionMethods.get(projectionIndex)));
    }
    LabelNode done = new LabelNode("done");
    // for loop loop body
    ForLoop loop = new ForLoop().initialize(position.set(start)).condition(lessThan(position, end)).update(position.set(add(position, constantInt(1)))).body(new BytecodeBlock().append(new IfStatement().condition(pageBuilder.invoke("isFull", boolean.class)).ifTrue(jump(done))).append(new IfStatement().condition(invokeFilter(thisVariable, session, expressionInputBlocks.get(filter), position)).ifTrue(project)));
    body.append(loop).visitLabel(done).append(position.ret());
}
Also used : LabelNode(com.facebook.presto.bytecode.instruction.LabelNode) Variable(com.facebook.presto.bytecode.Variable) ForLoop(com.facebook.presto.bytecode.control.ForLoop) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) RowExpression(com.facebook.presto.sql.relational.RowExpression) ImmutableMap(com.google.common.collect.ImmutableMap) 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) Collections.singletonList(java.util.Collections.singletonList) List(java.util.List) ImmutableList(com.google.common.collect.ImmutableList) Collectors.toList(java.util.stream.Collectors.toList)

Example 54 with BytecodeBlock

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

the class RowConstructorCodeGenerator method generateExpression.

@Override
public BytecodeNode generateExpression(Signature signature, BytecodeGeneratorContext context, Type rowType, List<RowExpression> arguments) {
    BytecodeBlock block = new BytecodeBlock().setDescription("Constructor for " + rowType.toString());
    CallSiteBinder binder = context.getCallSiteBinder();
    Scope scope = context.getScope();
    List<Type> types = rowType.getTypeParameters();
    block.comment("BlockBuilder blockBuilder = new InterleavedBlockBuilder(types, new BlockBuilderStatus(), 1);");
    Variable blockBuilder = scope.createTempVariable(BlockBuilder.class);
    Binding typesBinding = binder.bind(types, List.class);
    block.append(blockBuilder.set(newInstance(InterleavedBlockBuilder.class, loadConstant(typesBinding), newInstance(BlockBuilderStatus.class), constantInt(1))));
    for (int i = 0; i < arguments.size(); ++i) {
        Type fieldType = types.get(i);
        Class<?> javaType = fieldType.getJavaType();
        if (javaType == void.class) {
            block.comment(i + "-th field type of row is undefined");
            block.append(blockBuilder.invoke("appendNull", BlockBuilder.class).pop());
        } else {
            Variable field = scope.createTempVariable(javaType);
            block.comment("Clean wasNull and Generate + " + i + "-th field of row");
            block.append(context.wasNull().set(constantFalse()));
            block.append(context.generate(arguments.get(i)));
            block.putVariable(field);
            block.append(new IfStatement().condition(context.wasNull()).ifTrue(blockBuilder.invoke("appendNull", BlockBuilder.class).pop()).ifFalse(constantType(binder, fieldType).writeValue(blockBuilder, field).pop()));
        }
    }
    block.comment("put (Block) blockBuilder.build(); wasNull = false;");
    block.append(blockBuilder.invoke("build", Block.class));
    block.append(context.wasNull().set(constantFalse()));
    return block;
}
Also used : IfStatement(com.facebook.presto.bytecode.control.IfStatement) SqlTypeBytecodeExpression.constantType(com.facebook.presto.sql.gen.SqlTypeBytecodeExpression.constantType) Type(com.facebook.presto.spi.type.Type) Variable(com.facebook.presto.bytecode.Variable) Scope(com.facebook.presto.bytecode.Scope) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) Block(com.facebook.presto.spi.block.Block) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) BlockBuilderStatus(com.facebook.presto.spi.block.BlockBuilderStatus)

Example 55 with BytecodeBlock

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

the class SwitchCodeGenerator method generateExpression.

@Override
public BytecodeNode generateExpression(Signature signature, BytecodeGeneratorContext generatorContext, Type returnType, List<RowExpression> arguments) {
    // TODO: compile as
    /*
            hashCode = hashCode(<value>)

            // all constant expressions before a non-constant
            switch (hashCode) {
                case ...:
                    if (<value> == <constant1>) {
                       ...
                    }
                    else if (<value> == <constant2>) {
                       ...
                    }
                    else if (...) {
                    }
                case ...:
                    ...
            }

            if (<value> == <non-constant1>) {
                ...
            }
            else if (<value> == <non-constant2>) {
                ...
            }
            ...

            // repeat with next sequence of constant expressions
         */
    Scope scope = generatorContext.getScope();
    // process value, else, and all when clauses
    RowExpression value = arguments.get(0);
    BytecodeNode valueBytecode = generatorContext.generate(value);
    BytecodeNode elseValue;
    List<RowExpression> whenClauses;
    RowExpression last = arguments.get(arguments.size() - 1);
    if (last instanceof CallExpression && ((CallExpression) last).getSignature().getName().equals("WHEN")) {
        whenClauses = arguments.subList(1, arguments.size());
        elseValue = new BytecodeBlock().append(generatorContext.wasNull().set(constantTrue())).pushJavaDefault(returnType.getJavaType());
    } else {
        whenClauses = arguments.subList(1, arguments.size() - 1);
        elseValue = generatorContext.generate(last);
    }
    // determine the type of the value and result
    Class<?> valueType = value.getType().getJavaType();
    // evaluate the value and store it in a variable
    LabelNode nullValue = new LabelNode("nullCondition");
    Variable tempVariable = scope.createTempVariable(valueType);
    BytecodeBlock block = new BytecodeBlock().append(valueBytecode).append(BytecodeUtils.ifWasNullClearPopAndGoto(scope, nullValue, void.class, valueType)).putVariable(tempVariable);
    BytecodeNode getTempVariableNode = VariableInstruction.loadVariable(tempVariable);
    // build the statements
    elseValue = new BytecodeBlock().visitLabel(nullValue).append(elseValue);
    // reverse list because current if statement builder doesn't support if/else so we need to build the if statements bottom up
    for (RowExpression clause : Lists.reverse(whenClauses)) {
        Preconditions.checkArgument(clause instanceof CallExpression && ((CallExpression) clause).getSignature().getName().equals("WHEN"));
        RowExpression operand = ((CallExpression) clause).getArguments().get(0);
        RowExpression result = ((CallExpression) clause).getArguments().get(1);
        // call equals(value, operand)
        Signature equalsFunction = generatorContext.getRegistry().resolveOperator(OperatorType.EQUAL, ImmutableList.of(value.getType(), operand.getType()));
        // TODO: what if operand is null? It seems that the call will return "null" (which is cleared below)
        // and the code only does the right thing because the value in the stack for that scenario is
        // Java's default for boolean == false
        // This code should probably be checking for wasNull after the call and "failing" the equality
        // check if wasNull is true
        BytecodeNode equalsCall = generatorContext.generateCall(equalsFunction.getName(), generatorContext.getRegistry().getScalarFunctionImplementation(equalsFunction), ImmutableList.of(generatorContext.generate(operand), getTempVariableNode));
        BytecodeBlock condition = new BytecodeBlock().append(equalsCall).append(generatorContext.wasNull().set(constantFalse()));
        elseValue = new IfStatement("when").condition(condition).ifTrue(generatorContext.generate(result)).ifFalse(elseValue);
    }
    return block.append(elseValue);
}
Also used : LabelNode(com.facebook.presto.bytecode.instruction.LabelNode) IfStatement(com.facebook.presto.bytecode.control.IfStatement) Variable(com.facebook.presto.bytecode.Variable) Scope(com.facebook.presto.bytecode.Scope) Signature(com.facebook.presto.metadata.Signature) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) RowExpression(com.facebook.presto.sql.relational.RowExpression) BytecodeNode(com.facebook.presto.bytecode.BytecodeNode) CallExpression(com.facebook.presto.sql.relational.CallExpression)

Aggregations

BytecodeBlock (com.facebook.presto.bytecode.BytecodeBlock)82 Variable (com.facebook.presto.bytecode.Variable)57 MethodDefinition (com.facebook.presto.bytecode.MethodDefinition)43 IfStatement (com.facebook.presto.bytecode.control.IfStatement)42 Parameter (com.facebook.presto.bytecode.Parameter)38 Scope (com.facebook.presto.bytecode.Scope)33 Block (com.facebook.presto.spi.block.Block)23 BytecodeExpression (com.facebook.presto.bytecode.expression.BytecodeExpression)18 LabelNode (com.facebook.presto.bytecode.instruction.LabelNode)18 BytecodeNode (com.facebook.presto.bytecode.BytecodeNode)17 ImmutableList (com.google.common.collect.ImmutableList)16 ForLoop (com.facebook.presto.bytecode.control.ForLoop)12 Type (com.facebook.presto.spi.type.Type)12 ClassDefinition (com.facebook.presto.bytecode.ClassDefinition)11 DictionaryBlock (com.facebook.presto.spi.block.DictionaryBlock)11 LazyBlock (com.facebook.presto.spi.block.LazyBlock)11 RunLengthEncodedBlock (com.facebook.presto.spi.block.RunLengthEncodedBlock)11 BlockBuilder (com.facebook.presto.spi.block.BlockBuilder)10 List (java.util.List)9 RowExpression (com.facebook.presto.sql.relational.RowExpression)7