Пример #1
0
  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();
  }
Пример #2
0
  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();
  }