use of com.facebook.presto.bytecode.control.ForLoop 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();
}
use of com.facebook.presto.bytecode.control.ForLoop in project presto by prestodb.
the class PageProcessorCompiler method generateGetNonLazyPageMethod.
private static void generateGetNonLazyPageMethod(ClassDefinition classDefinition, RowExpression filter, List<RowExpression> projections) {
Parameter page = arg("page", Page.class);
MethodDefinition method = classDefinition.declareMethod(a(PRIVATE), "getNonLazyPage", type(Page.class), page);
Scope scope = method.getScope();
BytecodeBlock body = method.getBody();
List<Integer> allInputChannels = getInputChannels(concat(projections, ImmutableList.of(filter)));
if (allInputChannels.isEmpty()) {
body.append(page.ret());
return;
}
Variable index = scope.declareVariable(int.class, "index");
Variable channelCount = scope.declareVariable("channelCount", body, page.invoke("getChannelCount", int.class));
Variable blocks = scope.declareVariable("blocks", body, newArray(type(Block[].class), channelCount));
Variable inputBlock = scope.declareVariable(Block.class, "inputBlock");
Variable positionCount = scope.declareVariable("positionCount", body, page.invoke("getPositionCount", int.class));
Variable createNewPage = scope.declareVariable("createNewPage", body, constantFalse());
ForLoop forLoop = new ForLoop().initialize(index.set(constantInt(0))).condition(lessThan(index, channelCount)).update(index.increment()).body(new BytecodeBlock().append(inputBlock.set(page.invoke("getBlock", Block.class, index))).append(new IfStatement().condition(inputBlock.instanceOf(LazyBlock.class)).ifTrue(new BytecodeBlock().append(blocks.setElement(index, inputBlock.cast(LazyBlock.class).invoke("getBlock", Block.class))).append(createNewPage.set(constantTrue()))).ifFalse(blocks.setElement(index, inputBlock))));
body.append(forLoop);
body.append(new IfStatement().condition(createNewPage).ifTrue(page.set(newInstance(Page.class, positionCount, blocks))));
body.append(page.ret());
}
use of com.facebook.presto.bytecode.control.ForLoop in project presto by prestodb.
the class PageProcessorCompiler method generateProjectColumnarMethod.
private static MethodDefinition generateProjectColumnarMethod(ClassDefinition classDefinition, CallSiteBinder callSiteBinder, String methodName, RowExpression projection, MethodDefinition projectionMethod) {
Parameter session = arg("session", ConnectorSession.class);
Parameter page = arg("page", Page.class);
Parameter selectedPositions = arg("selectedPositions", int[].class);
Parameter pageBuilder = arg("pageBuilder", PageBuilder.class);
Parameter projectionIndex = arg("projectionIndex", int.class);
List<Parameter> params = ImmutableList.<Parameter>builder().add(session).add(page).add(selectedPositions).add(pageBuilder).add(projectionIndex).build();
MethodDefinition method = classDefinition.declareMethod(a(PRIVATE), methodName, type(Block.class), params);
BytecodeBlock body = method.getBody();
Scope scope = method.getScope();
Variable thisVariable = method.getThis();
ImmutableList.Builder<Variable> builder = ImmutableList.builder();
for (int channel : getInputChannels(projection)) {
Variable blockVariable = scope.declareVariable("block_" + channel, body, page.invoke("getBlock", Block.class, constantInt(channel)));
builder.add(blockVariable);
}
List<Variable> inputs = builder.build();
Variable positionCount = scope.declareVariable("positionCount", body, page.invoke("getPositionCount", int.class));
Variable position = scope.declareVariable("position", body, constantInt(0));
Variable cardinality = scope.declareVariable("cardinality", body, selectedPositions.length());
Variable outputBlock = scope.declareVariable(Block.class, "outputBlock");
Variable blockBuilder = scope.declareVariable("blockBuilder", body, pageBuilder.invoke("getBlockBuilder", BlockBuilder.class, projectionIndex));
Variable type = scope.declareVariable("type", body, pageBuilder.invoke("getType", Type.class, projectionIndex));
BytecodeBlock projectBlock = new BytecodeBlock().append(new ForLoop().initialize(position.set(constantInt(0))).condition(lessThan(position, cardinality)).update(position.increment()).body(invokeProject(thisVariable, session, inputs, selectedPositions.getElement(position), pageBuilder, projectionIndex, projectionMethod))).append(outputBlock.set(blockBuilder.invoke("build", Block.class)));
if (isIdentityExpression(projection)) {
// if nothing is filtered out, copy the entire block, else project it
body.append(new IfStatement().condition(equal(cardinality, positionCount)).ifTrue(new BytecodeBlock().append(inputs.get(0).invoke("assureLoaded", void.class)).append(outputBlock.set(inputs.get(0)))).ifFalse(projectBlock));
} else if (isConstantExpression(projection)) {
// if projection is a constant, create RLE block of constant expression with cardinality positions
ConstantExpression constantExpression = (ConstantExpression) projection;
verify(getInputChannels(projection).isEmpty());
BytecodeExpression value = loadConstant(callSiteBinder, constantExpression.getValue(), Object.class);
body.append(outputBlock.set(invokeStatic(RunLengthEncodedBlock.class, "create", Block.class, type, value, cardinality)));
} else {
body.append(projectBlock);
}
body.append(outputBlock.ret());
return method;
}
use of com.facebook.presto.bytecode.control.ForLoop in project presto by prestodb.
the class AccumulatorCompiler method generateInputForLoop.
private static BytecodeBlock generateInputForLoop(List<FieldDefinition> stateField, List<ParameterMetadata> parameterMetadatas, MethodHandle inputFunction, Scope scope, List<Variable> parameterVariables, List<Class> lambdaInterfaces, List<FieldDefinition> lambdaProviderFields, Variable masksBlock, CallSiteBinder callSiteBinder, boolean grouped) {
// For-loop over rows
Variable page = scope.getVariable("page");
Variable positionVariable = scope.declareVariable(int.class, "position");
Variable rowsVariable = scope.declareVariable(int.class, "rows");
BytecodeBlock block = new BytecodeBlock().append(page).invokeVirtual(Page.class, "getPositionCount", int.class).putVariable(rowsVariable).initializeVariable(positionVariable);
BytecodeNode loopBody = generateInvokeInputFunction(scope, stateField, positionVariable, parameterVariables, parameterMetadatas, lambdaInterfaces, lambdaProviderFields, inputFunction, callSiteBinder, grouped);
// Wrap with null checks
List<Boolean> nullable = new ArrayList<>();
for (ParameterMetadata metadata : parameterMetadatas) {
switch(metadata.getParameterType()) {
case INPUT_CHANNEL:
case BLOCK_INPUT_CHANNEL:
nullable.add(false);
break;
case NULLABLE_BLOCK_INPUT_CHANNEL:
nullable.add(true);
break;
// do nothing
default:
}
}
checkState(nullable.size() == parameterVariables.size(), "Number of parameters does not match");
for (int i = 0; i < parameterVariables.size(); i++) {
if (!nullable.get(i)) {
Variable variableDefinition = parameterVariables.get(i);
loopBody = new IfStatement("if(!%s.isNull(position))", variableDefinition.getName()).condition(new BytecodeBlock().getVariable(variableDefinition).getVariable(positionVariable).invokeInterface(Block.class, "isNull", boolean.class, int.class)).ifFalse(loopBody);
}
}
loopBody = new IfStatement("if(testMask(%s, position))", masksBlock.getName()).condition(new BytecodeBlock().getVariable(masksBlock).getVariable(positionVariable).invokeStatic(CompilerOperations.class, "testMask", boolean.class, Block.class, int.class)).ifTrue(loopBody);
BytecodeNode forLoop = new ForLoop().initialize(new BytecodeBlock().putVariable(positionVariable, 0)).condition(new BytecodeBlock().getVariable(positionVariable).getVariable(rowsVariable).invokeStatic(CompilerOperations.class, "lessThan", boolean.class, int.class, int.class)).update(new BytecodeBlock().incrementVariable(positionVariable, (byte) 1)).body(loopBody);
for (int i = 0; i < parameterVariables.size(); i++) {
if (!nullable.get(i)) {
Variable variableDefinition = parameterVariables.get(i);
forLoop = new IfStatement("if(!(%s instanceof RunLengthEncodedBlock && %s.isNull(0)))", variableDefinition.getName(), variableDefinition.getName()).condition(and(variableDefinition.instanceOf(RunLengthEncodedBlock.class), variableDefinition.invoke("isNull", boolean.class, constantInt(0)))).ifFalse(forLoop);
}
}
// Skip input blocks that eliminate all input positions
forLoop = new IfStatement("if(!(%s instanceof RunLengthEncodedBlock && !testMask(%s, 0)))", masksBlock.getName(), masksBlock.getName()).condition(and(masksBlock.instanceOf(RunLengthEncodedBlock.class), not(invokeStatic(type(CompilerOperations.class), "testMask", type(boolean.class), ImmutableList.of(type(Block.class), type(int.class)), masksBlock, constantInt(0))))).ifFalse(forLoop);
block.append(new IfStatement("if(%s > 0)", rowsVariable.getName()).condition(new BytecodeBlock().getVariable(rowsVariable).push(0).invokeStatic(CompilerOperations.class, "greaterThan", boolean.class, int.class, int.class)).ifTrue(forLoop));
return block;
}
use of com.facebook.presto.bytecode.control.ForLoop in project presto by prestodb.
the class AccumulatorCompiler method generateBlockNonNullPositionForLoop.
// Generates a for-loop with a local variable named "position" defined, with the current position in the block,
// loopBody will only be executed for non-null positions in the Block
private static BytecodeBlock generateBlockNonNullPositionForLoop(Scope scope, Variable positionVariable, BytecodeBlock loopBody) {
Variable rowsVariable = scope.declareVariable(int.class, "rows");
Variable blockVariable = scope.getVariable("block");
BytecodeBlock block = new BytecodeBlock().append(blockVariable).invokeInterface(Block.class, "getPositionCount", int.class).putVariable(rowsVariable);
IfStatement ifStatement = new IfStatement("if(!block.isNull(position))").condition(new BytecodeBlock().append(blockVariable).append(positionVariable).invokeInterface(Block.class, "isNull", boolean.class, int.class)).ifFalse(loopBody);
block.append(new ForLoop().initialize(positionVariable.set(constantInt(0))).condition(new BytecodeBlock().append(positionVariable).append(rowsVariable).invokeStatic(CompilerOperations.class, "lessThan", boolean.class, int.class, int.class)).update(new BytecodeBlock().incrementVariable(positionVariable, (byte) 1)).body(ifStatement));
return block;
}
Aggregations