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()); }
private static MethodDefinition generateProjectDictionaryMethod( ClassDefinition classDefinition, String methodName, RowExpression projection, MethodDefinition project, MethodDefinition projectColumnar) { 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(); List<Integer> inputChannels = getInputChannels(projection); if (inputChannels.size() != 1) { body.append(thisVariable.invoke(projectColumnar, params).ret()); return method; } Variable inputBlock = scope.declareVariable( "inputBlock", body, page.invoke( "getBlock", Block.class, constantInt(Iterables.getOnlyElement(inputChannels)))); IfStatement ifStatement = new IfStatement() .condition(inputBlock.instanceOf(DictionaryBlock.class)) .ifFalse(thisVariable.invoke(projectColumnar, params).ret()); body.append(ifStatement); Variable blockBuilder = scope.declareVariable( "blockBuilder", body, pageBuilder.invoke("getBlockBuilder", BlockBuilder.class, projectionIndex)); Variable cardinality = scope.declareVariable("cardinality", body, selectedPositions.length()); Variable dictionary = scope.declareVariable(Block.class, "dictionary"); Variable ids = scope.declareVariable(Slice.class, "ids"); Variable dictionaryCount = scope.declareVariable(int.class, "dictionaryCount"); Variable outputDictionary = scope.declareVariable(Block.class, "outputDictionary"); Variable outputIds = scope.declareVariable(int[].class, "outputIds"); BytecodeExpression inputDictionaries = thisVariable.getField("inputDictionaries", Block[].class); BytecodeExpression outputDictionaries = thisVariable.getField("outputDictionaries", Block[].class); Variable position = scope.declareVariable("position", body, constantInt(0)); body.comment("Extract dictionary and ids") .append( dictionary.set( inputBlock.cast(DictionaryBlock.class).invoke("getDictionary", Block.class))) .append(ids.set(inputBlock.cast(DictionaryBlock.class).invoke("getIds", Slice.class))) .append(dictionaryCount.set(dictionary.invoke("getPositionCount", int.class))); BytecodeBlock projectDictionary = new BytecodeBlock() .comment("Project dictionary") .append( new ForLoop() .initialize(position.set(constantInt(0))) .condition(lessThan(position, dictionaryCount)) .update(position.increment()) .body( invokeProject( thisVariable, session, ImmutableList.of(dictionary), position, pageBuilder, projectionIndex, project))) .append(outputDictionary.set(blockBuilder.invoke("build", Block.class))) .append(inputDictionaries.setElement(projectionIndex, dictionary)) .append(outputDictionaries.setElement(projectionIndex, outputDictionary)); body.comment("Use processed dictionary, if available, else project it") .append( new IfStatement() .condition(equal(inputDictionaries.getElement(projectionIndex), dictionary)) .ifTrue(outputDictionary.set(outputDictionaries.getElement(projectionIndex))) .ifFalse(projectDictionary)); body.comment("Filter ids") .append(outputIds.set(newArray(type(int[].class), cardinality))) .append( new ForLoop() .initialize(position.set(constantInt(0))) .condition(lessThan(position, cardinality)) .update(position.increment()) .body( outputIds.setElement( position, ids.invoke( "getInt", int.class, multiply( selectedPositions.getElement(position), constantInt(SIZE_OF_INT)))))); body.append( newInstance( DictionaryBlock.class, cardinality, outputDictionary, invokeStatic(Slices.class, "wrappedIntArray", Slice.class, outputIds)) .cast(Block.class) .ret()); return method; }