use of com.facebook.presto.bytecode.MethodDefinition in project presto by prestodb.
the class PageProcessorCompiler method generateConstructor.
private static void generateConstructor(ClassDefinition classDefinition, CachedInstanceBinder cachedInstanceBinder, int projectionCount) {
MethodDefinition constructorDefinition = classDefinition.declareConstructor(a(PUBLIC));
FieldDefinition inputDictionaries = classDefinition.declareField(a(PRIVATE, FINAL), "inputDictionaries", Block[].class);
FieldDefinition outputDictionaries = classDefinition.declareField(a(PRIVATE, FINAL), "outputDictionaries", Block[].class);
FieldDefinition inputFilterDictionary = classDefinition.declareField(a(PRIVATE), "inputFilterDictionary", Block.class);
FieldDefinition filterResult = classDefinition.declareField(a(PRIVATE), "filterResult", boolean[].class);
BytecodeBlock body = constructorDefinition.getBody();
Variable thisVariable = constructorDefinition.getThis();
body.comment("super();").append(thisVariable).invokeConstructor(Object.class);
body.append(thisVariable.setField(inputDictionaries, newArray(type(Block[].class), projectionCount)));
body.append(thisVariable.setField(outputDictionaries, newArray(type(Block[].class), projectionCount)));
body.append(thisVariable.setField(inputFilterDictionary, constantNull(Block.class)));
body.append(thisVariable.setField(filterResult, constantNull(boolean[].class)));
cachedInstanceBinder.generateInitializations(thisVariable, body);
body.ret();
}
use of com.facebook.presto.bytecode.MethodDefinition in project presto by prestodb.
the class PageProcessorCompiler method generateProcessColumnarDictionaryMethod.
private static void generateProcessColumnarDictionaryMethod(ClassDefinition classDefinition, List<RowExpression> projections, List<MethodDefinition> projectDictionaryMethods) {
Parameter session = arg("session", ConnectorSession.class);
Parameter page = arg("page", Page.class);
Parameter types = arg("types", List.class);
MethodDefinition method = classDefinition.declareMethod(a(PUBLIC), "processColumnarDictionary", 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());
Variable dictionarySourceIds = scope.declareVariable(type(Map.class, DictionaryId.class, DictionaryId.class), "dictionarySourceIds");
body.append(dictionarySourceIds.set(newInstance(type(HashMap.class, DictionaryId.class, DictionaryId.class))));
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;
}
// create PageBuilder
Variable pageBuilder = scope.declareVariable("pageBuilder", body, newInstance(PageBuilder.class, cardinality, types));
body.append(page.set(thisVariable.invoke("getNonLazyPage", Page.class, page)));
// create outputBlocks
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)).add(dictionarySourceIds).build();
body.append(outputBlocks.setElement(projectionIndex, thisVariable.invoke(projectDictionaryMethods.get(projectionIndex), params)));
}
body.append(newInstance(Page.class, cardinality, outputBlocks).ret());
}
use of com.facebook.presto.bytecode.MethodDefinition in project presto by prestodb.
the class MapFilterFunction method generateFilter.
private static MethodHandle generateFilter(Type keyType, Type valueType) {
CallSiteBinder binder = new CallSiteBinder();
MapType mapType = new MapType(keyType, valueType);
Class<?> keyJavaType = Primitives.wrap(keyType.getJavaType());
Class<?> valueJavaType = Primitives.wrap(valueType.getJavaType());
ClassDefinition definition = new ClassDefinition(a(PUBLIC, FINAL), makeClassName("MapFilter"), type(Object.class));
definition.declareDefaultConstructor(a(PRIVATE));
Parameter block = arg("block", Block.class);
Parameter function = arg("function", MethodHandle.class);
MethodDefinition method = definition.declareMethod(a(PUBLIC, STATIC), "filter", type(Block.class), ImmutableList.of(block, function));
BytecodeBlock body = method.getBody();
Scope scope = method.getScope();
Variable positionCount = scope.declareVariable(int.class, "positionCount");
Variable position = scope.declareVariable(int.class, "position");
Variable blockBuilder = scope.declareVariable(BlockBuilder.class, "blockBuilder");
Variable keyElement = scope.declareVariable(keyJavaType, "keyElement");
Variable valueElement = scope.declareVariable(valueJavaType, "valueElement");
Variable keep = scope.declareVariable(Boolean.class, "keep");
// invoke block.getPositionCount()
body.append(positionCount.set(block.invoke("getPositionCount", int.class)));
// create the interleaved block builder
body.append(blockBuilder.set(newInstance(InterleavedBlockBuilder.class, constantType(binder, mapType).invoke("getTypeParameters", List.class), newInstance(BlockBuilderStatus.class), positionCount)));
SqlTypeBytecodeExpression keySqlType = constantType(binder, keyType);
BytecodeNode loadKeyElement;
if (!keyType.equals(UNKNOWN)) {
// key element must be non-null
loadKeyElement = new BytecodeBlock().append(keyElement.set(keySqlType.getValue(block, position).cast(keyJavaType)));
} else {
loadKeyElement = new BytecodeBlock().append(keyElement.set(constantNull(keyJavaType)));
}
SqlTypeBytecodeExpression valueSqlType = constantType(binder, valueType);
BytecodeNode loadValueElement;
if (!valueType.equals(UNKNOWN)) {
loadValueElement = new IfStatement().condition(block.invoke("isNull", boolean.class, add(position, constantInt(1)))).ifTrue(valueElement.set(constantNull(valueJavaType))).ifFalse(valueElement.set(valueSqlType.getValue(block, add(position, constantInt(1))).cast(valueJavaType)));
} else {
loadValueElement = new BytecodeBlock().append(valueElement.set(constantNull(valueJavaType)));
}
body.append(new ForLoop().initialize(position.set(constantInt(0))).condition(lessThan(position, positionCount)).update(incrementVariable(position, (byte) 2)).body(new BytecodeBlock().append(loadKeyElement).append(loadValueElement).append(keep.set(function.invoke("invokeExact", Boolean.class, keyElement, valueElement))).append(new IfStatement("if (keep != null && keep) ...").condition(and(notEqual(keep, constantNull(Boolean.class)), keep.cast(boolean.class))).ifTrue(new BytecodeBlock().append(keySqlType.invoke("appendTo", void.class, block, position, blockBuilder)).append(valueSqlType.invoke("appendTo", void.class, block, add(position, constantInt(1)), blockBuilder))))));
body.append(blockBuilder.invoke("build", Block.class).ret());
Class<?> generatedClass = defineClass(definition, Object.class, binder.getBindings(), MapFilterFunction.class.getClassLoader());
return methodHandle(generatedClass, "filter", Block.class, MethodHandle.class);
}
use of com.facebook.presto.bytecode.MethodDefinition in project presto by prestodb.
the class TestArrayBytecodeExpressions method defineSetAndGetMethod.
private static MethodDefinition defineSetAndGetMethod(Class<?> aClass) {
Parameter arr = arg("arr", type(aClass));
Parameter index = arg("index", type(int.class));
Class<?> componentType = aClass.getComponentType();
Parameter value = arg("value", type(componentType));
MethodDefinition methodDefinition = classDefinition.declareMethod(a(PUBLIC, STATIC), "setAndGetMethod_" + componentType.getSimpleName(), type(componentType), arr, index, value);
methodDefinition.getBody().append(arr.setElement(index, value)).append(arr.getElement(index).ret());
return methodDefinition;
}
use of com.facebook.presto.bytecode.MethodDefinition in project presto by prestodb.
the class BytecodeExpressionAssertions method execute.
public static Object execute(Function<Scope, BytecodeNode> nodeGenerator, ParameterizedType returnType, Optional<ClassLoader> parentClassLoader) throws Exception {
ClassDefinition classDefinition = new ClassDefinition(a(PUBLIC, FINAL), makeClassName("Test"), type(Object.class));
MethodDefinition method = classDefinition.declareMethod(a(PUBLIC, STATIC), "test", returnType);
BytecodeNode node = nodeGenerator.apply(method.getScope());
method.getBody().append(node);
if (DUMP_BYTE_CODE_TREE) {
DumpBytecodeVisitor dumpBytecode = new DumpBytecodeVisitor(System.out);
dumpBytecode.visitClass(classDefinition);
}
DynamicClassLoader classLoader = new DynamicClassLoader(parentClassLoader.orElse(BytecodeExpressionAssertions.class.getClassLoader()));
ClassWriter cw = new SmartClassWriter(ClassInfoLoader.createClassInfoLoader(ImmutableList.of(classDefinition), classLoader));
classDefinition.visit(cw);
Class<?> clazz = classLoader.defineClass(classDefinition.getType().getJavaClassName(), cw.toByteArray());
return clazz.getMethod("test").invoke(null);
}
Aggregations