Search in sources :

Example 21 with Scope

use of io.airlift.bytecode.Scope in project trino by trinodb.

the class CursorProcessorCompiler method fieldReferenceCompiler.

private static RowExpressionVisitor<BytecodeNode, Scope> fieldReferenceCompiler(Variable cursorVariable) {
    return new RowExpressionVisitor<>() {

        @Override
        public BytecodeNode visitInputReference(InputReferenceExpression node, Scope scope) {
            int field = node.getField();
            Type type = node.getType();
            Variable wasNullVariable = scope.getVariable("wasNull");
            Class<?> javaType = type.getJavaType();
            IfStatement ifStatement = new IfStatement();
            ifStatement.condition().setDescription(format("cursor.get%s(%d)", type, field)).getVariable(cursorVariable).push(field).invokeInterface(RecordCursor.class, "isNull", boolean.class, int.class);
            ifStatement.ifTrue().putVariable(wasNullVariable, true).pushJavaDefault(javaType);
            ifStatement.ifFalse().getVariable(cursorVariable).push(field);
            if (javaType == boolean.class) {
                ifStatement.ifFalse().invokeInterface(RecordCursor.class, "getBoolean", boolean.class, int.class);
            } else if (javaType == long.class) {
                ifStatement.ifFalse().invokeInterface(RecordCursor.class, "getLong", long.class, int.class);
            } else if (javaType == double.class) {
                ifStatement.ifFalse().invokeInterface(RecordCursor.class, "getDouble", double.class, int.class);
            } else if (javaType == Slice.class) {
                ifStatement.ifFalse().invokeInterface(RecordCursor.class, "getSlice", Slice.class, int.class);
            } else {
                ifStatement.ifFalse().invokeInterface(RecordCursor.class, "getObject", Object.class, int.class).checkCast(javaType);
            }
            return ifStatement;
        }

        @Override
        public BytecodeNode visitCall(CallExpression call, Scope scope) {
            throw new UnsupportedOperationException("not yet implemented");
        }

        @Override
        public BytecodeNode visitSpecialForm(SpecialForm specialForm, Scope context) {
            throw new UnsupportedOperationException("not yet implemented");
        }

        @Override
        public BytecodeNode visitConstant(ConstantExpression literal, Scope scope) {
            throw new UnsupportedOperationException("not yet implemented");
        }

        @Override
        public BytecodeNode visitLambda(LambdaDefinitionExpression lambda, Scope context) {
            throw new UnsupportedOperationException();
        }

        @Override
        public BytecodeNode visitVariableReference(VariableReferenceExpression reference, Scope context) {
            throw new UnsupportedOperationException();
        }
    };
}
Also used : InputReferenceExpression(io.trino.sql.relational.InputReferenceExpression) Variable(io.airlift.bytecode.Variable) RecordCursor(io.trino.spi.connector.RecordCursor) ConstantExpression(io.trino.sql.relational.ConstantExpression) IfStatement(io.airlift.bytecode.control.IfStatement) Type(io.trino.spi.type.Type) Scope(io.airlift.bytecode.Scope) Slice(io.airlift.slice.Slice) VariableReferenceExpression(io.trino.sql.relational.VariableReferenceExpression) RowExpressionVisitor(io.trino.sql.relational.RowExpressionVisitor) CallExpression(io.trino.sql.relational.CallExpression) SpecialForm(io.trino.sql.relational.SpecialForm) LambdaDefinitionExpression(io.trino.sql.relational.LambdaDefinitionExpression)

Example 22 with Scope

use of io.airlift.bytecode.Scope in project trino by trinodb.

the class CursorProcessorCompiler method generateProjectMethod.

private void generateProjectMethod(ClassDefinition classDefinition, CallSiteBinder callSiteBinder, CachedInstanceBinder cachedInstanceBinder, Map<LambdaDefinitionExpression, CompiledLambda> compiledLambdaMap, String methodName, RowExpression projection) {
    Parameter session = arg("session", ConnectorSession.class);
    Parameter cursor = arg("cursor", RecordCursor.class);
    Parameter output = arg("output", BlockBuilder.class);
    MethodDefinition method = classDefinition.declareMethod(a(PUBLIC), methodName, type(void.class), session, cursor, output);
    method.comment("Projection: %s", projection);
    Scope scope = method.getScope();
    Variable wasNullVariable = scope.declareVariable(type(boolean.class), "wasNull");
    RowExpressionCompiler compiler = new RowExpressionCompiler(callSiteBinder, cachedInstanceBinder, fieldReferenceCompiler(cursor), functionManager, compiledLambdaMap);
    method.getBody().comment("boolean wasNull = false;").putVariable(wasNullVariable, false).getVariable(output).comment("evaluate projection: " + projection.toString()).append(compiler.compile(projection, scope)).append(generateWrite(callSiteBinder, scope, wasNullVariable, projection.getType())).ret();
}
Also used : Variable(io.airlift.bytecode.Variable) Scope(io.airlift.bytecode.Scope) MethodDefinition(io.airlift.bytecode.MethodDefinition) Parameter(io.airlift.bytecode.Parameter)

Example 23 with Scope

use of io.airlift.bytecode.Scope in project trino by trinodb.

the class InCodeGenerator method generateExpression.

@Override
public BytecodeNode generateExpression(BytecodeGeneratorContext generatorContext) {
    Type type = valueExpression.getType();
    Class<?> javaType = type.getJavaType();
    SwitchGenerationCase switchGenerationCase = checkSwitchGenerationCase(type, testExpressions);
    MethodHandle equalsMethodHandle = generatorContext.getScalarFunctionInvoker(resolvedEqualsFunction, simpleConvention(NULLABLE_RETURN, NEVER_NULL, NEVER_NULL)).getMethodHandle();
    MethodHandle hashCodeMethodHandle = generatorContext.getScalarFunctionInvoker(resolvedHashCodeFunction, simpleConvention(FAIL_ON_NULL, NEVER_NULL)).getMethodHandle();
    MethodHandle indeterminateMethodHandle = generatorContext.getScalarFunctionInvoker(resolvedIsIndeterminate, simpleConvention(FAIL_ON_NULL, NEVER_NULL)).getMethodHandle();
    ImmutableListMultimap.Builder<Integer, BytecodeNode> hashBucketsBuilder = ImmutableListMultimap.builder();
    ImmutableList.Builder<BytecodeNode> defaultBucket = ImmutableList.builder();
    ImmutableSet.Builder<Object> constantValuesBuilder = ImmutableSet.builder();
    for (RowExpression testValue : testExpressions) {
        BytecodeNode testBytecode = generatorContext.generate(testValue);
        if (isDeterminateConstant(testValue, indeterminateMethodHandle)) {
            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 = Long.hashCode((Long) hashCodeMethodHandle.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 Trino 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, resolvedEqualsFunction, match, defaultLabel, value, testValues, false, resolvedIsIndeterminate);
                switchBuilder.addCase(bucket.getKey(), caseBlock);
            }
            switchBuilder.defaultCase(jump(defaultLabel));
            Binding hashCodeBinding = generatorContext.getCallSiteBinder().bind(hashCodeMethodHandle);
            switchBlock = new BytecodeBlock().comment("lookupSwitch(hashCode(<stackValue>))").getVariable(value).append(invoke(hashCodeBinding, resolvedHashCodeFunction.getSignature())).invokeStatic(Long.class, "hashCode", int.class, long.class).putVariable(expression).append(switchBuilder.build());
            break;
        case SET_CONTAINS:
            Set<?> constantValuesSet = toFastutilHashSet(constantValues, type, hashCodeMethodHandle, equalsMethodHandle);
            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, resolvedEqualsFunction, match, noMatch, value, defaultBucket.build(), true, resolvedIsIndeterminate).setDescription("default");
    BytecodeBlock block = new BytecodeBlock().comment("IN").append(generatorContext.generate(valueExpression)).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);
    return block;
}
Also used : LabelNode(io.airlift.bytecode.instruction.LabelNode) Variable(io.airlift.bytecode.Variable) ImmutableList(com.google.common.collect.ImmutableList) ConstantExpression(io.trino.sql.relational.ConstantExpression) IfStatement(io.airlift.bytecode.control.IfStatement) ImmutableSet(com.google.common.collect.ImmutableSet) ImmutableListMultimap(com.google.common.collect.ImmutableListMultimap) BytecodeNode(io.airlift.bytecode.BytecodeNode) BytecodeBlock(io.airlift.bytecode.BytecodeBlock) RowExpression(io.trino.sql.relational.RowExpression) Type(io.trino.spi.type.Type) Scope(io.airlift.bytecode.Scope) SwitchBuilder(io.airlift.bytecode.control.SwitchStatement.SwitchBuilder) Collection(java.util.Collection) Map(java.util.Map) MethodHandle(java.lang.invoke.MethodHandle)

Example 24 with Scope

use of io.airlift.bytecode.Scope in project trino by trinodb.

the class JoinCompiler method generatePositionNotDistinctFromRowWithPageMethod.

private void generatePositionNotDistinctFromRowWithPageMethod(ClassDefinition classDefinition, CallSiteBinder callSiteBinder, List<Type> joinChannelTypes, List<FieldDefinition> joinChannelFields) {
    Parameter leftBlockIndex = arg("leftBlockIndex", int.class);
    Parameter leftBlockPosition = arg("leftBlockPosition", int.class);
    Parameter rightPosition = arg("rightPosition", int.class);
    Parameter page = arg("page", Page.class);
    Parameter rightChannels = arg("rightChannels", int[].class);
    MethodDefinition positionNotDistinctFromRowMethod = classDefinition.declareMethod(a(PUBLIC), "positionNotDistinctFromRow", type(boolean.class), leftBlockIndex, leftBlockPosition, rightPosition, page, rightChannels);
    Variable thisVariable = positionNotDistinctFromRowMethod.getThis();
    Scope scope = positionNotDistinctFromRowMethod.getScope();
    BytecodeBlock body = positionNotDistinctFromRowMethod.getBody();
    scope.declareVariable("wasNull", body, constantFalse());
    for (int index = 0; index < joinChannelTypes.size(); index++) {
        BytecodeExpression leftBlock = thisVariable.getField(joinChannelFields.get(index)).invoke("get", Object.class, leftBlockIndex).cast(Block.class);
        BytecodeExpression rightBlock = page.invoke("getBlock", Block.class, rightChannels.getElement(index));
        Type type = joinChannelTypes.get(index);
        body.append(new IfStatement().condition(typeDistinctFrom(callSiteBinder, type, leftBlock, leftBlockPosition, rightBlock, rightPosition)).ifTrue(constantFalse().ret()));
    }
    body.append(constantTrue().ret());
}
Also used : IfStatement(io.airlift.bytecode.control.IfStatement) SqlTypeBytecodeExpression.constantType(io.trino.sql.gen.SqlTypeBytecodeExpression.constantType) Type(io.trino.spi.type.Type) BigintType(io.trino.spi.type.BigintType) Variable(io.airlift.bytecode.Variable) Scope(io.airlift.bytecode.Scope) MethodDefinition(io.airlift.bytecode.MethodDefinition) BytecodeBlock(io.airlift.bytecode.BytecodeBlock) Parameter(io.airlift.bytecode.Parameter) BytecodeExpression(io.airlift.bytecode.expression.BytecodeExpression)

Example 25 with Scope

use of io.airlift.bytecode.Scope in project trino by trinodb.

the class OrderingCompiler method generatePageIndexCompareTo.

private void generatePageIndexCompareTo(ClassDefinition classDefinition, CallSiteBinder callSiteBinder, List<Type> sortTypes, List<Integer> sortChannels, List<SortOrder> sortOrders) {
    Parameter pagesIndex = arg("pagesIndex", PagesIndex.class);
    Parameter leftPosition = arg("leftPosition", int.class);
    Parameter rightPosition = arg("rightPosition", int.class);
    MethodDefinition compareToMethod = classDefinition.declareMethod(a(PUBLIC), "compareTo", type(int.class), pagesIndex, leftPosition, rightPosition);
    Scope scope = compareToMethod.getScope();
    Variable valueAddresses = scope.declareVariable(LongArrayList.class, "valueAddresses");
    compareToMethod.getBody().comment("LongArrayList valueAddresses = pagesIndex.valueAddresses").append(valueAddresses.set(pagesIndex.invoke("getValueAddresses", LongArrayList.class)));
    Variable leftPageAddress = scope.declareVariable(long.class, "leftPageAddress");
    compareToMethod.getBody().comment("long leftPageAddress = valueAddresses.getLong(leftPosition)").append(leftPageAddress.set(valueAddresses.invoke("getLong", long.class, leftPosition)));
    Variable leftBlockIndex = scope.declareVariable(int.class, "leftBlockIndex");
    compareToMethod.getBody().comment("int leftBlockIndex = decodeSliceIndex(leftPageAddress)").append(leftBlockIndex.set(invokeStatic(SyntheticAddress.class, "decodeSliceIndex", int.class, leftPageAddress)));
    Variable leftBlockPosition = scope.declareVariable(int.class, "leftBlockPosition");
    compareToMethod.getBody().comment("int leftBlockPosition = decodePosition(leftPageAddress)").append(leftBlockPosition.set(invokeStatic(SyntheticAddress.class, "decodePosition", int.class, leftPageAddress)));
    Variable rightPageAddress = scope.declareVariable(long.class, "rightPageAddress");
    compareToMethod.getBody().comment("long rightPageAddress = valueAddresses.getLong(rightPosition);").append(rightPageAddress.set(valueAddresses.invoke("getLong", long.class, rightPosition)));
    Variable rightBlockIndex = scope.declareVariable(int.class, "rightBlockIndex");
    compareToMethod.getBody().comment("int rightBlockIndex = decodeSliceIndex(rightPageAddress)").append(rightBlockIndex.set(invokeStatic(SyntheticAddress.class, "decodeSliceIndex", int.class, rightPageAddress)));
    Variable rightBlockPosition = scope.declareVariable(int.class, "rightBlockPosition");
    compareToMethod.getBody().comment("int rightBlockPosition = decodePosition(rightPageAddress)").append(rightBlockPosition.set(invokeStatic(SyntheticAddress.class, "decodePosition", int.class, rightPageAddress)));
    for (int i = 0; i < sortChannels.size(); i++) {
        int sortChannel = sortChannels.get(i);
        SortOrder sortOrder = sortOrders.get(i);
        Type sortType = sortTypes.get(i);
        MethodHandle compareBlockValue = getBlockPositionOrderingOperator(sortOrder, sortType);
        BytecodeBlock block = new BytecodeBlock().setDescription("compare channel " + sortChannel + " " + sortOrder);
        BytecodeExpression leftBlock = pagesIndex.invoke("getChannel", ObjectArrayList.class, constantInt(sortChannel)).invoke("get", Object.class, leftBlockIndex).cast(Block.class);
        BytecodeExpression rightBlock = pagesIndex.invoke("getChannel", ObjectArrayList.class, constantInt(sortChannel)).invoke("get", Object.class, rightBlockIndex).cast(Block.class);
        block.append(invokeDynamic(BOOTSTRAP_METHOD, ImmutableList.of(callSiteBinder.bind(compareBlockValue).getBindingId()), "compareBlockValue", compareBlockValue.type(), leftBlock, leftBlockPosition, rightBlock, rightBlockPosition));
        LabelNode equal = new LabelNode("equal");
        block.comment("if (compare != 0) return compare").dup().ifZeroGoto(equal).retInt().visitLabel(equal).pop(int.class);
        compareToMethod.getBody().append(block);
    }
    // values are equal
    compareToMethod.getBody().push(0).retInt();
}
Also used : LabelNode(io.airlift.bytecode.instruction.LabelNode) Type(io.trino.spi.type.Type) Variable(io.airlift.bytecode.Variable) Scope(io.airlift.bytecode.Scope) MethodDefinition(io.airlift.bytecode.MethodDefinition) BytecodeBlock(io.airlift.bytecode.BytecodeBlock) Parameter(io.airlift.bytecode.Parameter) SortOrder(io.trino.spi.connector.SortOrder) BytecodeExpression(io.airlift.bytecode.expression.BytecodeExpression) MethodHandle(java.lang.invoke.MethodHandle)

Aggregations

Scope (io.airlift.bytecode.Scope)67 Variable (io.airlift.bytecode.Variable)63 BytecodeBlock (io.airlift.bytecode.BytecodeBlock)56 MethodDefinition (io.airlift.bytecode.MethodDefinition)53 Parameter (io.airlift.bytecode.Parameter)49 IfStatement (io.airlift.bytecode.control.IfStatement)44 BytecodeNode (io.airlift.bytecode.BytecodeNode)21 ClassDefinition (io.airlift.bytecode.ClassDefinition)21 ImmutableList (com.google.common.collect.ImmutableList)17 ForLoop (io.airlift.bytecode.control.ForLoop)15 BytecodeExpression (io.airlift.bytecode.expression.BytecodeExpression)14 LabelNode (io.airlift.bytecode.instruction.LabelNode)14 Type (io.prestosql.spi.type.Type)12 Block (io.prestosql.spi.block.Block)11 ImmutableList.toImmutableList (com.google.common.collect.ImmutableList.toImmutableList)10 CallSiteBinder (io.prestosql.sql.gen.CallSiteBinder)9 Block (io.trino.spi.block.Block)9 VariableInstruction.incrementVariable (io.airlift.bytecode.instruction.VariableInstruction.incrementVariable)8 BlockBuilder (io.prestosql.spi.block.BlockBuilder)8 Type (io.trino.spi.type.Type)8