Search in sources :

Example 71 with Variable

use of com.facebook.presto.bytecode.Variable 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 72 with Variable

use of com.facebook.presto.bytecode.Variable 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 73 with Variable

use of com.facebook.presto.bytecode.Variable 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)

Example 74 with Variable

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

the class LambdaBytecodeGenerator method defineLambdaMethodAndField.

private static FieldDefinition defineLambdaMethodAndField(BytecodeExpressionVisitor innerExpressionVisitor, ClassDefinition classDefinition, String fieldAndMethodName, List<Parameter> inputParameters, LambdaDefinitionExpression lambda) {
    Class<?> returnType = Primitives.wrap(lambda.getBody().getType().getJavaType());
    MethodDefinition method = classDefinition.declareMethod(a(PUBLIC), fieldAndMethodName, type(returnType), inputParameters);
    Scope scope = method.getScope();
    Variable wasNull = scope.declareVariable(boolean.class, "wasNull");
    BytecodeNode compiledBody = lambda.getBody().accept(innerExpressionVisitor, scope);
    method.getBody().putVariable(wasNull, false).append(compiledBody).append(boxPrimitiveIfNecessary(scope, returnType)).ret(returnType);
    FieldDefinition methodHandleField = classDefinition.declareField(a(PRIVATE, STATIC, FINAL), fieldAndMethodName, type(MethodHandle.class));
    classDefinition.getClassInitializer().getBody().append(setStatic(methodHandleField, invokeStatic(Reflection.class, "methodHandle", MethodHandle.class, constantClass(classDefinition.getType()), constantString(fieldAndMethodName), newArray(type(Class[].class), inputParameters.stream().map(Parameter::getType).map(BytecodeExpressions::constantClass).collect(toImmutableList())))));
    return methodHandleField;
}
Also used : Variable(com.facebook.presto.bytecode.Variable) Scope(com.facebook.presto.bytecode.Scope) MethodDefinition(com.facebook.presto.bytecode.MethodDefinition) FieldDefinition(com.facebook.presto.bytecode.FieldDefinition) Parameter(com.facebook.presto.bytecode.Parameter) BytecodeNode(com.facebook.presto.bytecode.BytecodeNode) BytecodeExpressions.constantClass(com.facebook.presto.bytecode.expression.BytecodeExpressions.constantClass) MethodHandle(java.lang.invoke.MethodHandle)

Example 75 with Variable

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

the class PageProcessorCompiler method generateProjectDictionaryMethod.

private MethodDefinition generateProjectDictionaryMethod(ClassDefinition classDefinition, String methodName, RowExpression projection, MethodDefinition project, MethodDefinition projectColumnar, MethodDefinition projectRLE) {
    Parameter session = arg("session", ConnectorSession.class);
    Parameter page = arg("page", Page.class);
    Parameter selectedPositions = arg("selectedPositions", int[].class);
    Parameter pageBuilder = arg("pageBuilder", PageBuilder.class);
    Parameter projectionIndex = arg("projectionIndex", int.class);
    Parameter dictionarySourceIds = arg("dictionarySourceIds", Map.class);
    List<Parameter> params = ImmutableList.<Parameter>builder().add(session).add(page).add(selectedPositions).add(pageBuilder).add(projectionIndex).add(dictionarySourceIds).build();
    List<Parameter> columnarParams = ImmutableList.<Parameter>builder().add(session).add(page).add(selectedPositions).add(pageBuilder).add(projectionIndex).build();
    MethodDefinition method = classDefinition.declareMethod(a(PRIVATE), methodName, type(Block.class), params);
    BytecodeBlock body = method.getBody();
    Scope scope = method.getScope();
    Variable thisVariable = method.getThis();
    List<Integer> inputChannels = getInputChannels(projection);
    if (inputChannels.size() != 1 || !determinismEvaluator.isDeterministic(projection)) {
        body.append(thisVariable.invoke(projectColumnar, columnarParams).ret());
        return method;
    }
    Variable inputBlock = scope.declareVariable("inputBlock", body, page.invoke("getBlock", Block.class, constantInt(getOnlyElement(inputChannels))));
    body.append(new IfStatement().condition(inputBlock.instanceOf(RunLengthEncodedBlock.class)).ifTrue(thisVariable.invoke(projectRLE, columnarParams).ret()));
    body.append(new IfStatement().condition(inputBlock.instanceOf(DictionaryBlock.class)).ifFalse(thisVariable.invoke(projectColumnar, columnarParams).ret()));
    Variable blockBuilder = scope.declareVariable("blockBuilder", body, pageBuilder.invoke("getBlockBuilder", BlockBuilder.class, projectionIndex));
    Variable cardinality = scope.declareVariable("cardinality", body, selectedPositions.length());
    Variable dictionary = scope.declareVariable(Block.class, "dictionary");
    Variable dictionaryCount = scope.declareVariable(int.class, "dictionaryCount");
    Variable inputSourceId = scope.declareVariable(DictionaryId.class, "inputSourceId");
    Variable outputSourceId = scope.declareVariable(DictionaryId.class, "outputSourceId");
    Variable outputDictionary = scope.declareVariable(Block.class, "outputDictionary");
    Variable outputIds = scope.declareVariable(int[].class, "outputIds");
    BytecodeExpression inputDictionaries = thisVariable.getField("inputDictionaries", Block[].class);
    BytecodeExpression outputDictionaries = thisVariable.getField("outputDictionaries", Block[].class);
    Variable position = scope.declareVariable("position", body, constantInt(0));
    BytecodeExpression castDictionaryBlock = inputBlock.cast(DictionaryBlock.class);
    body.comment("Extract dictionary, ids, positionCount and dictionarySourceId").append(dictionary.set(castDictionaryBlock.invoke("getDictionary", Block.class))).append(dictionaryCount.set(dictionary.invoke("getPositionCount", int.class))).append(inputSourceId.set(castDictionaryBlock.invoke("getDictionarySourceId", DictionaryId.class)));
    BytecodeBlock projectDictionary = new BytecodeBlock().comment("Project dictionary").append(new ForLoop().initialize(position.set(constantInt(0))).condition(lessThan(position, dictionaryCount)).update(position.increment()).body(invokeProject(thisVariable, session, ImmutableList.of(dictionary), position, pageBuilder, projectionIndex, project))).append(outputDictionary.set(blockBuilder.invoke("build", Block.class))).append(inputDictionaries.setElement(projectionIndex, dictionary)).append(outputDictionaries.setElement(projectionIndex, outputDictionary));
    body.comment("Use processed dictionary, if available, else project it").append(new IfStatement().condition(equal(inputDictionaries.getElement(projectionIndex), dictionary)).ifTrue(outputDictionary.set(outputDictionaries.getElement(projectionIndex))).ifFalse(projectDictionary));
    body.comment("Filter ids").append(outputIds.set(newArray(type(int[].class), cardinality))).append(new ForLoop().initialize(position.set(constantInt(0))).condition(lessThan(position, cardinality)).update(position.increment()).body(outputIds.setElement(position, castDictionaryBlock.invoke("getId", int.class, selectedPositions.getElement(position)))));
    body.append(outputSourceId.set(dictionarySourceIds.invoke("get", Object.class, inputSourceId.cast(Object.class)).cast(DictionaryId.class)));
    body.append(new IfStatement().condition(equal(outputSourceId, constantNull(DictionaryId.class))).ifTrue(new BytecodeBlock().append(outputSourceId.set(invokeStatic(DictionaryId.class, "randomDictionaryId", DictionaryId.class))).append(dictionarySourceIds.invoke("put", Object.class, inputSourceId.cast(Object.class), outputSourceId.cast(Object.class))).pop()));
    body.append(newInstance(DictionaryBlock.class, cardinality, outputDictionary, outputIds, constantFalse(), outputSourceId).cast(Block.class).ret());
    return method;
}
Also used : 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) 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) BytecodeExpression(com.facebook.presto.bytecode.expression.BytecodeExpression) BlockBuilder(com.facebook.presto.spi.block.BlockBuilder)

Aggregations

Variable (com.facebook.presto.bytecode.Variable)131 BytecodeBlock (com.facebook.presto.bytecode.BytecodeBlock)104 MethodDefinition (com.facebook.presto.bytecode.MethodDefinition)91 Parameter (com.facebook.presto.bytecode.Parameter)75 Scope (com.facebook.presto.bytecode.Scope)68 IfStatement (com.facebook.presto.bytecode.control.IfStatement)68 BytecodeExpression (com.facebook.presto.bytecode.expression.BytecodeExpression)40 BytecodeNode (com.facebook.presto.bytecode.BytecodeNode)36 ImmutableList (com.google.common.collect.ImmutableList)30 LabelNode (com.facebook.presto.bytecode.instruction.LabelNode)28 ClassDefinition (com.facebook.presto.bytecode.ClassDefinition)21 ForLoop (com.facebook.presto.bytecode.control.ForLoop)21 Block (com.facebook.presto.spi.block.Block)19 Block (com.facebook.presto.common.block.Block)18 List (java.util.List)17 CallSiteBinder (com.facebook.presto.bytecode.CallSiteBinder)16 FieldDefinition (com.facebook.presto.bytecode.FieldDefinition)15 Type (com.facebook.presto.common.type.Type)15 RowExpression (com.facebook.presto.spi.relation.RowExpression)15 ImmutableList.toImmutableList (com.google.common.collect.ImmutableList.toImmutableList)14