Search in sources :

Example 31 with Variable

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

the class CursorProcessorCompiler method generateMethods.

@Override
public void generateMethods(SqlFunctionProperties sqlFunctionProperties, ClassDefinition classDefinition, CallSiteBinder callSiteBinder, RowExpression filter, List<RowExpression> projections) {
    CachedInstanceBinder cachedInstanceBinder = new CachedInstanceBinder(classDefinition, callSiteBinder);
    List<RowExpression> rowExpressions = ImmutableList.<RowExpression>builder().addAll(projections).add(filter).build();
    Map<LambdaDefinitionExpression, CompiledLambda> compiledLambdaMap = generateMethodsForLambda(classDefinition, callSiteBinder, cachedInstanceBinder, rowExpressions, metadata, sqlFunctionProperties, sessionFunctions, "");
    Map<VariableReferenceExpression, CommonSubExpressionFields> cseFields = ImmutableMap.of();
    RowExpressionCompiler compiler = new RowExpressionCompiler(classDefinition, callSiteBinder, cachedInstanceBinder, fieldReferenceCompiler(cseFields), metadata, sqlFunctionProperties, sessionFunctions, compiledLambdaMap);
    if (isOptimizeCommonSubExpressions) {
        Map<Integer, Map<RowExpression, VariableReferenceExpression>> commonSubExpressionsByLevel = collectCSEByLevel(rowExpressions);
        if (!commonSubExpressionsByLevel.isEmpty()) {
            cseFields = declareCommonSubExpressionFields(classDefinition, commonSubExpressionsByLevel);
            compiler = new RowExpressionCompiler(classDefinition, callSiteBinder, cachedInstanceBinder, fieldReferenceCompiler(cseFields), metadata, sqlFunctionProperties, sessionFunctions, compiledLambdaMap);
            generateCommonSubExpressionMethods(classDefinition, compiler, commonSubExpressionsByLevel, cseFields);
            Map<RowExpression, VariableReferenceExpression> commonSubExpressions = commonSubExpressionsByLevel.values().stream().flatMap(m -> m.entrySet().stream()).collect(toImmutableMap(Map.Entry::getKey, Map.Entry::getValue));
            projections = rewriteRowExpressionsWithCSE(projections, commonSubExpressions);
            filter = rewriteRowExpressionsWithCSE(ImmutableList.of(filter), commonSubExpressions).get(0);
        }
    }
    generateProcessMethod(classDefinition, projections.size(), cseFields);
    generateFilterMethod(classDefinition, compiler, filter);
    for (int i = 0; i < projections.size(); i++) {
        String methodName = "project_" + i;
        generateProjectMethod(classDefinition, compiler, methodName, projections.get(i));
    }
    MethodDefinition constructorDefinition = classDefinition.declareConstructor(a(PUBLIC));
    BytecodeBlock constructorBody = constructorDefinition.getBody();
    Variable thisVariable = constructorDefinition.getThis();
    constructorBody.comment("super();").append(thisVariable).invokeConstructor(Object.class);
    initializeCommonSubExpressionFields(cseFields.values(), thisVariable, constructorBody);
    cachedInstanceBinder.generateInitializations(thisVariable, constructorBody);
    constructorBody.ret();
}
Also used : CursorProcessorOutput(com.facebook.presto.operator.project.CursorProcessorOutput) RowExpressionVisitor(com.facebook.presto.spi.relation.RowExpressionVisitor) VariableReferenceExpression(com.facebook.presto.spi.relation.VariableReferenceExpression) SqlInvokedFunction(com.facebook.presto.spi.function.SqlInvokedFunction) MethodDefinition(com.facebook.presto.bytecode.MethodDefinition) PageBuilder(com.facebook.presto.common.PageBuilder) Access.a(com.facebook.presto.bytecode.Access.a) JumpInstruction.jump(com.facebook.presto.bytecode.instruction.JumpInstruction.jump) CallSiteBinder(com.facebook.presto.bytecode.CallSiteBinder) ParameterizedType.type(com.facebook.presto.bytecode.ParameterizedType.type) BytecodeUtils.boxPrimitiveIfNecessary(com.facebook.presto.sql.gen.BytecodeUtils.boxPrimitiveIfNecessary) CommonSubExpressionRewriter.collectCSEByLevel(com.facebook.presto.sql.gen.CommonSubExpressionRewriter.collectCSEByLevel) Map(java.util.Map) CallExpression(com.facebook.presto.spi.relation.CallExpression) SpecialFormExpression(com.facebook.presto.spi.relation.SpecialFormExpression) IfStatement(com.facebook.presto.bytecode.control.IfStatement) Variable(com.facebook.presto.bytecode.Variable) CommonSubExpressionRewriter.rewriteExpressionWithCSE(com.facebook.presto.sql.gen.CommonSubExpressionRewriter.rewriteExpressionWithCSE) BlockBuilder(com.facebook.presto.common.block.BlockBuilder) Parameter(com.facebook.presto.bytecode.Parameter) ImmutableMap(com.google.common.collect.ImmutableMap) SqlFunctionProperties(com.facebook.presto.common.function.SqlFunctionProperties) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) LambdaDefinitionExpression(com.facebook.presto.spi.relation.LambdaDefinitionExpression) BytecodeExpressions.constantBoolean(com.facebook.presto.bytecode.expression.BytecodeExpressions.constantBoolean) String.format(java.lang.String.format) CompiledLambda(com.facebook.presto.sql.gen.LambdaBytecodeGenerator.CompiledLambda) ClassDefinition(com.facebook.presto.bytecode.ClassDefinition) RecordCursor(com.facebook.presto.spi.RecordCursor) List(java.util.List) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap) Scope(com.facebook.presto.bytecode.Scope) Optional(java.util.Optional) InputReferenceExpression(com.facebook.presto.spi.relation.InputReferenceExpression) LabelNode(com.facebook.presto.bytecode.instruction.LabelNode) Parameter.arg(com.facebook.presto.bytecode.Parameter.arg) Logger(com.facebook.airlift.log.Logger) Slice(io.airlift.slice.Slice) DriverYieldSignal(com.facebook.presto.operator.DriverYieldSignal) PRIVATE(com.facebook.presto.bytecode.Access.PRIVATE) HashMap(java.util.HashMap) ConstantExpression(com.facebook.presto.spi.relation.ConstantExpression) BytecodeExpressions.constantFalse(com.facebook.presto.bytecode.expression.BytecodeExpressions.constantFalse) CommonSubExpressionFields.initializeCommonSubExpressionFields(com.facebook.presto.sql.gen.CommonSubExpressionRewriter.CommonSubExpressionFields.initializeCommonSubExpressionFields) WhileLoop(com.facebook.presto.bytecode.control.WhileLoop) ImmutableList(com.google.common.collect.ImmutableList) BytecodeExpressions.or(com.facebook.presto.bytecode.expression.BytecodeExpressions.or) LambdaBytecodeGenerator.generateMethodsForLambda(com.facebook.presto.sql.gen.LambdaBytecodeGenerator.generateMethodsForLambda) BytecodeExpressions.constantTrue(com.facebook.presto.bytecode.expression.BytecodeExpressions.constantTrue) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) CommonSubExpressionFields.declareCommonSubExpressionFields(com.facebook.presto.sql.gen.CommonSubExpressionRewriter.CommonSubExpressionFields.declareCommonSubExpressionFields) Type(com.facebook.presto.common.type.Type) RowExpression(com.facebook.presto.spi.relation.RowExpression) PUBLIC(com.facebook.presto.bytecode.Access.PUBLIC) BytecodeExpressions.newInstance(com.facebook.presto.bytecode.expression.BytecodeExpressions.newInstance) Primitives(com.google.common.primitives.Primitives) BytecodeNode(com.facebook.presto.bytecode.BytecodeNode) SqlFunctionId(com.facebook.presto.spi.function.SqlFunctionId) CommonSubExpressionFields(com.facebook.presto.sql.gen.CommonSubExpressionRewriter.CommonSubExpressionFields) BytecodeUtils.unboxPrimitiveIfNecessary(com.facebook.presto.sql.gen.BytecodeUtils.unboxPrimitiveIfNecessary) Metadata(com.facebook.presto.metadata.Metadata) Variable(com.facebook.presto.bytecode.Variable) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) RowExpression(com.facebook.presto.spi.relation.RowExpression) CompiledLambda(com.facebook.presto.sql.gen.LambdaBytecodeGenerator.CompiledLambda) CommonSubExpressionFields.initializeCommonSubExpressionFields(com.facebook.presto.sql.gen.CommonSubExpressionRewriter.CommonSubExpressionFields.initializeCommonSubExpressionFields) CommonSubExpressionFields.declareCommonSubExpressionFields(com.facebook.presto.sql.gen.CommonSubExpressionRewriter.CommonSubExpressionFields.declareCommonSubExpressionFields) CommonSubExpressionFields(com.facebook.presto.sql.gen.CommonSubExpressionRewriter.CommonSubExpressionFields) VariableReferenceExpression(com.facebook.presto.spi.relation.VariableReferenceExpression) MethodDefinition(com.facebook.presto.bytecode.MethodDefinition) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap) HashMap(java.util.HashMap) LambdaDefinitionExpression(com.facebook.presto.spi.relation.LambdaDefinitionExpression)

Example 32 with Variable

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

the class InCodeGenerator method generateExpression.

@Override
public BytecodeNode generateExpression(BytecodeGeneratorContext generatorContext, Type returnType, List<RowExpression> arguments, Optional<Variable> outputBlockVariable) {
    List<RowExpression> values = arguments.subList(1, arguments.size());
    // empty IN statements are not allowed by the standard, and not possible here
    // the implementation assumes this condition is always met
    checkArgument(values.size() > 0, "values must not be empty");
    Type type = arguments.get(0).getType();
    Class<?> javaType = type.getJavaType();
    SwitchGenerationCase switchGenerationCase = checkSwitchGenerationCase(type, values);
    FunctionHandle hashCodeHandle = generatorContext.getFunctionManager().resolveOperator(HASH_CODE, fromTypes(type));
    MethodHandle hashCodeFunction = generatorContext.getFunctionManager().getJavaScalarFunctionImplementation(hashCodeHandle).getMethodHandle();
    FunctionHandle isIndeterminateHandle = generatorContext.getFunctionManager().resolveOperator(INDETERMINATE, fromTypes(type));
    JavaScalarFunctionImplementation isIndeterminateFunction = generatorContext.getFunctionManager().getJavaScalarFunctionImplementation(isIndeterminateHandle);
    ImmutableListMultimap.Builder<Integer, BytecodeNode> hashBucketsBuilder = ImmutableListMultimap.builder();
    ImmutableList.Builder<BytecodeNode> defaultBucket = ImmutableList.builder();
    ImmutableSet.Builder<Object> constantValuesBuilder = ImmutableSet.builder();
    for (RowExpression testValue : values) {
        BytecodeNode testBytecode = generatorContext.generate(testValue, Optional.empty());
        if (isDeterminateConstant(testValue, isIndeterminateFunction.getMethodHandle())) {
            ConstantExpression constant = (ConstantExpression) testValue;
            Object object = constant.getValue();
            switch(switchGenerationCase) {
                case DIRECT_SWITCH:
                case SET_CONTAINS:
                    constantValuesBuilder.add(object);
                    break;
                case HASH_SWITCH:
                    try {
                        int hashCode = toIntExact(Long.hashCode((Long) hashCodeFunction.invoke(object)));
                        hashBucketsBuilder.put(hashCode, testBytecode);
                    } catch (Throwable throwable) {
                        throw new IllegalArgumentException("Error processing IN statement: error calculating hash code for " + object, throwable);
                    }
                    break;
                default:
                    throw new IllegalArgumentException("Not supported switch generation case: " + switchGenerationCase);
            }
        } else {
            defaultBucket.add(testBytecode);
        }
    }
    ImmutableListMultimap<Integer, BytecodeNode> hashBuckets = hashBucketsBuilder.build();
    ImmutableSet<Object> constantValues = constantValuesBuilder.build();
    LabelNode end = new LabelNode("end");
    LabelNode match = new LabelNode("match");
    LabelNode noMatch = new LabelNode("noMatch");
    LabelNode defaultLabel = new LabelNode("default");
    Scope scope = generatorContext.getScope();
    Variable value = scope.createTempVariable(javaType);
    BytecodeNode switchBlock;
    Variable expression = scope.createTempVariable(int.class);
    SwitchBuilder switchBuilder = new SwitchBuilder().expression(expression);
    switch(switchGenerationCase) {
        case DIRECT_SWITCH:
            // For these types, it's safe to not use presto HASH_CODE and EQUAL operator.
            for (Object constantValue : constantValues) {
                switchBuilder.addCase(toIntExact((Long) constantValue), jump(match));
            }
            switchBuilder.defaultCase(jump(defaultLabel));
            switchBlock = new BytecodeBlock().comment("lookupSwitch(<stackValue>))").append(new IfStatement().condition(invokeStatic(InCodeGenerator.class, "isInteger", boolean.class, value)).ifFalse(new BytecodeBlock().gotoLabel(defaultLabel))).append(expression.set(value.cast(int.class))).append(switchBuilder.build());
            break;
        case HASH_SWITCH:
            for (Map.Entry<Integer, Collection<BytecodeNode>> bucket : hashBuckets.asMap().entrySet()) {
                Collection<BytecodeNode> testValues = bucket.getValue();
                BytecodeBlock caseBlock = buildInCase(generatorContext, scope, type, match, defaultLabel, value, testValues, false, isIndeterminateFunction);
                switchBuilder.addCase(bucket.getKey(), caseBlock);
            }
            switchBuilder.defaultCase(jump(defaultLabel));
            Binding hashCodeBinding = generatorContext.getCallSiteBinder().bind(hashCodeFunction);
            switchBlock = new BytecodeBlock().comment("lookupSwitch(hashCode(<stackValue>))").getVariable(value).append(invoke(hashCodeBinding, HASH_CODE.name())).invokeStatic(Long.class, "hashCode", int.class, long.class).putVariable(expression).append(switchBuilder.build());
            break;
        case SET_CONTAINS:
            Set<?> constantValuesSet = toFastutilHashSet(constantValues, type, functionAndTypeManager);
            Binding constant = generatorContext.getCallSiteBinder().bind(constantValuesSet, constantValuesSet.getClass());
            switchBlock = new BytecodeBlock().comment("inListSet.contains(<stackValue>)").append(new IfStatement().condition(new BytecodeBlock().comment("value").getVariable(value).comment("set").append(loadConstant(constant)).invokeStatic(FastutilSetHelper.class, "in", boolean.class, javaType.isPrimitive() ? javaType : Object.class, constantValuesSet.getClass())).ifTrue(jump(match)));
            break;
        default:
            throw new IllegalArgumentException("Not supported switch generation case: " + switchGenerationCase);
    }
    BytecodeBlock defaultCaseBlock = buildInCase(generatorContext, scope, type, match, noMatch, value, defaultBucket.build(), true, isIndeterminateFunction).setDescription("default");
    BytecodeBlock block = new BytecodeBlock().comment("IN").append(generatorContext.generate(arguments.get(0), Optional.empty())).append(ifWasNullPopAndGoto(scope, end, boolean.class, javaType)).putVariable(value).append(switchBlock).visitLabel(defaultLabel).append(defaultCaseBlock);
    BytecodeBlock matchBlock = new BytecodeBlock().setDescription("match").visitLabel(match).append(generatorContext.wasNull().set(constantFalse())).push(true).gotoLabel(end);
    block.append(matchBlock);
    BytecodeBlock noMatchBlock = new BytecodeBlock().setDescription("noMatch").visitLabel(noMatch).push(false).gotoLabel(end);
    block.append(noMatchBlock);
    block.visitLabel(end);
    outputBlockVariable.ifPresent(output -> block.append(generateWrite(generatorContext, returnType, output)));
    return block;
}
Also used : LabelNode(com.facebook.presto.bytecode.instruction.LabelNode) JavaScalarFunctionImplementation(com.facebook.presto.spi.function.JavaScalarFunctionImplementation) Variable(com.facebook.presto.bytecode.Variable) ImmutableList(com.google.common.collect.ImmutableList) ConstantExpression(com.facebook.presto.spi.relation.ConstantExpression) IfStatement(com.facebook.presto.bytecode.control.IfStatement) ImmutableSet(com.google.common.collect.ImmutableSet) ImmutableListMultimap(com.google.common.collect.ImmutableListMultimap) BytecodeNode(com.facebook.presto.bytecode.BytecodeNode) FunctionHandle(com.facebook.presto.spi.function.FunctionHandle) Binding(com.facebook.presto.bytecode.Binding) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) RowExpression(com.facebook.presto.spi.relation.RowExpression) IntegerType(com.facebook.presto.common.type.IntegerType) Type(com.facebook.presto.common.type.Type) BigintType(com.facebook.presto.common.type.BigintType) DateType(com.facebook.presto.common.type.DateType) Scope(com.facebook.presto.bytecode.Scope) SwitchBuilder(com.facebook.presto.bytecode.control.SwitchStatement.SwitchBuilder) Collection(java.util.Collection) Map(java.util.Map) MethodHandle(java.lang.invoke.MethodHandle)

Example 33 with Variable

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

the class InCodeGenerator method buildInCase.

private static BytecodeBlock buildInCase(BytecodeGeneratorContext generatorContext, Scope scope, Type type, LabelNode matchLabel, LabelNode noMatchLabel, Variable value, Collection<BytecodeNode> testValues, boolean checkForNulls, JavaScalarFunctionImplementation isIndeterminateFunction) {
    // 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();
    if (checkForNulls) {
        caseBlock.putVariable(caseWasNull, false);
    }
    LabelNode elseLabel = new LabelNode("else");
    BytecodeBlock elseBlock = new BytecodeBlock().visitLabel(elseLabel);
    Variable wasNull = generatorContext.wasNull();
    if (checkForNulls) {
        // That is incorrect. Doing an explicit check for indeterminate is required to correctly return NULL.
        if (testValues.isEmpty()) {
            elseBlock.append(new BytecodeBlock().append(generatorContext.generateCall(INDETERMINATE.name(), isIndeterminateFunction, ImmutableList.of(value))).putVariable(wasNull));
        } else {
            elseBlock.append(wasNull.set(caseWasNull));
        }
    }
    elseBlock.gotoLabel(noMatchLabel);
    FunctionHandle equalsHandle = generatorContext.getFunctionManager().resolveOperator(EQUAL, fromTypes(type, type));
    JavaScalarFunctionImplementation equalsFunction = generatorContext.getFunctionManager().getJavaScalarFunctionImplementation(equalsHandle);
    BytecodeNode elseNode = elseBlock;
    for (BytecodeNode testNode : testValues) {
        LabelNode testLabel = new LabelNode("test");
        IfStatement test = new IfStatement();
        BytecodeNode equalsCall = generatorContext.generateCall(EQUAL.name(), equalsFunction, ImmutableList.of(value, testNode));
        test.condition().visitLabel(testLabel).append(equalsCall);
        if (checkForNulls) {
            IfStatement wasNullCheck = new IfStatement("if wasNull, set caseWasNull to true, clear wasNull, pop boolean, and goto next test value");
            wasNullCheck.condition(wasNull);
            wasNullCheck.ifTrue(new BytecodeBlock().append(caseWasNull.set(constantTrue())).append(wasNull.set(constantFalse())).pop(boolean.class).gotoLabel(elseLabel));
            test.condition().append(wasNullCheck);
        }
        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) JavaScalarFunctionImplementation(com.facebook.presto.spi.function.JavaScalarFunctionImplementation) 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) FunctionHandle(com.facebook.presto.spi.function.FunctionHandle)

Example 34 with Variable

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

the class PageFunctionCompiler method generateCommonSubExpressionMethods.

private List<MethodDefinition> generateCommonSubExpressionMethods(ClassDefinition classDefinition, RowExpressionCompiler compiler, Map<Integer, Map<RowExpression, VariableReferenceExpression>> commonSubExpressionsByLevel, Map<VariableReferenceExpression, CommonSubExpressionFields> commonSubExpressionFieldsMap) {
    ImmutableList.Builder<MethodDefinition> methods = ImmutableList.builder();
    Parameter properties = arg("properties", SqlFunctionProperties.class);
    Parameter page = arg("page", Page.class);
    Parameter position = arg("position", int.class);
    int startLevel = commonSubExpressionsByLevel.keySet().stream().reduce(Math::min).get();
    int maxLevel = commonSubExpressionsByLevel.keySet().stream().reduce(Math::max).get();
    for (int i = startLevel; i <= maxLevel; i++) {
        if (commonSubExpressionsByLevel.containsKey(i)) {
            for (Map.Entry<RowExpression, VariableReferenceExpression> entry : commonSubExpressionsByLevel.get(i).entrySet()) {
                RowExpression cse = entry.getKey();
                Class<?> type = Primitives.wrap(cse.getType().getJavaType());
                VariableReferenceExpression cseVariable = entry.getValue();
                CommonSubExpressionFields cseFields = commonSubExpressionFieldsMap.get(cseVariable);
                MethodDefinition method = classDefinition.declareMethod(a(PRIVATE), "get" + cseVariable.getName(), type(cseFields.getResultType()), ImmutableList.<Parameter>builder().add(properties).add(page).add(position).build());
                method.comment("cse: %s", cse);
                Scope scope = method.getScope();
                BytecodeBlock body = method.getBody();
                Variable thisVariable = method.getThis();
                declareBlockVariables(ImmutableList.of(cse), page, scope, body);
                scope.declareVariable("wasNull", body, constantFalse());
                IfStatement ifStatement = new IfStatement().condition(thisVariable.getField(cseFields.getEvaluatedField())).ifFalse(new BytecodeBlock().append(thisVariable).append(compiler.compile(cse, scope, Optional.empty())).append(boxPrimitiveIfNecessary(scope, type)).putField(cseFields.getResultField()).append(thisVariable.setField(cseFields.getEvaluatedField(), constantBoolean(true))));
                body.append(ifStatement).append(thisVariable).getField(cseFields.getResultField()).retObject();
                methods.add(method);
            }
        }
    }
    return methods.build();
}
Also used : Variable(com.facebook.presto.bytecode.Variable) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) ImmutableList(com.google.common.collect.ImmutableList) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) RowExpression(com.facebook.presto.spi.relation.RowExpression) IfStatement(com.facebook.presto.bytecode.control.IfStatement) CommonSubExpressionFields.initializeCommonSubExpressionFields(com.facebook.presto.sql.gen.CommonSubExpressionRewriter.CommonSubExpressionFields.initializeCommonSubExpressionFields) CommonSubExpressionFields.declareCommonSubExpressionFields(com.facebook.presto.sql.gen.CommonSubExpressionRewriter.CommonSubExpressionFields.declareCommonSubExpressionFields) CommonSubExpressionFields(com.facebook.presto.sql.gen.CommonSubExpressionRewriter.CommonSubExpressionFields) Scope(com.facebook.presto.bytecode.Scope) MethodDefinition(com.facebook.presto.bytecode.MethodDefinition) VariableReferenceExpression(com.facebook.presto.spi.relation.VariableReferenceExpression) Parameter(com.facebook.presto.bytecode.Parameter) Map(java.util.Map) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap) ImmutableMap(com.google.common.collect.ImmutableMap) Collections.emptyMap(java.util.Collections.emptyMap)

Example 35 with Variable

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

the class PageFunctionCompiler method definePageProjectWorkClass.

private ClassDefinition definePageProjectWorkClass(SqlFunctionProperties sqlFunctionProperties, Map<SqlFunctionId, SqlInvokedFunction> sessionFunctions, List<RowExpression> projections, CallSiteBinder callSiteBinder, boolean isOptimizeCommonSubExpression, Optional<String> classNameSuffix) {
    ClassDefinition classDefinition = new ClassDefinition(a(PUBLIC, FINAL), generateProjectionWorkClassName(classNameSuffix), type(Object.class), type(Work.class));
    FieldDefinition blockBuilderFields = classDefinition.declareField(a(PRIVATE), "blockBuilders", type(List.class, BlockBuilder.class));
    FieldDefinition propertiesField = classDefinition.declareField(a(PRIVATE), "properties", SqlFunctionProperties.class);
    FieldDefinition pageField = classDefinition.declareField(a(PRIVATE), "page", Page.class);
    FieldDefinition selectedPositionsField = classDefinition.declareField(a(PRIVATE), "selectedPositions", SelectedPositions.class);
    FieldDefinition nextIndexOrPositionField = classDefinition.declareField(a(PRIVATE), "nextIndexOrPosition", int.class);
    FieldDefinition resultField = classDefinition.declareField(a(PRIVATE), "result", List.class);
    CachedInstanceBinder cachedInstanceBinder = new CachedInstanceBinder(classDefinition, callSiteBinder);
    // process
    generateProcessMethod(classDefinition, blockBuilderFields, projections.size(), propertiesField, pageField, selectedPositionsField, nextIndexOrPositionField, resultField);
    // getResult
    MethodDefinition method = classDefinition.declareMethod(a(PUBLIC), "getResult", type(Object.class), ImmutableList.of());
    method.getBody().append(method.getThis().getField(resultField)).ret(Object.class);
    Map<LambdaDefinitionExpression, CompiledLambda> compiledLambdaMap = generateMethodsForLambda(classDefinition, callSiteBinder, cachedInstanceBinder, projections, metadata, sqlFunctionProperties, sessionFunctions, "");
    // cse
    Map<VariableReferenceExpression, CommonSubExpressionFields> cseFields = ImmutableMap.of();
    RowExpressionCompiler compiler = new RowExpressionCompiler(classDefinition, callSiteBinder, cachedInstanceBinder, new FieldAndVariableReferenceCompiler(callSiteBinder, cseFields), metadata, sqlFunctionProperties, sessionFunctions, compiledLambdaMap);
    if (isOptimizeCommonSubExpression) {
        Map<Integer, Map<RowExpression, VariableReferenceExpression>> commonSubExpressionsByLevel = collectCSEByLevel(projections);
        if (!commonSubExpressionsByLevel.isEmpty()) {
            cseFields = declareCommonSubExpressionFields(classDefinition, commonSubExpressionsByLevel);
            compiler = new RowExpressionCompiler(classDefinition, callSiteBinder, cachedInstanceBinder, new FieldAndVariableReferenceCompiler(callSiteBinder, cseFields), metadata, sqlFunctionProperties, sessionFunctions, compiledLambdaMap);
            generateCommonSubExpressionMethods(classDefinition, compiler, commonSubExpressionsByLevel, cseFields);
            Map<RowExpression, VariableReferenceExpression> commonSubExpressions = commonSubExpressionsByLevel.values().stream().flatMap(m -> m.entrySet().stream()).collect(toImmutableMap(Map.Entry::getKey, Map.Entry::getValue));
            projections = projections.stream().map(projection -> rewriteExpressionWithCSE(projection, commonSubExpressions)).collect(toImmutableList());
            if (log.isDebugEnabled()) {
                log.debug("Extracted %d common sub-expressions", commonSubExpressions.size());
                commonSubExpressions.entrySet().forEach(entry -> log.debug("\t%s = %s", entry.getValue(), entry.getKey()));
                log.debug("Rewrote %d projections: %s", projections.size(), Joiner.on(", ").join(projections));
            }
        }
    }
    // evaluate
    generateEvaluateMethod(classDefinition, compiler, projections, blockBuilderFields, cseFields);
    // constructor
    Parameter blockBuilders = arg("blockBuilders", type(List.class, BlockBuilder.class));
    Parameter properties = arg("properties", SqlFunctionProperties.class);
    Parameter page = arg("page", Page.class);
    Parameter selectedPositions = arg("selectedPositions", SelectedPositions.class);
    MethodDefinition constructorDefinition = classDefinition.declareConstructor(a(PUBLIC), blockBuilders, properties, page, selectedPositions);
    BytecodeBlock body = constructorDefinition.getBody();
    Variable thisVariable = constructorDefinition.getThis();
    body.comment("super();").append(thisVariable).invokeConstructor(Object.class).append(thisVariable.setField(blockBuilderFields, invokeStatic(ImmutableList.class, "copyOf", ImmutableList.class, blockBuilders.cast(Collection.class)))).append(thisVariable.setField(propertiesField, properties)).append(thisVariable.setField(pageField, page)).append(thisVariable.setField(selectedPositionsField, selectedPositions)).append(thisVariable.setField(nextIndexOrPositionField, selectedPositions.invoke("getOffset", int.class))).append(thisVariable.setField(resultField, constantNull(Block.class)));
    initializeCommonSubExpressionFields(cseFields.values(), thisVariable, body);
    cachedInstanceBinder.generateInitializations(thisVariable, body);
    body.ret();
    return classDefinition;
}
Also used : Page(com.facebook.presto.common.Page) LoadingCache(com.google.common.cache.LoadingCache) PageFieldsToInputParametersRewriter(com.facebook.presto.operator.project.PageFieldsToInputParametersRewriter) PageFilter(com.facebook.presto.operator.project.PageFilter) Expressions.subExpressions(com.facebook.presto.sql.relational.Expressions.subExpressions) SqlInvokedFunction(com.facebook.presto.spi.function.SqlInvokedFunction) MethodDefinition(com.facebook.presto.bytecode.MethodDefinition) InputPageProjection(com.facebook.presto.operator.project.InputPageProjection) CallSiteBinder(com.facebook.presto.bytecode.CallSiteBinder) ForLoop(com.facebook.presto.bytecode.control.ForLoop) BytecodeUtils.boxPrimitiveIfNecessary(com.facebook.presto.sql.gen.BytecodeUtils.boxPrimitiveIfNecessary) CommonSubExpressionRewriter.collectCSEByLevel(com.facebook.presto.sql.gen.CommonSubExpressionRewriter.collectCSEByLevel) Map(java.util.Map) CompilerUtils.makeClassName(com.facebook.presto.util.CompilerUtils.makeClassName) IfStatement(com.facebook.presto.bytecode.control.IfStatement) BytecodeExpressions.add(com.facebook.presto.bytecode.expression.BytecodeExpressions.add) Variable(com.facebook.presto.bytecode.Variable) CommonSubExpressionRewriter.rewriteExpressionWithCSE(com.facebook.presto.sql.gen.CommonSubExpressionRewriter.rewriteExpressionWithCSE) BlockBuilder(com.facebook.presto.common.block.BlockBuilder) Parameter(com.facebook.presto.bytecode.Parameter) SqlFunctionProperties(com.facebook.presto.common.function.SqlFunctionProperties) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) PageProjectionWithOutputs(com.facebook.presto.operator.project.PageProjectionWithOutputs) BytecodeExpressions.constantBoolean(com.facebook.presto.bytecode.expression.BytecodeExpressions.constantBoolean) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap) FINAL(com.facebook.presto.bytecode.Access.FINAL) Scope(com.facebook.presto.bytecode.Scope) BytecodeExpressions.invokeStatic(com.facebook.presto.bytecode.expression.BytecodeExpressions.invokeStatic) Joiner(com.google.common.base.Joiner) MoreObjects.toStringHelper(com.google.common.base.MoreObjects.toStringHelper) PageProjection(com.facebook.presto.operator.project.PageProjection) ConstantExpression(com.facebook.presto.spi.relation.ConstantExpression) BytecodeExpressions.constantFalse(com.facebook.presto.bytecode.expression.BytecodeExpressions.constantFalse) Supplier(java.util.function.Supplier) CommonSubExpressionFields.initializeCommonSubExpressionFields(com.facebook.presto.sql.gen.CommonSubExpressionRewriter.CommonSubExpressionFields.initializeCommonSubExpressionFields) TreeSet(java.util.TreeSet) Managed(org.weakref.jmx.Managed) LambdaBytecodeGenerator.generateMethodsForLambda(com.facebook.presto.sql.gen.LambdaBytecodeGenerator.generateMethodsForLambda) GeneratedPageProjection(com.facebook.presto.operator.project.GeneratedPageProjection) CommonSubExpressionFields.declareCommonSubExpressionFields(com.facebook.presto.sql.gen.CommonSubExpressionRewriter.CommonSubExpressionFields.declareCommonSubExpressionFields) BytecodeExpressions.constantNull(com.facebook.presto.bytecode.expression.BytecodeExpressions.constantNull) Nullable(javax.annotation.Nullable) Throwables.throwIfInstanceOf(com.google.common.base.Throwables.throwIfInstanceOf) SqlFunctionId(com.facebook.presto.spi.function.SqlFunctionId) Work(com.facebook.presto.operator.Work) CommonSubExpressionFields(com.facebook.presto.sql.gen.CommonSubExpressionRewriter.CommonSubExpressionFields) ParameterizedType(com.facebook.presto.bytecode.ParameterizedType) Metadata(com.facebook.presto.metadata.Metadata) BytecodeExpressions.newArray(com.facebook.presto.bytecode.expression.BytecodeExpressions.newArray) RowExpressionVisitor(com.facebook.presto.spi.relation.RowExpressionVisitor) VariableReferenceExpression(com.facebook.presto.spi.relation.VariableReferenceExpression) BytecodeUtils.invoke(com.facebook.presto.sql.gen.BytecodeUtils.invoke) Access.a(com.facebook.presto.bytecode.Access.a) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) CommonSubExpressionRewriter.getExpressionsPartitionedByCSE(com.facebook.presto.sql.gen.CommonSubExpressionRewriter.getExpressionsPartitionedByCSE) ParameterizedType.type(com.facebook.presto.bytecode.ParameterizedType.type) CallExpression(com.facebook.presto.spi.relation.CallExpression) SpecialFormExpression(com.facebook.presto.spi.relation.SpecialFormExpression) ImmutableMap(com.google.common.collect.ImmutableMap) BytecodeExpressions.lessThan(com.facebook.presto.bytecode.expression.BytecodeExpressions.lessThan) Collection(java.util.Collection) SelectedPositions(com.facebook.presto.operator.project.SelectedPositions) LambdaDefinitionExpression(com.facebook.presto.spi.relation.LambdaDefinitionExpression) CacheLoader(com.google.common.cache.CacheLoader) Objects(java.util.Objects) CompiledLambda(com.facebook.presto.sql.gen.LambdaBytecodeGenerator.CompiledLambda) ClassDefinition(com.facebook.presto.bytecode.ClassDefinition) List(java.util.List) ConstantPageProjection(com.facebook.presto.operator.project.ConstantPageProjection) Optional(java.util.Optional) CacheBuilder(com.google.common.cache.CacheBuilder) InputReferenceExpression(com.facebook.presto.spi.relation.InputReferenceExpression) Parameter.arg(com.facebook.presto.bytecode.Parameter.arg) IntStream(java.util.stream.IntStream) BytecodeExpressions.and(com.facebook.presto.bytecode.expression.BytecodeExpressions.and) DeterminismEvaluator(com.facebook.presto.spi.relation.DeterminismEvaluator) Nested(org.weakref.jmx.Nested) Logger(com.facebook.airlift.log.Logger) InputChannels(com.facebook.presto.operator.project.InputChannels) BytecodeExpressions.constantInt(com.facebook.presto.bytecode.expression.BytecodeExpressions.constantInt) PRIVATE(com.facebook.presto.bytecode.Access.PRIVATE) RowExpressionDeterminismEvaluator(com.facebook.presto.sql.relational.RowExpressionDeterminismEvaluator) PrestoException(com.facebook.presto.spi.PrestoException) BytecodeExpressions.not(com.facebook.presto.bytecode.expression.BytecodeExpressions.not) Inject(javax.inject.Inject) ImmutableList(com.google.common.collect.ImmutableList) PageFieldsToInputParametersRewriter.rewritePageFieldsToInputParameters(com.facebook.presto.operator.project.PageFieldsToInputParametersRewriter.rewritePageFieldsToInputParameters) Verify.verify(com.google.common.base.Verify.verify) UncheckedExecutionException(com.google.common.util.concurrent.UncheckedExecutionException) Objects.requireNonNull(java.util.Objects.requireNonNull) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) RowExpression(com.facebook.presto.spi.relation.RowExpression) PUBLIC(com.facebook.presto.bytecode.Access.PUBLIC) Collections.emptyMap(java.util.Collections.emptyMap) CompilerUtils.defineClass(com.facebook.presto.util.CompilerUtils.defineClass) Reflection.constructorMethodHandle(com.facebook.presto.util.Reflection.constructorMethodHandle) Primitives(com.google.common.primitives.Primitives) CompilerConfig(com.facebook.presto.sql.planner.CompilerConfig) BytecodeNode(com.facebook.presto.bytecode.BytecodeNode) FieldDefinition(com.facebook.presto.bytecode.FieldDefinition) BytecodeUtils.unboxPrimitiveIfNecessary(com.facebook.presto.sql.gen.BytecodeUtils.unboxPrimitiveIfNecessary) VisibleForTesting(com.google.common.annotations.VisibleForTesting) Block(com.facebook.presto.common.block.Block) COMPILER_ERROR(com.facebook.presto.spi.StandardErrorCode.COMPILER_ERROR) Variable(com.facebook.presto.bytecode.Variable) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) ImmutableList(com.google.common.collect.ImmutableList) FieldDefinition(com.facebook.presto.bytecode.FieldDefinition) ClassDefinition(com.facebook.presto.bytecode.ClassDefinition) CompiledLambda(com.facebook.presto.sql.gen.LambdaBytecodeGenerator.CompiledLambda) CommonSubExpressionFields.initializeCommonSubExpressionFields(com.facebook.presto.sql.gen.CommonSubExpressionRewriter.CommonSubExpressionFields.initializeCommonSubExpressionFields) CommonSubExpressionFields.declareCommonSubExpressionFields(com.facebook.presto.sql.gen.CommonSubExpressionRewriter.CommonSubExpressionFields.declareCommonSubExpressionFields) CommonSubExpressionFields(com.facebook.presto.sql.gen.CommonSubExpressionRewriter.CommonSubExpressionFields) MethodDefinition(com.facebook.presto.bytecode.MethodDefinition) Work(com.facebook.presto.operator.Work) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) List(java.util.List) ImmutableList(com.google.common.collect.ImmutableList) BlockBuilder(com.facebook.presto.common.block.BlockBuilder) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) RowExpression(com.facebook.presto.spi.relation.RowExpression) VariableReferenceExpression(com.facebook.presto.spi.relation.VariableReferenceExpression) Parameter(com.facebook.presto.bytecode.Parameter) Map(java.util.Map) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap) ImmutableMap(com.google.common.collect.ImmutableMap) Collections.emptyMap(java.util.Collections.emptyMap) LambdaDefinitionExpression(com.facebook.presto.spi.relation.LambdaDefinitionExpression)

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