Search in sources :

Example 71 with BytecodeBlock

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

the class BytecodeUtils method generateInvocation.

public static BytecodeNode generateInvocation(Scope scope, String name, ScalarFunctionImplementation function, Optional<BytecodeNode> instance, List<BytecodeNode> arguments, Binding binding) {
    MethodType methodType = binding.getType();
    Class<?> returnType = methodType.returnType();
    Class<?> unboxedReturnType = Primitives.unwrap(returnType);
    LabelNode end = new LabelNode("end");
    BytecodeBlock block = new BytecodeBlock().setDescription("invoke " + name);
    List<Class<?>> stackTypes = new ArrayList<>();
    if (function.getInstanceFactory().isPresent()) {
        checkArgument(instance.isPresent());
    }
    // Index of current parameter in the MethodHandle
    int currentParameterIndex = 0;
    // Index of parameter (without @IsNull) in Presto function
    int realParameterIndex = 0;
    boolean boundInstance = false;
    while (currentParameterIndex < methodType.parameterArray().length) {
        Class<?> type = methodType.parameterArray()[currentParameterIndex];
        stackTypes.add(type);
        if (function.getInstanceFactory().isPresent() && !boundInstance) {
            checkState(type.equals(function.getInstanceFactory().get().type().returnType()), "Mismatched type for instance parameter");
            block.append(instance.get());
            boundInstance = true;
        } else if (type == ConnectorSession.class) {
            block.append(scope.getVariable("session"));
        } else {
            block.append(arguments.get(realParameterIndex));
            if (!function.getNullableArguments().get(realParameterIndex)) {
                checkArgument(!Primitives.isWrapperType(type), "Non-nullable argument must not be primitive wrapper type");
                block.append(ifWasNullPopAndGoto(scope, end, unboxedReturnType, Lists.reverse(stackTypes)));
            } else {
                if (function.getNullFlags().get(realParameterIndex)) {
                    if (type == Void.class) {
                        block.append(boxPrimitiveIfNecessary(scope, type));
                    }
                    block.append(scope.getVariable("wasNull"));
                    stackTypes.add(boolean.class);
                    currentParameterIndex++;
                } else {
                    block.append(boxPrimitiveIfNecessary(scope, type));
                }
                block.append(scope.getVariable("wasNull").set(constantFalse()));
            }
            realParameterIndex++;
        }
        currentParameterIndex++;
    }
    block.append(invoke(binding, name));
    if (function.isNullable()) {
        block.append(unboxPrimitiveIfNecessary(scope, returnType));
    }
    block.visitLabel(end);
    return block;
}
Also used : LabelNode(com.facebook.presto.bytecode.instruction.LabelNode) MethodType(java.lang.invoke.MethodType) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) ArrayList(java.util.ArrayList) ConnectorSession(com.facebook.presto.spi.ConnectorSession)

Example 72 with BytecodeBlock

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

the class BytecodeUtils method boxPrimitiveIfNecessary.

public static BytecodeNode boxPrimitiveIfNecessary(Scope scope, Class<?> type) {
    checkArgument(!type.isPrimitive(), "cannot box into primitive type");
    if (!Primitives.isWrapperType(type)) {
        return NOP;
    }
    BytecodeBlock notNull = new BytecodeBlock().comment("box primitive");
    Class<?> expectedCurrentStackType;
    if (type == Long.class) {
        notNull.invokeStatic(Long.class, "valueOf", Long.class, long.class);
        expectedCurrentStackType = long.class;
    } else if (type == Double.class) {
        notNull.invokeStatic(Double.class, "valueOf", Double.class, double.class);
        expectedCurrentStackType = double.class;
    } else if (type == Boolean.class) {
        notNull.invokeStatic(Boolean.class, "valueOf", Boolean.class, boolean.class);
        expectedCurrentStackType = boolean.class;
    } else if (type == Void.class) {
        notNull.pushNull().checkCast(Void.class);
        return notNull;
    } else {
        throw new UnsupportedOperationException("not yet implemented: " + type);
    }
    BytecodeBlock condition = new BytecodeBlock().append(scope.getVariable("wasNull"));
    BytecodeBlock wasNull = new BytecodeBlock().pop(expectedCurrentStackType).pushNull().checkCast(type);
    return new IfStatement().condition(condition).ifTrue(wasNull).ifFalse(notNull);
}
Also used : IfStatement(com.facebook.presto.bytecode.control.IfStatement) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock)

Example 73 with BytecodeBlock

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

the class BytecodeUtils method generateWrite.

public static BytecodeNode generateWrite(CallSiteBinder callSiteBinder, Scope scope, Variable wasNullVariable, Type type) {
    if (type.getJavaType() == void.class) {
        return new BytecodeBlock().comment("output.appendNull();").invokeInterface(BlockBuilder.class, "appendNull", BlockBuilder.class).pop();
    }
    Class<?> valueJavaType = type.getJavaType();
    if (!valueJavaType.isPrimitive() && valueJavaType != Slice.class) {
        valueJavaType = Object.class;
    }
    String methodName = "write" + Primitives.wrap(valueJavaType).getSimpleName();
    // the stack contains [output, value]
    // We should be able to insert the code to get the output variable and compute the value
    // at the right place instead of assuming they are in the stack. We should also not need to
    // use temp variables to re-shuffle the stack to the right shape before Type.writeXXX is called
    // Unfortunately, because of the assumptions made by try_cast, we can't get around it yet.
    // TODO: clean up once try_cast is fixed
    Variable tempValue = scope.createTempVariable(valueJavaType);
    Variable tempOutput = scope.createTempVariable(BlockBuilder.class);
    return new BytecodeBlock().comment("if (wasNull)").append(new IfStatement().condition(wasNullVariable).ifTrue(new BytecodeBlock().comment("output.appendNull();").pop(valueJavaType).invokeInterface(BlockBuilder.class, "appendNull", BlockBuilder.class).pop()).ifFalse(new BytecodeBlock().comment("%s.%s(output, %s)", type.getTypeSignature(), methodName, valueJavaType.getSimpleName()).putVariable(tempValue).putVariable(tempOutput).append(loadConstant(callSiteBinder.bind(type, Type.class))).getVariable(tempOutput).getVariable(tempValue).invokeInterface(Type.class, methodName, void.class, BlockBuilder.class, valueJavaType)));
}
Also used : IfStatement(com.facebook.presto.bytecode.control.IfStatement) Type(com.facebook.presto.spi.type.Type) MethodType(java.lang.invoke.MethodType) Variable(com.facebook.presto.bytecode.Variable) Slice(io.airlift.slice.Slice) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) BlockBuilder(com.facebook.presto.spi.block.BlockBuilder)

Example 74 with BytecodeBlock

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

the class JoinCompiler method generateAppendToMethod.

private static void generateAppendToMethod(ClassDefinition classDefinition, CallSiteBinder callSiteBinder, List<Type> types, List<Integer> outputChannels, List<FieldDefinition> channelFields) {
    Parameter blockIndex = arg("blockIndex", int.class);
    Parameter blockPosition = arg("blockPosition", int.class);
    Parameter pageBuilder = arg("pageBuilder", PageBuilder.class);
    Parameter outputChannelOffset = arg("outputChannelOffset", int.class);
    MethodDefinition appendToMethod = classDefinition.declareMethod(a(PUBLIC), "appendTo", type(void.class), blockIndex, blockPosition, pageBuilder, outputChannelOffset);
    Variable thisVariable = appendToMethod.getThis();
    BytecodeBlock appendToBody = appendToMethod.getBody();
    int pageBuilderOutputChannel = 0;
    for (int outputChannel : outputChannels) {
        Type type = types.get(outputChannel);
        BytecodeExpression typeExpression = constantType(callSiteBinder, type);
        BytecodeExpression block = thisVariable.getField(channelFields.get(outputChannel)).invoke("get", Object.class, blockIndex).cast(Block.class);
        appendToBody.comment("%s.appendTo(channel_%s.get(outputChannel), blockPosition, pageBuilder.getBlockBuilder(outputChannelOffset + %s));", type.getClass(), outputChannel, pageBuilderOutputChannel).append(typeExpression).append(block).append(blockPosition).append(pageBuilder).append(outputChannelOffset).push(pageBuilderOutputChannel++).append(OpCode.IADD).invokeVirtual(PageBuilder.class, "getBlockBuilder", BlockBuilder.class, int.class).invokeInterface(Type.class, "appendTo", void.class, Block.class, int.class, BlockBuilder.class);
    }
    appendToBody.ret();
}
Also used : Type(com.facebook.presto.spi.type.Type) SqlTypeBytecodeExpression.constantType(com.facebook.presto.sql.gen.SqlTypeBytecodeExpression.constantType) BigintType(com.facebook.presto.spi.type.BigintType) Variable(com.facebook.presto.bytecode.Variable) MethodDefinition(com.facebook.presto.bytecode.MethodDefinition) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) Parameter(com.facebook.presto.bytecode.Parameter) PageBuilder(com.facebook.presto.spi.PageBuilder) BytecodeExpression(com.facebook.presto.bytecode.expression.BytecodeExpression) BlockBuilder(com.facebook.presto.spi.block.BlockBuilder)

Example 75 with BytecodeBlock

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

the class JoinProbeCompiler method generateConstructor.

private static void generateConstructor(ClassDefinition classDefinition, List<Integer> probeChannels, Optional<Integer> probeHashChannel, FieldDefinition lookupSourceField, List<FieldDefinition> blockFields, List<FieldDefinition> probeChannelFields, FieldDefinition probeBlocksArrayField, FieldDefinition probePageField, FieldDefinition pageField, FieldDefinition probeHashBlockField, FieldDefinition positionField, FieldDefinition positionCountField) {
    Parameter lookupSource = arg("lookupSource", LookupSource.class);
    Parameter page = arg("page", Page.class);
    MethodDefinition constructorDefinition = classDefinition.declareConstructor(a(PUBLIC), lookupSource, page);
    Variable thisVariable = constructorDefinition.getThis();
    BytecodeBlock constructor = constructorDefinition.getBody().comment("super();").append(thisVariable).invokeConstructor(Object.class);
    constructor.comment("this.lookupSource = lookupSource;").append(thisVariable.setField(lookupSourceField, lookupSource));
    constructor.comment("this.positionCount = page.getPositionCount();").append(thisVariable.setField(positionCountField, page.invoke("getPositionCount", int.class)));
    constructor.comment("Set block fields");
    for (int index = 0; index < blockFields.size(); index++) {
        constructor.append(thisVariable.setField(blockFields.get(index), page.invoke("getBlock", Block.class, constantInt(index))));
    }
    constructor.comment("Set probe channel fields");
    for (int index = 0; index < probeChannelFields.size(); index++) {
        constructor.append(thisVariable.setField(probeChannelFields.get(index), thisVariable.getField(blockFields.get(probeChannels.get(index)))));
    }
    constructor.comment("this.probeBlocks = new Block[<probeChannelCount>];");
    constructor.append(thisVariable).push(probeChannelFields.size()).newArray(Block.class).putField(probeBlocksArrayField);
    for (int index = 0; index < probeChannelFields.size(); index++) {
        constructor.append(thisVariable).getField(probeBlocksArrayField).push(index).append(thisVariable).getField(probeChannelFields.get(index)).putObjectArrayElement();
    }
    constructor.comment("this.page = page").append(thisVariable.setField(pageField, page));
    constructor.comment("this.probePage = new Page(probeBlocks)").append(thisVariable.setField(probePageField, newInstance(Page.class, thisVariable.getField(probeBlocksArrayField))));
    if (probeHashChannel.isPresent()) {
        Integer index = probeHashChannel.get();
        constructor.comment("this.probeHashBlock = blocks[hashChannel.get()]").append(thisVariable.setField(probeHashBlockField, thisVariable.getField(blockFields.get(index))));
    }
    constructor.comment("this.position = -1;").append(thisVariable.setField(positionField, constantInt(-1)));
    constructor.ret();
}
Also used : Variable(com.facebook.presto.bytecode.Variable) MethodDefinition(com.facebook.presto.bytecode.MethodDefinition) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) Parameter(com.facebook.presto.bytecode.Parameter) Block(com.facebook.presto.spi.block.Block) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock)

Aggregations

BytecodeBlock (com.facebook.presto.bytecode.BytecodeBlock)82 Variable (com.facebook.presto.bytecode.Variable)57 MethodDefinition (com.facebook.presto.bytecode.MethodDefinition)43 IfStatement (com.facebook.presto.bytecode.control.IfStatement)42 Parameter (com.facebook.presto.bytecode.Parameter)38 Scope (com.facebook.presto.bytecode.Scope)33 Block (com.facebook.presto.spi.block.Block)23 BytecodeExpression (com.facebook.presto.bytecode.expression.BytecodeExpression)18 LabelNode (com.facebook.presto.bytecode.instruction.LabelNode)18 BytecodeNode (com.facebook.presto.bytecode.BytecodeNode)17 ImmutableList (com.google.common.collect.ImmutableList)16 ForLoop (com.facebook.presto.bytecode.control.ForLoop)12 Type (com.facebook.presto.spi.type.Type)12 ClassDefinition (com.facebook.presto.bytecode.ClassDefinition)11 DictionaryBlock (com.facebook.presto.spi.block.DictionaryBlock)11 LazyBlock (com.facebook.presto.spi.block.LazyBlock)11 RunLengthEncodedBlock (com.facebook.presto.spi.block.RunLengthEncodedBlock)11 BlockBuilder (com.facebook.presto.spi.block.BlockBuilder)10 List (java.util.List)9 RowExpression (com.facebook.presto.sql.relational.RowExpression)7