Search in sources :

Example 16 with ForLoop

use of com.facebook.presto.bytecode.control.ForLoop in project presto by prestodb.

the class ArrayTransformFunction method generateTransform.

private static Class<?> generateTransform(Type inputType, Type outputType) {
    CallSiteBinder binder = new CallSiteBinder();
    Class<?> inputJavaType = Primitives.wrap(inputType.getJavaType());
    Class<?> outputJavaType = Primitives.wrap(outputType.getJavaType());
    ClassDefinition definition = new ClassDefinition(a(PUBLIC, FINAL), makeClassName("ArrayTransform"), type(Object.class));
    definition.declareDefaultConstructor(a(PRIVATE));
    // define createPageBuilder
    MethodDefinition createPageBuilderMethod = definition.declareMethod(a(PUBLIC, STATIC), "createPageBuilder", type(PageBuilder.class));
    createPageBuilderMethod.getBody().append(newInstance(PageBuilder.class, constantType(binder, new ArrayType(outputType)).invoke("getTypeParameters", List.class)).ret());
    // define transform method
    Parameter pageBuilder = arg("pageBuilder", PageBuilder.class);
    Parameter block = arg("block", Block.class);
    Parameter function = arg("function", UnaryFunctionInterface.class);
    MethodDefinition method = definition.declareMethod(a(PUBLIC, STATIC), "transform", type(Block.class), ImmutableList.of(pageBuilder, block, function));
    BytecodeBlock body = method.getBody();
    Scope scope = method.getScope();
    Variable positionCount = scope.declareVariable(int.class, "positionCount");
    Variable position = scope.declareVariable(int.class, "position");
    Variable blockBuilder = scope.declareVariable(BlockBuilder.class, "blockBuilder");
    Variable inputElement = scope.declareVariable(inputJavaType, "inputElement");
    Variable outputElement = scope.declareVariable(outputJavaType, "outputElement");
    // invoke block.getPositionCount()
    body.append(positionCount.set(block.invoke("getPositionCount", int.class)));
    // reset page builder if it is full
    body.append(new IfStatement().condition(pageBuilder.invoke("isFull", boolean.class)).ifTrue(pageBuilder.invoke("reset", void.class)));
    // get block builder
    body.append(blockBuilder.set(pageBuilder.invoke("getBlockBuilder", BlockBuilder.class, constantInt(0))));
    BytecodeNode loadInputElement;
    if (!inputType.equals(UNKNOWN)) {
        loadInputElement = new IfStatement().condition(block.invoke("isNull", boolean.class, position)).ifTrue(inputElement.set(constantNull(inputJavaType))).ifFalse(inputElement.set(constantType(binder, inputType).getValue(block, position).cast(inputJavaType)));
    } else {
        loadInputElement = new BytecodeBlock().append(inputElement.set(constantNull(inputJavaType)));
    }
    BytecodeNode writeOutputElement;
    if (!outputType.equals(UNKNOWN)) {
        writeOutputElement = new IfStatement().condition(equal(outputElement, constantNull(outputJavaType))).ifTrue(blockBuilder.invoke("appendNull", BlockBuilder.class).pop()).ifFalse(constantType(binder, outputType).writeValue(blockBuilder, outputElement.cast(outputType.getJavaType())));
    } else {
        writeOutputElement = new BytecodeBlock().append(blockBuilder.invoke("appendNull", BlockBuilder.class).pop());
    }
    body.append(new ForLoop().initialize(position.set(constantInt(0))).condition(lessThan(position, positionCount)).update(incrementVariable(position, (byte) 1)).body(new BytecodeBlock().append(loadInputElement).append(outputElement.set(function.invoke("apply", Object.class, inputElement.cast(Object.class)).cast(outputJavaType))).append(writeOutputElement)));
    body.append(pageBuilder.invoke("declarePositions", void.class, positionCount));
    body.append(blockBuilder.invoke("getRegion", Block.class, subtract(blockBuilder.invoke("getPositionCount", int.class), positionCount), positionCount).ret());
    return defineClass(definition, Object.class, binder.getBindings(), ArrayTransformFunction.class.getClassLoader());
}
Also used : Signature.typeVariable(com.facebook.presto.spi.function.Signature.typeVariable) Variable(com.facebook.presto.bytecode.Variable) VariableInstruction.incrementVariable(com.facebook.presto.bytecode.instruction.VariableInstruction.incrementVariable) ForLoop(com.facebook.presto.bytecode.control.ForLoop) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) PageBuilder(com.facebook.presto.common.PageBuilder) ClassDefinition(com.facebook.presto.bytecode.ClassDefinition) ArrayType(com.facebook.presto.common.type.ArrayType) IfStatement(com.facebook.presto.bytecode.control.IfStatement) Scope(com.facebook.presto.bytecode.Scope) MethodDefinition(com.facebook.presto.bytecode.MethodDefinition) CallSiteBinder(com.facebook.presto.bytecode.CallSiteBinder) Parameter(com.facebook.presto.bytecode.Parameter) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) Block(com.facebook.presto.common.block.Block) List(java.util.List) ImmutableList(com.google.common.collect.ImmutableList) BytecodeNode(com.facebook.presto.bytecode.BytecodeNode) BlockBuilder(com.facebook.presto.common.block.BlockBuilder)

Example 17 with ForLoop

use of com.facebook.presto.bytecode.control.ForLoop in project presto by prestodb.

the class PageFunctionCompiler method generatePageFilterMethod.

private static MethodDefinition generatePageFilterMethod(ClassDefinition classDefinition, FieldDefinition selectedPositionsField) {
    Parameter properties = arg("properties", SqlFunctionProperties.class);
    Parameter page = arg("page", Page.class);
    MethodDefinition method = classDefinition.declareMethod(a(PUBLIC), "filter", type(SelectedPositions.class), ImmutableList.<Parameter>builder().add(properties).add(page).build());
    Scope scope = method.getScope();
    Variable thisVariable = method.getThis();
    BytecodeBlock body = method.getBody();
    Variable positionCount = scope.declareVariable("positionCount", body, page.invoke("getPositionCount", int.class));
    body.append(new IfStatement("grow selectedPositions if necessary").condition(lessThan(thisVariable.getField(selectedPositionsField).length(), positionCount)).ifTrue(thisVariable.setField(selectedPositionsField, newArray(type(boolean[].class), positionCount))));
    Variable selectedPositions = scope.declareVariable("selectedPositions", body, thisVariable.getField(selectedPositionsField));
    Variable position = scope.declareVariable(int.class, "position");
    body.append(new ForLoop().initialize(position.set(constantInt(0))).condition(lessThan(position, positionCount)).update(position.increment()).body(selectedPositions.setElement(position, thisVariable.invoke("filter", boolean.class, properties, page, position))));
    body.append(invokeStatic(PageFilter.class, "positionsArrayToSelectedPositions", SelectedPositions.class, selectedPositions, positionCount).ret());
    return method;
}
Also used : IfStatement(com.facebook.presto.bytecode.control.IfStatement) Variable(com.facebook.presto.bytecode.Variable) Scope(com.facebook.presto.bytecode.Scope) ForLoop(com.facebook.presto.bytecode.control.ForLoop) MethodDefinition(com.facebook.presto.bytecode.MethodDefinition) SelectedPositions(com.facebook.presto.operator.project.SelectedPositions) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) Parameter(com.facebook.presto.bytecode.Parameter)

Example 18 with ForLoop

use of com.facebook.presto.bytecode.control.ForLoop in project presto by prestodb.

the class JoinCompiler method generateConstructor.

private static void generateConstructor(ClassDefinition classDefinition, List<Integer> joinChannels, FieldDefinition sizeField, FieldDefinition instanceSizeField, List<FieldDefinition> channelFields, List<FieldDefinition> joinChannelFields, FieldDefinition hashChannelField) {
    Parameter channels = arg("channels", type(List.class, type(List.class, Block.class)));
    Parameter hashChannel = arg("hashChannel", type(OptionalInt.class));
    MethodDefinition constructorDefinition = classDefinition.declareConstructor(a(PUBLIC), channels, hashChannel);
    Variable thisVariable = constructorDefinition.getThis();
    Variable blockIndex = constructorDefinition.getScope().declareVariable(int.class, "blockIndex");
    BytecodeBlock constructor = constructorDefinition.getBody().comment("super();").append(thisVariable).invokeConstructor(Object.class);
    constructor.comment("this.size = INSTANCE_SIZE").append(thisVariable.setField(sizeField, getStatic(instanceSizeField)));
    constructor.comment("Set channel fields");
    for (int index = 0; index < channelFields.size(); index++) {
        BytecodeExpression channel = channels.invoke("get", Object.class, constantInt(index)).cast(type(List.class, Block.class));
        constructor.append(thisVariable.setField(channelFields.get(index), channel));
        BytecodeBlock loopBody = new BytecodeBlock();
        constructor.comment("for(blockIndex = 0; blockIndex < channel.size(); blockIndex++) { size += channel.get(i).getRetainedSizeInBytes() }").append(new ForLoop().initialize(blockIndex.set(constantInt(0))).condition(new BytecodeBlock().append(blockIndex).append(channel.invoke("size", int.class)).invokeStatic(CompilerOperations.class, "lessThan", boolean.class, int.class, int.class)).update(new BytecodeBlock().incrementVariable(blockIndex, (byte) 1)).body(loopBody));
        loopBody.append(thisVariable).append(thisVariable).getField(sizeField).append(channel.invoke("get", Object.class, blockIndex).cast(type(Block.class)).invoke("getRetainedSizeInBytes", long.class)).longAdd().putField(sizeField);
    }
    constructor.comment("Set join channel fields");
    for (int index = 0; index < joinChannelFields.size(); index++) {
        BytecodeExpression joinChannel = channels.invoke("get", Object.class, constantInt(joinChannels.get(index))).cast(type(List.class, Block.class));
        constructor.append(thisVariable.setField(joinChannelFields.get(index), joinChannel));
    }
    constructor.comment("Set hashChannel");
    constructor.append(new IfStatement().condition(hashChannel.invoke("isPresent", boolean.class)).ifTrue(thisVariable.setField(hashChannelField, channels.invoke("get", Object.class, hashChannel.invoke("getAsInt", int.class)))).ifFalse(thisVariable.setField(hashChannelField, constantNull(hashChannelField.getType()))));
    constructor.ret();
}
Also used : IfStatement(com.facebook.presto.bytecode.control.IfStatement) Variable(com.facebook.presto.bytecode.Variable) 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) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) Block(com.facebook.presto.common.block.Block) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) List(java.util.List) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) OptionalInt(java.util.OptionalInt) BytecodeExpression(com.facebook.presto.bytecode.expression.BytecodeExpression)

Example 19 with ForLoop

use of com.facebook.presto.bytecode.control.ForLoop in project presto by prestodb.

the class PageFunctionCompiler method generateProcessMethod.

private static MethodDefinition generateProcessMethod(ClassDefinition classDefinition, FieldDefinition blockBuilders, int blockBuilderSize, FieldDefinition properties, FieldDefinition page, FieldDefinition selectedPositions, FieldDefinition nextIndexOrPosition, FieldDefinition result) {
    MethodDefinition method = classDefinition.declareMethod(a(PUBLIC), "process", type(boolean.class), ImmutableList.of());
    Scope scope = method.getScope();
    Variable thisVariable = method.getThis();
    BytecodeBlock body = method.getBody();
    Variable from = scope.declareVariable("from", body, thisVariable.getField(nextIndexOrPosition));
    Variable to = scope.declareVariable("to", body, add(thisVariable.getField(selectedPositions).invoke("getOffset", int.class), thisVariable.getField(selectedPositions).invoke("size", int.class)));
    Variable positions = scope.declareVariable(int[].class, "positions");
    Variable index = scope.declareVariable(int.class, "index");
    IfStatement ifStatement = new IfStatement().condition(thisVariable.getField(selectedPositions).invoke("isList", boolean.class));
    body.append(ifStatement);
    ifStatement.ifTrue(new BytecodeBlock().append(positions.set(thisVariable.getField(selectedPositions).invoke("getPositions", int[].class))).append(new ForLoop("positions loop").initialize(index.set(from)).condition(lessThan(index, to)).update(index.increment()).body(new BytecodeBlock().append(thisVariable.invoke("evaluate", void.class, thisVariable.getField(properties), thisVariable.getField(page), positions.getElement(index))))));
    ifStatement.ifFalse(new ForLoop("range based loop").initialize(index.set(from)).condition(lessThan(index, to)).update(index.increment()).body(new BytecodeBlock().append(thisVariable.invoke("evaluate", void.class, thisVariable.getField(properties), thisVariable.getField(page), index))));
    Variable blocksBuilder = scope.declareVariable("blocksBuilder", body, invokeStatic(ImmutableList.class, "builder", ImmutableList.Builder.class));
    Variable iterator = scope.createTempVariable(int.class);
    ForLoop forLoop = new ForLoop("for (iterator = 0; iterator < this.blockBuilders.size(); iterator ++) blockBuildersBuilder.add(this.blockBuilders.get(iterator).builder();").initialize(iterator.set(constantInt(0))).condition(lessThan(iterator, constantInt(blockBuilderSize))).update(iterator.increment()).body(new BytecodeBlock().append(blocksBuilder.invoke("add", ImmutableList.Builder.class, thisVariable.getField(blockBuilders).invoke("get", Object.class, iterator).cast(BlockBuilder.class).invoke("build", Block.class).cast(Object.class)).pop()));
    body.append(forLoop).comment("result = blockBuildersBuilder.build(); return true").append(thisVariable.setField(result, blocksBuilder.invoke("build", ImmutableList.class))).push(true).retBoolean();
    return method;
}
Also used : IfStatement(com.facebook.presto.bytecode.control.IfStatement) Variable(com.facebook.presto.bytecode.Variable) Scope(com.facebook.presto.bytecode.Scope) ForLoop(com.facebook.presto.bytecode.control.ForLoop) MethodDefinition(com.facebook.presto.bytecode.MethodDefinition) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) ImmutableList(com.google.common.collect.ImmutableList) BlockBuilder(com.facebook.presto.common.block.BlockBuilder) CacheBuilder(com.google.common.cache.CacheBuilder) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) Block(com.facebook.presto.common.block.Block)

Aggregations

Variable (com.facebook.presto.bytecode.Variable)19 ForLoop (com.facebook.presto.bytecode.control.ForLoop)19 IfStatement (com.facebook.presto.bytecode.control.IfStatement)19 BytecodeBlock (com.facebook.presto.bytecode.BytecodeBlock)18 MethodDefinition (com.facebook.presto.bytecode.MethodDefinition)15 Parameter (com.facebook.presto.bytecode.Parameter)14 Scope (com.facebook.presto.bytecode.Scope)14 Block (com.facebook.presto.common.block.Block)8 Block (com.facebook.presto.spi.block.Block)8 ImmutableList (com.google.common.collect.ImmutableList)8 BytecodeNode (com.facebook.presto.bytecode.BytecodeNode)7 DictionaryBlock (com.facebook.presto.spi.block.DictionaryBlock)6 LazyBlock (com.facebook.presto.spi.block.LazyBlock)6 RunLengthEncodedBlock (com.facebook.presto.spi.block.RunLengthEncodedBlock)6 ClassDefinition (com.facebook.presto.bytecode.ClassDefinition)5 BytecodeExpression (com.facebook.presto.bytecode.expression.BytecodeExpression)5 VariableInstruction.incrementVariable (com.facebook.presto.bytecode.instruction.VariableInstruction.incrementVariable)5 List (java.util.List)5 CallSiteBinder (com.facebook.presto.bytecode.CallSiteBinder)4 BlockBuilder (com.facebook.presto.common.block.BlockBuilder)4