use of com.facebook.presto.bytecode.Variable in project presto by prestodb.
the class StateCompiler method generateGroupedStateClass.
private static <T> Class<? extends T> generateGroupedStateClass(Class<T> clazz, Map<String, Type> fieldTypes, DynamicClassLoader classLoader) {
ClassDefinition definition = new ClassDefinition(a(PUBLIC, FINAL), makeClassName("Grouped" + clazz.getSimpleName()), type(AbstractGroupedAccumulatorState.class), type(clazz), type(GroupedAccumulator.class));
FieldDefinition instanceSize = generateInstanceSize(definition);
List<StateField> fields = enumerateFields(clazz, fieldTypes);
// Create constructor
MethodDefinition constructor = definition.declareConstructor(a(PUBLIC));
constructor.getBody().append(constructor.getThis()).invokeConstructor(AbstractGroupedAccumulatorState.class);
// Create ensureCapacity
MethodDefinition ensureCapacity = definition.declareMethod(a(PUBLIC), "ensureCapacity", type(void.class), arg("size", long.class));
// Generate fields, constructor, and ensureCapacity
List<FieldDefinition> fieldDefinitions = new ArrayList<>();
for (StateField field : fields) {
fieldDefinitions.add(generateGroupedField(definition, constructor, ensureCapacity, field));
}
constructor.getBody().ret();
ensureCapacity.getBody().ret();
// Generate getEstimatedSize
MethodDefinition getEstimatedSize = definition.declareMethod(a(PUBLIC), "getEstimatedSize", type(long.class));
BytecodeBlock body = getEstimatedSize.getBody();
Variable size = getEstimatedSize.getScope().declareVariable(long.class, "size");
// initialize size to the size of the instance
body.append(size.set(getStatic(instanceSize)));
// add field to size
for (FieldDefinition field : fieldDefinitions) {
body.append(size.set(add(size, getEstimatedSize.getThis().getField(field).invoke("sizeOf", long.class))));
}
// return size
body.append(size.ret());
return defineClass(definition, clazz, classLoader);
}
use of com.facebook.presto.bytecode.Variable in project presto by prestodb.
the class PageProcessorCompiler method getBytecodeFilterOnRLE.
private static BytecodeBlock getBytecodeFilterOnRLE(Parameter session, Scope scope, Variable blockVariable) {
Variable positionCount = scope.getVariable("positionCount");
Variable thisVariable = scope.getThis();
BytecodeBlock ifFilterOnRLEBlock = new BytecodeBlock();
Variable rleBlock = scope.declareVariable("rleBlock", ifFilterOnRLEBlock, blockVariable.cast(RunLengthEncodedBlock.class));
Variable rleValue = scope.declareVariable("rleValue", ifFilterOnRLEBlock, rleBlock.invoke("getValue", Block.class));
ifFilterOnRLEBlock.append(new IfStatement().condition(invokeFilter(thisVariable, session, singletonList(rleValue), constantInt(0))).ifTrue(invokeStatic(IntStream.class, "range", IntStream.class, constantInt(0), positionCount).invoke("toArray", int[].class).ret()).ifFalse(newArray(type(int[].class), constantInt(0)).ret()));
return ifFilterOnRLEBlock;
}
use of com.facebook.presto.bytecode.Variable in project presto by prestodb.
the class PageProcessorCompiler method generateFilterPageMethod.
private void generateFilterPageMethod(ClassDefinition classDefinition, RowExpression filter) {
Parameter session = arg("session", ConnectorSession.class);
Parameter page = arg("page", Page.class);
MethodDefinition method = classDefinition.declareMethod(a(PUBLIC), "filterPage", type(int[].class), session, page);
method.comment("Filter: %s rows in the page", filter.toString());
Scope scope = method.getScope();
Variable thisVariable = method.getThis();
BytecodeBlock body = method.getBody();
Variable positionCount = scope.declareVariable("positionCount", body, page.invoke("getPositionCount", int.class));
Variable selectedPositions = scope.declareVariable("selectedPositions", body, newArray(type(int[].class), positionCount));
Variable selectedCount = scope.declareVariable("selectedCount", body, constantInt(0));
Variable position = scope.declareVariable(int.class, "position");
List<Integer> filterChannels = getInputChannels(filter);
// extract block variables
ImmutableList.Builder<Variable> blockVariablesBuilder = ImmutableList.builder();
for (int channel : filterChannels) {
Variable blockVariable = scope.declareVariable("block_" + channel, body, page.invoke("getBlock", Block.class, constantInt(channel)));
blockVariablesBuilder.add(blockVariable);
}
List<Variable> blockVariables = blockVariablesBuilder.build();
if (filterChannels.size() == 1 && determinismEvaluator.isDeterministic(filter)) {
BytecodeBlock ifFilterOnDictionaryBlock = getBytecodeFilterOnDictionary(session, scope, blockVariables.get(0));
BytecodeBlock ifFilterOnRLEBlock = getBytecodeFilterOnRLE(session, scope, blockVariables.get(0));
body.append(new IfStatement().condition(blockVariables.get(0).instanceOf(DictionaryBlock.class)).ifTrue(ifFilterOnDictionaryBlock));
body.append(new IfStatement().condition(blockVariables.get(0).instanceOf(RunLengthEncodedBlock.class)).ifTrue(ifFilterOnRLEBlock));
}
body.append(new ForLoop().initialize(position.set(constantInt(0))).condition(lessThan(position, positionCount)).update(position.increment()).body(new IfStatement().condition(invokeFilter(thisVariable, session, blockVariables, position)).ifTrue(new BytecodeBlock().append(selectedPositions.setElement(selectedCount, position)).append(selectedCount.increment()))));
body.append(invokeStatic(Arrays.class, "copyOf", int[].class, selectedPositions, selectedCount).ret());
}
use of com.facebook.presto.bytecode.Variable in project presto by prestodb.
the class PageProcessorCompiler method getBytecodeFilterOnDictionary.
private static BytecodeBlock getBytecodeFilterOnDictionary(Parameter session, Scope scope, Variable blockVariable) {
Variable position = scope.getVariable("position");
Variable positionCount = scope.getVariable("positionCount");
Variable selectedCount = scope.getVariable("selectedCount");
Variable selectedPositions = scope.getVariable("selectedPositions");
Variable thisVariable = scope.getThis();
BytecodeExpression inputFilterDictionary = thisVariable.getField("inputFilterDictionary", Block.class);
BytecodeExpression filterResult = thisVariable.getField("filterResult", boolean[].class);
BytecodeBlock ifFilterOnDictionaryBlock = new BytecodeBlock();
Variable dictionaryBlock = scope.declareVariable("dictionaryBlock", ifFilterOnDictionaryBlock, blockVariable.cast(DictionaryBlock.class));
Variable dictionary = scope.declareVariable("dictionary", ifFilterOnDictionaryBlock, dictionaryBlock.invoke("getDictionary", Block.class));
Variable dictionaryPositionCount = scope.declareVariable("dictionaryPositionCount", ifFilterOnDictionaryBlock, dictionary.invoke("getPositionCount", int.class));
Variable selectedDictionaryPositions = scope.declareVariable("selectedDictionaryPositions", ifFilterOnDictionaryBlock, newArray(type(boolean[].class), dictionaryPositionCount));
// if cached value is available use it else filter dictionary and cache it
ifFilterOnDictionaryBlock.append(new IfStatement().condition(equal(dictionary, inputFilterDictionary)).ifTrue(selectedDictionaryPositions.set(filterResult)).ifFalse(new BytecodeBlock().append(new ForLoop().initialize(position.set(constantInt(0))).condition(lessThan(position, dictionaryPositionCount)).update(position.increment()).body(selectedDictionaryPositions.setElement(position, invokeFilter(thisVariable, session, singletonList(dictionary), position)))).append(thisVariable.setField("inputFilterDictionary", dictionary)).append(thisVariable.setField("filterResult", selectedDictionaryPositions))));
// create selected positions
ifFilterOnDictionaryBlock.append(new ForLoop().initialize(position.set(constantInt(0))).condition(lessThan(position, positionCount)).update(position.increment()).body(new IfStatement().condition(selectedDictionaryPositions.getElement(dictionaryBlock.invoke("getId", int.class, position))).ifTrue(new BytecodeBlock().append(selectedPositions.setElement(selectedCount, position)).append(selectedCount.increment()))));
// return selectedPositions
ifFilterOnDictionaryBlock.append(invokeStatic(Arrays.class, "copyOf", int[].class, selectedPositions, selectedCount).ret());
return ifFilterOnDictionaryBlock;
}
use of com.facebook.presto.bytecode.Variable in project presto by prestodb.
the class PageProcessorCompiler method generateProcessColumnarMethod.
private static void generateProcessColumnarMethod(ClassDefinition classDefinition, List<RowExpression> projections, List<MethodDefinition> projectColumnarMethods) {
Parameter session = arg("session", ConnectorSession.class);
Parameter page = arg("page", Page.class);
Parameter types = arg("types", List.class);
MethodDefinition method = classDefinition.declareMethod(a(PUBLIC), "processColumnar", type(Page.class), session, page, types);
Scope scope = method.getScope();
BytecodeBlock body = method.getBody();
Variable thisVariable = method.getThis();
Variable selectedPositions = scope.declareVariable("selectedPositions", body, thisVariable.invoke("filterPage", int[].class, session, page));
Variable cardinality = scope.declareVariable("cardinality", body, selectedPositions.length());
body.comment("if no rows selected return null").append(new IfStatement().condition(equal(cardinality, constantInt(0))).ifTrue(constantNull(Page.class).ret()));
if (projections.isEmpty()) {
// if no projections, return new page with selected rows
body.append(newInstance(Page.class, cardinality, newArray(type(Block[].class), 0)).ret());
return;
}
Variable pageBuilder = scope.declareVariable("pageBuilder", body, newInstance(PageBuilder.class, cardinality, types));
Variable outputBlocks = scope.declareVariable("outputBlocks", body, newArray(type(Block[].class), projections.size()));
for (int projectionIndex = 0; projectionIndex < projections.size(); projectionIndex++) {
List<BytecodeExpression> params = ImmutableList.<BytecodeExpression>builder().add(session).add(page).add(selectedPositions).add(pageBuilder).add(constantInt(projectionIndex)).build();
body.append(outputBlocks.setElement(projectionIndex, thisVariable.invoke(projectColumnarMethods.get(projectionIndex), params)));
}
// create new page from outputBlocks
body.append(newInstance(Page.class, cardinality, outputBlocks).ret());
}
Aggregations