Search in sources :

Example 41 with MethodDefinition

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

the class PageProcessorCompiler method generateMethodsForLambdaAndTry.

private PreGeneratedExpressions generateMethodsForLambdaAndTry(ClassDefinition containerClassDefinition, CallSiteBinder callSiteBinder, CachedInstanceBinder cachedInstanceBinder, RowExpression projection, String methodPrefix) {
    Set<RowExpression> lambdaAndTryExpressions = ImmutableSet.copyOf(extractLambdaAndTryExpressions(projection));
    ImmutableMap.Builder<CallExpression, MethodDefinition> tryMethodMap = ImmutableMap.builder();
    ImmutableMap.Builder<LambdaDefinitionExpression, FieldDefinition> lambdaFieldMap = ImmutableMap.builder();
    int counter = 0;
    for (RowExpression expression : lambdaAndTryExpressions) {
        if (expression instanceof CallExpression) {
            CallExpression tryExpression = (CallExpression) expression;
            verify(!Signatures.TRY.equals(tryExpression.getSignature().getName()));
            Parameter session = arg("session", ConnectorSession.class);
            List<Parameter> blocks = toBlockParameters(getInputChannels(tryExpression.getArguments()));
            Parameter position = arg("position", int.class);
            BytecodeExpressionVisitor innerExpressionVisitor = new BytecodeExpressionVisitor(callSiteBinder, cachedInstanceBinder, fieldReferenceCompiler(callSiteBinder), metadata.getFunctionRegistry(), new PreGeneratedExpressions(tryMethodMap.build(), lambdaFieldMap.build()));
            List<Parameter> inputParameters = ImmutableList.<Parameter>builder().add(session).addAll(blocks).add(position).build();
            MethodDefinition tryMethod = defineTryMethod(innerExpressionVisitor, containerClassDefinition, methodPrefix + "_try_" + counter, inputParameters, Primitives.wrap(tryExpression.getType().getJavaType()), tryExpression, callSiteBinder);
            tryMethodMap.put(tryExpression, tryMethod);
        } else if (expression instanceof LambdaDefinitionExpression) {
            LambdaDefinitionExpression lambdaExpression = (LambdaDefinitionExpression) expression;
            PreGeneratedExpressions preGeneratedExpressions = new PreGeneratedExpressions(tryMethodMap.build(), lambdaFieldMap.build());
            FieldDefinition methodHandleField = LambdaBytecodeGenerator.preGenerateLambdaExpression(lambdaExpression, methodPrefix + "_lambda_" + counter, containerClassDefinition, preGeneratedExpressions, callSiteBinder, cachedInstanceBinder, metadata.getFunctionRegistry());
            lambdaFieldMap.put(lambdaExpression, methodHandleField);
        } else {
            throw new VerifyException(format("unexpected expression: %s", expression.toString()));
        }
        counter++;
    }
    return new PreGeneratedExpressions(tryMethodMap.build(), lambdaFieldMap.build());
}
Also used : FieldDefinition(com.facebook.presto.bytecode.FieldDefinition) RowExpression(com.facebook.presto.sql.relational.RowExpression) ImmutableMap(com.google.common.collect.ImmutableMap) VerifyException(com.google.common.base.VerifyException) MethodDefinition(com.facebook.presto.bytecode.MethodDefinition) Parameter(com.facebook.presto.bytecode.Parameter) CallExpression(com.facebook.presto.sql.relational.CallExpression) LambdaDefinitionExpression(com.facebook.presto.sql.relational.LambdaDefinitionExpression)

Example 42 with MethodDefinition

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

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

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

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

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