Search in sources :

Example 21 with LabelNode

use of io.airlift.bytecode.instruction.LabelNode in project trino by trinodb.

the class JoinCompiler method generateRowNotDistinctFromRowMethod.

private void generateRowNotDistinctFromRowMethod(ClassDefinition classDefinition, CallSiteBinder callSiteBinder, List<Type> joinChannelTypes) {
    Parameter leftPosition = arg("leftPosition", int.class);
    Parameter leftPage = arg("leftPage", Page.class);
    Parameter rightPosition = arg("rightPosition", int.class);
    Parameter rightPage = arg("rightPage", Page.class);
    MethodDefinition rowNotDistinctFromRowMethod = classDefinition.declareMethod(a(PUBLIC), "rowNotDistinctFromRow", type(boolean.class), leftPosition, leftPage, rightPosition, rightPage);
    for (int index = 0; index < joinChannelTypes.size(); index++) {
        Type type = joinChannelTypes.get(index);
        BytecodeExpression leftBlock = leftPage.invoke("getBlock", Block.class, constantInt(index));
        BytecodeExpression rightBlock = rightPage.invoke("getBlock", Block.class, constantInt(index));
        LabelNode checkNextField = new LabelNode("checkNextField");
        rowNotDistinctFromRowMethod.getBody().append(typeDistinctFrom(callSiteBinder, type, leftBlock, leftPosition, rightBlock, rightPosition)).ifFalseGoto(checkNextField).push(false).retBoolean().visitLabel(checkNextField);
    }
    rowNotDistinctFromRowMethod.getBody().push(true).retInt();
}
Also used : LabelNode(io.airlift.bytecode.instruction.LabelNode) SqlTypeBytecodeExpression.constantType(io.trino.sql.gen.SqlTypeBytecodeExpression.constantType) Type(io.trino.spi.type.Type) BigintType(io.trino.spi.type.BigintType) MethodDefinition(io.airlift.bytecode.MethodDefinition) Parameter(io.airlift.bytecode.Parameter) BytecodeExpression(io.airlift.bytecode.expression.BytecodeExpression)

Example 22 with LabelNode

use of io.airlift.bytecode.instruction.LabelNode 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)

Example 23 with LabelNode

use of io.airlift.bytecode.instruction.LabelNode in project trino by trinodb.

the class SwitchCodeGenerator method generateExpression.

@Override
public BytecodeNode generateExpression(BytecodeGeneratorContext generatorContext) {
    // TODO: compile as
    /*
            hashCode = hashCode(<value>)

            // all constant expressions before a non-constant
            switch (hashCode) {
                case ...:
                    if (<value> == <constant1>) {
                       ...
                    }
                    else if (<value> == <constant2>) {
                       ...
                    }
                    else if (...) {
                    }
                case ...:
                    ...
            }

            if (<value> == <non-constant1>) {
                ...
            }
            else if (<value> == <non-constant2>) {
                ...
            }
            ...

            // repeat with next sequence of constant expressions
         */
    Scope scope = generatorContext.getScope();
    // process value, else, and all when clauses
    BytecodeNode valueBytecode = generatorContext.generate(value);
    BytecodeNode elseValue;
    if (this.elseValue.isEmpty()) {
        elseValue = new BytecodeBlock().append(generatorContext.wasNull().set(constantTrue())).pushJavaDefault(returnType.getJavaType());
    } else {
        elseValue = generatorContext.generate(this.elseValue.get());
    }
    // determine the type of the value and result
    Class<?> valueType = value.getType().getJavaType();
    // evaluate the value and store it in a variable
    LabelNode nullValue = new LabelNode("nullCondition");
    Variable tempVariable = scope.createTempVariable(valueType);
    BytecodeBlock block = new BytecodeBlock().append(valueBytecode).append(BytecodeUtils.ifWasNullClearPopAndGoto(scope, nullValue, void.class, valueType)).putVariable(tempVariable);
    BytecodeNode getTempVariableNode = VariableInstruction.loadVariable(tempVariable);
    // build the statements
    elseValue = new BytecodeBlock().visitLabel(nullValue).append(elseValue);
    // reverse list because current if statement builder doesn't support if/else so we need to build the if statements bottom up
    for (int i = whenClauses.size() - 1; i >= 0; i--) {
        SpecialForm clause = whenClauses.get(i);
        RowExpression operand = clause.getArguments().get(0);
        RowExpression result = clause.getArguments().get(1);
        // call equals(value, operand)
        // TODO: what if operand is null? It seems that the call will return "null" (which is cleared below)
        // and the code only does the right thing because the value in the stack for that scenario is
        // Java's default for boolean == false
        // This code should probably be checking for wasNull after the call and "failing" the equality
        // check if wasNull is true
        BytecodeNode equalsCall = generatorContext.generateCall(equalsFunctions.get(i), ImmutableList.of(generatorContext.generate(operand), getTempVariableNode));
        BytecodeBlock condition = new BytecodeBlock().append(equalsCall).append(generatorContext.wasNull().set(constantFalse()));
        elseValue = new IfStatement("when").condition(condition).ifTrue(generatorContext.generate(result)).ifFalse(elseValue);
    }
    return block.append(elseValue);
}
Also used : LabelNode(io.airlift.bytecode.instruction.LabelNode) IfStatement(io.airlift.bytecode.control.IfStatement) Variable(io.airlift.bytecode.Variable) Scope(io.airlift.bytecode.Scope) BytecodeBlock(io.airlift.bytecode.BytecodeBlock) RowExpression(io.trino.sql.relational.RowExpression) BytecodeNode(io.airlift.bytecode.BytecodeNode) SpecialForm(io.trino.sql.relational.SpecialForm)

Example 24 with LabelNode

use of io.airlift.bytecode.instruction.LabelNode in project trino by trinodb.

the class BytecodeUtils method unboxPrimitiveIfNecessary.

public static BytecodeBlock unboxPrimitiveIfNecessary(Scope scope, Class<?> boxedType) {
    BytecodeBlock block = new BytecodeBlock();
    LabelNode end = new LabelNode("end");
    Class<?> unboxedType = Primitives.unwrap(boxedType);
    Variable wasNull = scope.getVariable("wasNull");
    if (unboxedType.isPrimitive()) {
        LabelNode notNull = new LabelNode("notNull");
        block.dup(boxedType).ifNotNullGoto(notNull).append(wasNull.set(constantTrue())).comment("swap boxed null with unboxed default").pop(boxedType).pushJavaDefault(unboxedType).gotoLabel(end).visitLabel(notNull).append(unboxPrimitive(unboxedType));
    } else {
        block.dup(boxedType).ifNotNullGoto(end).append(wasNull.set(constantTrue()));
    }
    block.visitLabel(end);
    return block;
}
Also used : LabelNode(io.airlift.bytecode.instruction.LabelNode) Variable(io.airlift.bytecode.Variable) BytecodeBlock(io.airlift.bytecode.BytecodeBlock)

Example 25 with LabelNode

use of io.airlift.bytecode.instruction.LabelNode in project trino by trinodb.

the class BytecodeUtils method generateFullInvocation.

private static BytecodeNode generateFullInvocation(Scope scope, String functionName, FunctionNullability functionNullability, List<Boolean> argumentIsFunctionType, Function<InvocationConvention, FunctionInvoker> functionInvokerProvider, Function<MethodHandle, BytecodeNode> instanceFactory, List<Function<Optional<Class<?>>, BytecodeNode>> argumentCompilers, CallSiteBinder binder) {
    verify(argumentIsFunctionType.size() == argumentCompilers.size());
    List<InvocationArgumentConvention> argumentConventions = new ArrayList<>();
    List<BytecodeNode> arguments = new ArrayList<>();
    for (int i = 0; i < argumentIsFunctionType.size(); i++) {
        if (argumentIsFunctionType.get(i)) {
            argumentConventions.add(FUNCTION);
            arguments.add(null);
        } else {
            BytecodeNode argument = argumentCompilers.get(i).apply(Optional.empty());
            argumentConventions.add(getPreferredArgumentConvention(argument, argumentCompilers.size(), functionNullability.isArgumentNullable(i)));
            arguments.add(argument);
        }
    }
    InvocationConvention invocationConvention = new InvocationConvention(argumentConventions, functionNullability.isReturnNullable() ? NULLABLE_RETURN : FAIL_ON_NULL, true, true);
    FunctionInvoker functionInvoker = functionInvokerProvider.apply(invocationConvention);
    Binding binding = binder.bind(functionInvoker.getMethodHandle());
    LabelNode end = new LabelNode("end");
    BytecodeBlock block = new BytecodeBlock().setDescription("invoke " + functionName);
    Optional<BytecodeNode> instance = functionInvoker.getInstanceFactory().map(instanceFactory);
    // Index of current parameter in the MethodHandle
    int currentParameterIndex = 0;
    // Index of parameter (without @IsNull) in Trino function
    int realParameterIndex = 0;
    // Index of function argument types
    int lambdaArgumentIndex = 0;
    MethodType methodType = binding.getType();
    Class<?> returnType = methodType.returnType();
    Class<?> unboxedReturnType = Primitives.unwrap(returnType);
    List<Class<?>> stackTypes = new ArrayList<>();
    boolean instanceIsBound = false;
    while (currentParameterIndex < methodType.parameterArray().length) {
        Class<?> type = methodType.parameterArray()[currentParameterIndex];
        stackTypes.add(type);
        if (instance.isPresent() && !instanceIsBound) {
            checkState(type.equals(functionInvoker.getInstanceFactory().get().type().returnType()), "Mismatched type for instance parameter");
            block.append(instance.get());
            instanceIsBound = true;
        } else if (type == ConnectorSession.class) {
            block.append(scope.getVariable("session"));
        } else {
            switch(invocationConvention.getArgumentConvention(realParameterIndex)) {
                case NEVER_NULL:
                    block.append(arguments.get(realParameterIndex));
                    checkArgument(!Primitives.isWrapperType(type), "Non-nullable argument must not be primitive wrapper type");
                    block.append(ifWasNullPopAndGoto(scope, end, unboxedReturnType, Lists.reverse(stackTypes)));
                    break;
                case NULL_FLAG:
                    block.append(arguments.get(realParameterIndex));
                    block.append(scope.getVariable("wasNull"));
                    block.append(scope.getVariable("wasNull").set(constantFalse()));
                    stackTypes.add(boolean.class);
                    currentParameterIndex++;
                    break;
                case BOXED_NULLABLE:
                    block.append(arguments.get(realParameterIndex));
                    block.append(boxPrimitiveIfNecessary(scope, type));
                    block.append(scope.getVariable("wasNull").set(constantFalse()));
                    break;
                case BLOCK_POSITION:
                    InputReferenceNode inputReferenceNode = (InputReferenceNode) arguments.get(realParameterIndex);
                    block.append(inputReferenceNode.produceBlockAndPosition());
                    stackTypes.add(int.class);
                    if (!functionNullability.isArgumentNullable(realParameterIndex)) {
                        block.append(scope.getVariable("wasNull").set(inputReferenceNode.blockAndPositionIsNull()));
                        block.append(ifWasNullPopAndGoto(scope, end, unboxedReturnType, Lists.reverse(stackTypes)));
                    }
                    currentParameterIndex++;
                    break;
                case FUNCTION:
                    Class<?> lambdaInterface = functionInvoker.getLambdaInterfaces().get(lambdaArgumentIndex);
                    block.append(argumentCompilers.get(realParameterIndex).apply(Optional.of(lambdaInterface)));
                    lambdaArgumentIndex++;
                    break;
                default:
                    throw new UnsupportedOperationException(format("Unsupported argument conventsion type: %s", invocationConvention.getArgumentConvention(realParameterIndex)));
            }
            realParameterIndex++;
        }
        currentParameterIndex++;
    }
    block.append(invoke(binding, functionName));
    if (functionNullability.isReturnNullable()) {
        block.append(unboxPrimitiveIfNecessary(scope, returnType));
    }
    block.visitLabel(end);
    return block;
}
Also used : LabelNode(io.airlift.bytecode.instruction.LabelNode) MethodType(java.lang.invoke.MethodType) ArrayList(java.util.ArrayList) BytecodeBlock(io.airlift.bytecode.BytecodeBlock) InputReferenceNode(io.trino.sql.gen.InputReferenceCompiler.InputReferenceNode) InvocationArgumentConvention(io.trino.spi.function.InvocationConvention.InvocationArgumentConvention) InvocationConvention(io.trino.spi.function.InvocationConvention) BytecodeNode(io.airlift.bytecode.BytecodeNode) FunctionInvoker(io.trino.metadata.FunctionInvoker) ConnectorSession(io.trino.spi.connector.ConnectorSession)

Aggregations

LabelNode (io.airlift.bytecode.instruction.LabelNode)39 Variable (io.airlift.bytecode.Variable)32 BytecodeBlock (io.airlift.bytecode.BytecodeBlock)29 MethodDefinition (io.airlift.bytecode.MethodDefinition)19 Parameter (io.airlift.bytecode.Parameter)19 IfStatement (io.airlift.bytecode.control.IfStatement)19 BytecodeExpression (io.airlift.bytecode.expression.BytecodeExpression)17 BytecodeNode (io.airlift.bytecode.BytecodeNode)16 Scope (io.airlift.bytecode.Scope)14 Type (io.trino.spi.type.Type)10 Type (io.prestosql.spi.type.Type)6 BigintType (io.trino.spi.type.BigintType)6 SqlTypeBytecodeExpression.constantType (io.trino.sql.gen.SqlTypeBytecodeExpression.constantType)6 ImmutableList (com.google.common.collect.ImmutableList)5 FunctionHandle (io.prestosql.spi.function.FunctionHandle)5 RowExpression (io.trino.sql.relational.RowExpression)5 BuiltInScalarFunctionImplementation (io.prestosql.spi.function.BuiltInScalarFunctionImplementation)4 RowExpression (io.prestosql.spi.relation.RowExpression)4 MethodHandle (java.lang.invoke.MethodHandle)4 ImmutableSet (com.google.common.collect.ImmutableSet)3