use of com.facebook.presto.bytecode.BytecodeNode in project presto by prestodb.
the class ArrayTransformFunction method generateTransform.
private static Class<?> generateTransform(Type inputType, Type outputType) {
CallSiteBinder binder = new CallSiteBinder();
Class<?> inputJavaType = Primitives.wrap(inputType.getJavaType());
Class<?> outputJavaType = Primitives.wrap(outputType.getJavaType());
ClassDefinition definition = new ClassDefinition(a(PUBLIC, FINAL), makeClassName("ArrayTransform"), type(Object.class));
definition.declareDefaultConstructor(a(PRIVATE));
// define createPageBuilder
MethodDefinition createPageBuilderMethod = definition.declareMethod(a(PUBLIC, STATIC), "createPageBuilder", type(PageBuilder.class));
createPageBuilderMethod.getBody().append(newInstance(PageBuilder.class, constantType(binder, new ArrayType(outputType)).invoke("getTypeParameters", List.class)).ret());
// define transform method
Parameter pageBuilder = arg("pageBuilder", PageBuilder.class);
Parameter block = arg("block", Block.class);
Parameter function = arg("function", UnaryFunctionInterface.class);
MethodDefinition method = definition.declareMethod(a(PUBLIC, STATIC), "transform", type(Block.class), ImmutableList.of(pageBuilder, 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 inputElement = scope.declareVariable(inputJavaType, "inputElement");
Variable outputElement = scope.declareVariable(outputJavaType, "outputElement");
// invoke block.getPositionCount()
body.append(positionCount.set(block.invoke("getPositionCount", int.class)));
// reset page builder if it is full
body.append(new IfStatement().condition(pageBuilder.invoke("isFull", boolean.class)).ifTrue(pageBuilder.invoke("reset", void.class)));
// get block builder
body.append(blockBuilder.set(pageBuilder.invoke("getBlockBuilder", BlockBuilder.class, constantInt(0))));
BytecodeNode loadInputElement;
if (!inputType.equals(UNKNOWN)) {
loadInputElement = new IfStatement().condition(block.invoke("isNull", boolean.class, position)).ifTrue(inputElement.set(constantNull(inputJavaType))).ifFalse(inputElement.set(constantType(binder, inputType).getValue(block, position).cast(inputJavaType)));
} else {
loadInputElement = new BytecodeBlock().append(inputElement.set(constantNull(inputJavaType)));
}
BytecodeNode writeOutputElement;
if (!outputType.equals(UNKNOWN)) {
writeOutputElement = new IfStatement().condition(equal(outputElement, constantNull(outputJavaType))).ifTrue(blockBuilder.invoke("appendNull", BlockBuilder.class).pop()).ifFalse(constantType(binder, outputType).writeValue(blockBuilder, outputElement.cast(outputType.getJavaType())));
} else {
writeOutputElement = new BytecodeBlock().append(blockBuilder.invoke("appendNull", BlockBuilder.class).pop());
}
body.append(new ForLoop().initialize(position.set(constantInt(0))).condition(lessThan(position, positionCount)).update(incrementVariable(position, (byte) 1)).body(new BytecodeBlock().append(loadInputElement).append(outputElement.set(function.invoke("apply", Object.class, inputElement.cast(Object.class)).cast(outputJavaType))).append(writeOutputElement)));
body.append(pageBuilder.invoke("declarePositions", void.class, positionCount));
body.append(blockBuilder.invoke("getRegion", Block.class, subtract(blockBuilder.invoke("getPositionCount", int.class), positionCount), positionCount).ret());
return defineClass(definition, Object.class, binder.getBindings(), ArrayTransformFunction.class.getClassLoader());
}
use of com.facebook.presto.bytecode.BytecodeNode in project presto by prestodb.
the class TestSetVariableBytecodeExpression method testGetField.
@Test
public void testGetField() throws Exception {
Function<Scope, BytecodeNode> nodeGenerator = scope -> {
Variable point = scope.declareVariable(Point.class, "point");
BytecodeExpression setPoint = point.set(newInstance(Point.class, constantInt(3), constantInt(7)));
assertEquals(setPoint.toString(), "point = new Point(3, 7);");
return new BytecodeBlock().append(setPoint).append(point.ret());
};
assertBytecodeNode(nodeGenerator, type(Point.class), new Point(3, 7));
}
use of com.facebook.presto.bytecode.BytecodeNode 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);
String tree = dumpBytecodeTree(classDefinition);
if (DUMP_BYTECODE_TREE.get()) {
System.out.println(tree);
}
ClassLoader classLoader = parentClassLoader.orElse(BytecodeExpressionAssertions.class.getClassLoader());
return classGenerator(classLoader).defineClass(classDefinition, Object.class).getMethod("test").invoke(null);
}
use of com.facebook.presto.bytecode.BytecodeNode in project presto by prestodb.
the class JoinCompiler method generateCompareSortChannelPositionsMethod.
private static void generateCompareSortChannelPositionsMethod(ClassDefinition classDefinition, CallSiteBinder callSiteBinder, List<Type> types, List<FieldDefinition> channelFields, Optional<Integer> sortChannel) {
Parameter leftBlockIndex = arg("leftBlockIndex", int.class);
Parameter leftBlockPosition = arg("leftBlockPosition", int.class);
Parameter rightBlockIndex = arg("rightBlockIndex", int.class);
Parameter rightBlockPosition = arg("rightBlockPosition", int.class);
MethodDefinition compareMethod = classDefinition.declareMethod(a(PUBLIC), "compareSortChannelPositions", type(int.class), leftBlockIndex, leftBlockPosition, rightBlockIndex, rightBlockPosition);
if (!sortChannel.isPresent()) {
compareMethod.getBody().append(newInstance(UnsupportedOperationException.class)).throwObject();
return;
}
Variable thisVariable = compareMethod.getThis();
int index = sortChannel.get();
BytecodeExpression type = constantType(callSiteBinder, types.get(index));
BytecodeExpression leftBlock = thisVariable.getField(channelFields.get(index)).invoke("get", Object.class, leftBlockIndex).cast(Block.class);
BytecodeExpression rightBlock = thisVariable.getField(channelFields.get(index)).invoke("get", Object.class, rightBlockIndex).cast(Block.class);
BytecodeNode comparison = type.invoke("compareTo", int.class, leftBlock, leftBlockPosition, rightBlock, rightBlockPosition).ret();
compareMethod.getBody().append(comparison);
}
use of com.facebook.presto.bytecode.BytecodeNode in project presto by prestodb.
the class JoinCompiler method generatePositionEqualsRowMethod.
private static void generatePositionEqualsRowMethod(ClassDefinition classDefinition, CallSiteBinder callSiteBinder, List<Type> joinChannelTypes, List<FieldDefinition> joinChannelFields, boolean ignoreNulls) {
Parameter leftBlockIndex = arg("leftBlockIndex", int.class);
Parameter leftBlockPosition = arg("leftBlockPosition", int.class);
Parameter rightPosition = arg("rightPosition", int.class);
Parameter rightPage = arg("rightPage", Page.class);
MethodDefinition positionEqualsRowMethod = classDefinition.declareMethod(a(PUBLIC), ignoreNulls ? "positionEqualsRowIgnoreNulls" : "positionEqualsRow", type(boolean.class), leftBlockIndex, leftBlockPosition, rightPosition, rightPage);
Variable thisVariable = positionEqualsRowMethod.getThis();
for (int index = 0; index < joinChannelTypes.size(); index++) {
BytecodeExpression type = constantType(callSiteBinder, joinChannelTypes.get(index));
BytecodeExpression leftBlock = thisVariable.getField(joinChannelFields.get(index)).invoke("get", Object.class, leftBlockIndex).cast(Block.class);
BytecodeExpression rightBlock = rightPage.invoke("getBlock", Block.class, constantInt(index));
BytecodeNode equalityCondition;
if (ignoreNulls) {
equalityCondition = typeEqualsIgnoreNulls(type, leftBlock, leftBlockPosition, rightBlock, rightPosition);
} else {
equalityCondition = typeEquals(type, leftBlock, leftBlockPosition, rightBlock, rightPosition);
}
LabelNode checkNextField = new LabelNode("checkNextField");
positionEqualsRowMethod.getBody().append(equalityCondition).ifTrueGoto(checkNextField).push(false).retBoolean().visitLabel(checkNextField);
}
positionEqualsRowMethod.getBody().push(true).retInt();
}
Aggregations