Search in sources :

Example 6 with LabelNode

use of com.facebook.presto.bytecode.instruction.LabelNode in project presto by prestodb.

the class CursorProcessorCompiler method generateFilterMethod.

private void generateFilterMethod(ClassDefinition classDefinition, CallSiteBinder callSiteBinder, CachedInstanceBinder cachedInstanceBinder, RowExpression filter) {
    PreGeneratedExpressions preGeneratedExpressions = generateMethodsForLambdaAndTry(classDefinition, callSiteBinder, cachedInstanceBinder, filter, "filter");
    Parameter session = arg("session", ConnectorSession.class);
    Parameter cursor = arg("cursor", RecordCursor.class);
    MethodDefinition method = classDefinition.declareMethod(a(PUBLIC), "filter", type(boolean.class), session, cursor);
    method.comment("Filter: %s", filter);
    Scope scope = method.getScope();
    Variable wasNullVariable = scope.declareVariable(type(boolean.class), "wasNull");
    BytecodeExpressionVisitor visitor = new BytecodeExpressionVisitor(callSiteBinder, cachedInstanceBinder, fieldReferenceCompiler(cursor), metadata.getFunctionRegistry(), preGeneratedExpressions);
    LabelNode end = new LabelNode("end");
    method.getBody().comment("boolean wasNull = false;").putVariable(wasNullVariable, false).comment("evaluate filter: " + filter).append(filter.accept(visitor, scope)).comment("if (wasNull) return false;").getVariable(wasNullVariable).ifFalseGoto(end).pop(boolean.class).push(false).visitLabel(end).retBoolean();
}
Also used : LabelNode(com.facebook.presto.bytecode.instruction.LabelNode) Variable(com.facebook.presto.bytecode.Variable) Scope(com.facebook.presto.bytecode.Scope) MethodDefinition(com.facebook.presto.bytecode.MethodDefinition) Parameter(com.facebook.presto.bytecode.Parameter)

Example 7 with LabelNode

use of com.facebook.presto.bytecode.instruction.LabelNode in project presto by prestodb.

the class CursorProcessorCompiler method generateProcessMethod.

private static void generateProcessMethod(ClassDefinition classDefinition, int projections) {
    Parameter session = arg("session", ConnectorSession.class);
    Parameter cursor = arg("cursor", RecordCursor.class);
    Parameter count = arg("count", int.class);
    Parameter pageBuilder = arg("pageBuilder", PageBuilder.class);
    MethodDefinition method = classDefinition.declareMethod(a(PUBLIC), "process", type(int.class), session, cursor, count, pageBuilder);
    Scope scope = method.getScope();
    Variable completedPositionsVariable = scope.declareVariable(int.class, "completedPositions");
    method.getBody().comment("int completedPositions = 0;").putVariable(completedPositionsVariable, 0);
    //
    // for loop loop body
    //
    LabelNode done = new LabelNode("done");
    ForLoop forLoop = new ForLoop().initialize(NOP).condition(new BytecodeBlock().comment("completedPositions < count").getVariable(completedPositionsVariable).getVariable(count).invokeStatic(CompilerOperations.class, "lessThan", boolean.class, int.class, int.class)).update(new BytecodeBlock().comment("completedPositions++").incrementVariable(completedPositionsVariable, (byte) 1));
    BytecodeBlock forLoopBody = new BytecodeBlock().comment("if (pageBuilder.isFull()) break;").append(new BytecodeBlock().getVariable(pageBuilder).invokeVirtual(PageBuilder.class, "isFull", boolean.class).ifTrueGoto(done)).comment("if (!cursor.advanceNextPosition()) break;").append(new BytecodeBlock().getVariable(cursor).invokeInterface(RecordCursor.class, "advanceNextPosition", boolean.class).ifFalseGoto(done));
    forLoop.body(forLoopBody);
    // if (filter(cursor))
    IfStatement ifStatement = new IfStatement();
    ifStatement.condition().append(method.getThis()).getVariable(session).getVariable(cursor).invokeVirtual(classDefinition.getType(), "filter", type(boolean.class), type(ConnectorSession.class), type(RecordCursor.class));
    // pageBuilder.declarePosition();
    ifStatement.ifTrue().getVariable(pageBuilder).invokeVirtual(PageBuilder.class, "declarePosition", void.class);
    // this.project_43(session, cursor, pageBuilder.getBlockBuilder(42)));
    for (int projectionIndex = 0; projectionIndex < projections; projectionIndex++) {
        ifStatement.ifTrue().append(method.getThis()).getVariable(session).getVariable(cursor);
        // pageBuilder.getBlockBuilder(0)
        ifStatement.ifTrue().getVariable(pageBuilder).push(projectionIndex).invokeVirtual(PageBuilder.class, "getBlockBuilder", BlockBuilder.class, int.class);
        // project(block..., blockBuilder)gen
        ifStatement.ifTrue().invokeVirtual(classDefinition.getType(), "project_" + projectionIndex, type(void.class), type(ConnectorSession.class), type(RecordCursor.class), type(BlockBuilder.class));
    }
    forLoopBody.append(ifStatement);
    method.getBody().append(forLoop).visitLabel(done).comment("return completedPositions;").getVariable(completedPositionsVariable).retInt();
}
Also used : LabelNode(com.facebook.presto.bytecode.instruction.LabelNode) IfStatement(com.facebook.presto.bytecode.control.IfStatement) Variable(com.facebook.presto.bytecode.Variable) RecordCursor(com.facebook.presto.spi.RecordCursor) Scope(com.facebook.presto.bytecode.Scope) ForLoop(com.facebook.presto.bytecode.control.ForLoop) MethodDefinition(com.facebook.presto.bytecode.MethodDefinition) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) Parameter(com.facebook.presto.bytecode.Parameter) ConnectorSession(com.facebook.presto.spi.ConnectorSession) BlockBuilder(com.facebook.presto.spi.block.BlockBuilder)

Example 8 with LabelNode

use of com.facebook.presto.bytecode.instruction.LabelNode in project presto by prestodb.

the class DereferenceCodeGenerator method generateExpression.

@Override
public BytecodeNode generateExpression(Signature signature, BytecodeGeneratorContext generator, Type returnType, List<RowExpression> arguments) {
    checkArgument(arguments.size() == 2);
    CallSiteBinder callSiteBinder = generator.getCallSiteBinder();
    BytecodeBlock block = new BytecodeBlock().comment("DEREFERENCE").setDescription("DEREFERENCE");
    Variable wasNull = generator.wasNull();
    Variable rowBlock = generator.getScope().createTempVariable(Block.class);
    int index = (int) ((ConstantExpression) arguments.get(1)).getValue();
    // clear the wasNull flag before evaluating the row value
    block.putVariable(wasNull, false);
    block.append(generator.generate(arguments.get(0))).putVariable(rowBlock);
    IfStatement ifRowBlockIsNull = new IfStatement("if row block is null...").condition(wasNull);
    Class<?> javaType = returnType.getJavaType();
    LabelNode end = new LabelNode("end");
    ifRowBlockIsNull.ifTrue().comment("if row block is null, push null to the stack and goto 'end' label (return)").putVariable(wasNull, true).pushJavaDefault(javaType).gotoLabel(end);
    block.append(ifRowBlockIsNull);
    IfStatement ifFieldIsNull = new IfStatement("if row field is null...");
    ifFieldIsNull.condition().comment("call rowBlock.isNull(index)").append(rowBlock).push(index).invokeInterface(Block.class, "isNull", boolean.class, int.class);
    ifFieldIsNull.ifTrue().comment("if the field is null, push null to stack").putVariable(wasNull, true).pushJavaDefault(javaType);
    BytecodeExpression value = constantType(callSiteBinder, returnType).getValue(rowBlock, constantInt(index));
    ifFieldIsNull.ifFalse().comment("otherwise call type.getTYPE(rowBlock, index)").append(value).putVariable(wasNull, false);
    block.append(ifFieldIsNull).visitLabel(end);
    return block;
}
Also used : LabelNode(com.facebook.presto.bytecode.instruction.LabelNode) IfStatement(com.facebook.presto.bytecode.control.IfStatement) Variable(com.facebook.presto.bytecode.Variable) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) BytecodeExpression(com.facebook.presto.bytecode.expression.BytecodeExpression)

Example 9 with LabelNode

use of com.facebook.presto.bytecode.instruction.LabelNode in project presto by prestodb.

the class InCodeGenerator method generateExpression.

@Override
public BytecodeNode generateExpression(Signature signature, BytecodeGeneratorContext generatorContext, Type returnType, List<RowExpression> arguments) {
    BytecodeNode value = generatorContext.generate(arguments.get(0));
    List<RowExpression> values = arguments.subList(1, arguments.size());
    ImmutableList.Builder<BytecodeNode> valuesBytecode = ImmutableList.builder();
    for (int i = 1; i < arguments.size(); i++) {
        BytecodeNode testNode = generatorContext.generate(arguments.get(i));
        valuesBytecode.add(testNode);
    }
    Type type = arguments.get(0).getType();
    Class<?> javaType = type.getJavaType();
    SwitchGenerationCase switchGenerationCase = checkSwitchGenerationCase(type, values);
    Signature hashCodeSignature = internalOperator(HASH_CODE, BIGINT, ImmutableList.of(type));
    MethodHandle hashCodeFunction = generatorContext.getRegistry().getScalarFunctionImplementation(hashCodeSignature).getMethodHandle();
    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);
        if (testValue instanceof ConstantExpression && ((ConstantExpression) testValue).getValue() != null) {
            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();
    BytecodeNode switchBlock;
    BytecodeBlock switchCaseBlocks = new BytecodeBlock();
    LookupSwitch.LookupSwitchBuilder switchBuilder = lookupSwitchBuilder();
    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), match);
            }
            switchBuilder.defaultCase(defaultLabel);
            switchBlock = new BytecodeBlock().comment("lookupSwitch(<stackValue>))").dup(javaType).append(new IfStatement().condition(new BytecodeBlock().dup(javaType).invokeStatic(InCodeGenerator.class, "isInteger", boolean.class, long.class)).ifFalse(new BytecodeBlock().pop(javaType).gotoLabel(defaultLabel))).longToInt().append(switchBuilder.build());
            break;
        case HASH_SWITCH:
            for (Map.Entry<Integer, Collection<BytecodeNode>> bucket : hashBuckets.asMap().entrySet()) {
                LabelNode label = new LabelNode("inHash" + bucket.getKey());
                switchBuilder.addCase(bucket.getKey(), label);
                Collection<BytecodeNode> testValues = bucket.getValue();
                BytecodeBlock caseBlock = buildInCase(generatorContext, scope, type, label, match, defaultLabel, testValues, false);
                switchCaseBlocks.append(caseBlock.setDescription("case " + bucket.getKey()));
            }
            switchBuilder.defaultCase(defaultLabel);
            Binding hashCodeBinding = generatorContext.getCallSiteBinder().bind(hashCodeFunction);
            switchBlock = new BytecodeBlock().comment("lookupSwitch(hashCode(<stackValue>))").dup(javaType).append(invoke(hashCodeBinding, hashCodeSignature)).invokeStatic(Long.class, "hashCode", int.class, long.class).append(switchBuilder.build()).append(switchCaseBlocks);
            break;
        case SET_CONTAINS:
            Set<?> constantValuesSet = toFastutilHashSet(constantValues, type, registry);
            Binding constant = generatorContext.getCallSiteBinder().bind(constantValuesSet, constantValuesSet.getClass());
            switchBlock = new BytecodeBlock().comment("inListSet.contains(<stackValue>)").append(new IfStatement().condition(new BytecodeBlock().comment("value").dup(javaType).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, defaultLabel, match, noMatch, defaultBucket.build(), true).setDescription("default");
    BytecodeBlock block = new BytecodeBlock().comment("IN").append(value).append(ifWasNullPopAndGoto(scope, end, boolean.class, javaType)).append(switchBlock).append(defaultCaseBlock);
    BytecodeBlock matchBlock = new BytecodeBlock().setDescription("match").visitLabel(match).pop(javaType).append(generatorContext.wasNull().set(constantFalse())).push(true).gotoLabel(end);
    block.append(matchBlock);
    BytecodeBlock noMatchBlock = new BytecodeBlock().setDescription("noMatch").visitLabel(noMatch).pop(javaType).push(false).gotoLabel(end);
    block.append(noMatchBlock);
    block.visitLabel(end);
    return block;
}
Also used : LabelNode(com.facebook.presto.bytecode.instruction.LabelNode) ImmutableList(com.google.common.collect.ImmutableList) ConstantExpression(com.facebook.presto.sql.relational.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) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) RowExpression(com.facebook.presto.sql.relational.RowExpression) IntegerType(com.facebook.presto.spi.type.IntegerType) DateType(com.facebook.presto.spi.type.DateType) Type(com.facebook.presto.spi.type.Type) BigintType(com.facebook.presto.spi.type.BigintType) LookupSwitch(com.facebook.presto.bytecode.control.LookupSwitch) Scope(com.facebook.presto.bytecode.Scope) Signature(com.facebook.presto.metadata.Signature) Collection(java.util.Collection) Map(java.util.Map) MethodHandle(java.lang.invoke.MethodHandle)

Example 10 with LabelNode

use of com.facebook.presto.bytecode.instruction.LabelNode in project presto by prestodb.

the class JoinCompiler method generatePositionEqualsPositionMethod.

private static void generatePositionEqualsPositionMethod(ClassDefinition classDefinition, CallSiteBinder callSiteBinder, List<Type> joinChannelTypes, List<FieldDefinition> joinChannelFields, boolean ignoreNulls) {
    Parameter leftBlockIndex = arg("leftBlockIndex", int.class);
    Parameter leftBlockPosition = arg("leftBlockPosition", int.class);
    Parameter rightBlockIndex = arg("rightBlockIndex", int.class);
    Parameter rightBlockPosition = arg("rightBlockPosition", int.class);
    MethodDefinition positionEqualsPositionMethod = classDefinition.declareMethod(a(PUBLIC), ignoreNulls ? "positionEqualsPositionIgnoreNulls" : "positionEqualsPosition", type(boolean.class), leftBlockIndex, leftBlockPosition, rightBlockIndex, rightBlockPosition);
    Variable thisVariable = positionEqualsPositionMethod.getThis();
    for (int index = 0; index < joinChannelTypes.size(); index++) {
        BytecodeExpression type = constantType(callSiteBinder, joinChannelTypes.get(index));
        BytecodeExpression leftBlock = thisVariable.getField(joinChannelFields.get(index)).invoke("get", Object.class, leftBlockIndex).cast(Block.class);
        BytecodeExpression rightBlock = thisVariable.getField(joinChannelFields.get(index)).invoke("get", Object.class, rightBlockIndex).cast(Block.class);
        BytecodeNode equalityCondition;
        if (ignoreNulls) {
            equalityCondition = typeEqualsIgnoreNulls(type, leftBlock, leftBlockPosition, rightBlock, rightBlockPosition);
        } else {
            equalityCondition = typeEquals(type, leftBlock, leftBlockPosition, rightBlock, rightBlockPosition);
        }
        LabelNode checkNextField = new LabelNode("checkNextField");
        positionEqualsPositionMethod.getBody().append(equalityCondition).ifTrueGoto(checkNextField).push(false).retBoolean().visitLabel(checkNextField);
    }
    positionEqualsPositionMethod.getBody().push(true).retInt();
}
Also used : LabelNode(com.facebook.presto.bytecode.instruction.LabelNode) Variable(com.facebook.presto.bytecode.Variable) MethodDefinition(com.facebook.presto.bytecode.MethodDefinition) Parameter(com.facebook.presto.bytecode.Parameter) BytecodeNode(com.facebook.presto.bytecode.BytecodeNode) BytecodeExpression(com.facebook.presto.bytecode.expression.BytecodeExpression)

Aggregations

LabelNode (com.facebook.presto.bytecode.instruction.LabelNode)24 BytecodeBlock (com.facebook.presto.bytecode.BytecodeBlock)18 Variable (com.facebook.presto.bytecode.Variable)14 MethodDefinition (com.facebook.presto.bytecode.MethodDefinition)9 IfStatement (com.facebook.presto.bytecode.control.IfStatement)9 BytecodeNode (com.facebook.presto.bytecode.BytecodeNode)8 Parameter (com.facebook.presto.bytecode.Parameter)7 Scope (com.facebook.presto.bytecode.Scope)7 BytecodeExpression (com.facebook.presto.bytecode.expression.BytecodeExpression)5 RowExpression (com.facebook.presto.sql.relational.RowExpression)4 Signature (com.facebook.presto.metadata.Signature)3 Type (com.facebook.presto.spi.type.Type)3 ForLoop (com.facebook.presto.bytecode.control.ForLoop)2 ScalarFunctionImplementation (com.facebook.presto.operator.scalar.ScalarFunctionImplementation)2 ConnectorSession (com.facebook.presto.spi.ConnectorSession)2 ImmutableList (com.google.common.collect.ImmutableList)2 FieldDefinition (com.facebook.presto.bytecode.FieldDefinition)1 LookupSwitch (com.facebook.presto.bytecode.control.LookupSwitch)1 JumpInstruction (com.facebook.presto.bytecode.instruction.JumpInstruction)1 RecordCursor (com.facebook.presto.spi.RecordCursor)1