private void generateFilterAndProjectCursorMethod( ClassDefinition classDefinition, List<RowExpression> projections) { MethodDefinition filterAndProjectMethod = classDefinition.declareMethod( new CompilerContext(BOOTSTRAP_METHOD), a(PUBLIC), "filterAndProjectRowOriented", type(int.class), arg("cursor", RecordCursor.class), arg("pageBuilder", PageBuilder.class)); CompilerContext compilerContext = filterAndProjectMethod.getCompilerContext(); LocalVariableDefinition completedPositionsVariable = compilerContext.declareVariable(int.class, "completedPositions"); filterAndProjectMethod .getBody() .comment("int completedPositions = 0;") .putVariable(completedPositionsVariable, 0); // // for loop loop body // LabelNode done = new LabelNode("done"); ForLoopBuilder forLoop = ForLoop.forLoopBuilder(compilerContext) .initialize(NOP) .condition( new Block(compilerContext) .comment("completedPositions < 16384") .getVariable(completedPositionsVariable) .push(16384) .invokeStatic( CompilerOperations.class, "lessThan", boolean.class, int.class, int.class)) .update( new Block(compilerContext) .comment("completedPositions++") .incrementVariable(completedPositionsVariable, (byte) 1)); Block forLoopBody = new Block(compilerContext); forLoop.body(forLoopBody); forLoopBody .comment("if (pageBuilder.isFull()) break;") .append( new Block(compilerContext) .getVariable("pageBuilder") .invokeVirtual(PageBuilder.class, "isFull", boolean.class) .ifTrueGoto(done)); forLoopBody .comment("if (!cursor.advanceNextPosition()) break;") .append( new Block(compilerContext) .getVariable("cursor") .invokeInterface(RecordCursor.class, "advanceNextPosition", boolean.class) .ifFalseGoto(done)); // if (filter(cursor)) IfStatementBuilder ifStatement = new IfStatementBuilder(compilerContext); ifStatement.condition( new Block(compilerContext) .pushThis() .getVariable("cursor") .invokeVirtual( classDefinition.getType(), "filter", type(boolean.class), type(RecordCursor.class))); Block trueBlock = new Block(compilerContext); ifStatement.ifTrue(trueBlock); if (projections.isEmpty()) { // pageBuilder.declarePosition(); trueBlock .getVariable("pageBuilder") .invokeVirtual(PageBuilder.class, "declarePosition", void.class); } else { // project_43(block..., pageBuilder.getBlockBuilder(42))); for (int projectionIndex = 0; projectionIndex < projections.size(); projectionIndex++) { trueBlock.pushThis(); trueBlock.getVariable("cursor"); // pageBuilder.getBlockBuilder(0) trueBlock .getVariable("pageBuilder") .push(projectionIndex) .invokeVirtual(PageBuilder.class, "getBlockBuilder", BlockBuilder.class, int.class); // project(block..., blockBuilder) trueBlock.invokeVirtual( classDefinition.getType(), "project_" + projectionIndex, type(void.class), type(RecordCursor.class), type(BlockBuilder.class)); } } forLoopBody.append(ifStatement.build()); filterAndProjectMethod .getBody() .append(forLoop.build()) .visitLabel(done) .comment("return completedPositions;") .getVariable("completedPositions") .retInt(); }
private void generateFilterAndProjectRowOriented( ClassDefinition classDefinition, RowExpression filter, List<RowExpression> projections) { MethodDefinition filterAndProjectMethod = classDefinition.declareMethod( new CompilerContext(BOOTSTRAP_METHOD), a(PUBLIC), "filterAndProjectRowOriented", type(void.class), arg("page", com.facebook.presto.operator.Page.class), arg("pageBuilder", PageBuilder.class)); CompilerContext compilerContext = filterAndProjectMethod.getCompilerContext(); LocalVariableDefinition positionVariable = compilerContext.declareVariable(int.class, "position"); LocalVariableDefinition rowsVariable = compilerContext.declareVariable(int.class, "rows"); filterAndProjectMethod .getBody() .comment("int rows = page.getPositionCount();") .getVariable("page") .invokeVirtual(com.facebook.presto.operator.Page.class, "getPositionCount", int.class) .putVariable(rowsVariable); List<Integer> allInputChannels = getInputChannels(Iterables.concat(projections, ImmutableList.of(filter))); for (int channel : allInputChannels) { LocalVariableDefinition blockVariable = compilerContext.declareVariable( com.facebook.presto.spi.block.Block.class, "block_" + channel); filterAndProjectMethod .getBody() .comment("Block %s = page.getBlock(%s);", blockVariable.getName(), channel) .getVariable("page") .push(channel) .invokeVirtual( com.facebook.presto.operator.Page.class, "getBlock", com.facebook.presto.spi.block.Block.class, int.class) .putVariable(blockVariable); } // // for loop body // // for (position = 0; position < rows; position++) ForLoopBuilder forLoop = forLoopBuilder(compilerContext) .comment("for (position = 0; position < rows; position++)") .initialize(new Block(compilerContext).putVariable(positionVariable, 0)) .condition( new Block(compilerContext) .getVariable(positionVariable) .getVariable(rowsVariable) .invokeStatic( CompilerOperations.class, "lessThan", boolean.class, int.class, int.class)) .update(new Block(compilerContext).incrementVariable(positionVariable, (byte) 1)); Block forLoopBody = new Block(compilerContext); IfStatementBuilder ifStatement = new IfStatementBuilder(compilerContext).comment("if (filter(position, blocks...)"); Block condition = new Block(compilerContext); condition.pushThis(); condition.getVariable(positionVariable); List<Integer> filterInputChannels = getInputChannels(filter); for (int channel : filterInputChannels) { condition.getVariable("block_" + channel); } condition.invokeVirtual( classDefinition.getType(), "filter", type(boolean.class), ImmutableList.<ParameterizedType>builder() .add(type(int.class)) .addAll( nCopies( filterInputChannels.size(), type(com.facebook.presto.spi.block.Block.class))) .build()); ifStatement.condition(condition); Block trueBlock = new Block(compilerContext); if (projections.isEmpty()) { trueBlock .comment("pageBuilder.declarePosition()") .getVariable("pageBuilder") .invokeVirtual(PageBuilder.class, "declarePosition", void.class); } else { // pageBuilder.getBlockBuilder(0).append(block.getDouble(0); for (int projectionIndex = 0; projectionIndex < projections.size(); projectionIndex++) { trueBlock.comment( "project_%s(position, blocks..., pageBuilder.getBlockBuilder(%s))", projectionIndex, projectionIndex); trueBlock.pushThis(); List<Integer> projectionInputs = getInputChannels(projections.get(projectionIndex)); trueBlock.getVariable(positionVariable); for (int channel : projectionInputs) { trueBlock.getVariable("block_" + channel); } // pageBuilder.getBlockBuilder(0) trueBlock .getVariable("pageBuilder") .push(projectionIndex) .invokeVirtual(PageBuilder.class, "getBlockBuilder", BlockBuilder.class, int.class); // project(position, block_0, block_1, blockBuilder) trueBlock.invokeVirtual( classDefinition.getType(), "project_" + projectionIndex, type(void.class), ImmutableList.<ParameterizedType>builder() .add(type(int.class)) .addAll( nCopies( projectionInputs.size(), type(com.facebook.presto.spi.block.Block.class))) .add(type(BlockBuilder.class)) .build()); } } ifStatement.ifTrue(trueBlock); forLoopBody.append(ifStatement.build()); filterAndProjectMethod.getBody().append(forLoop.body(forLoopBody).build()); filterAndProjectMethod.getBody().ret(); }