use of com.facebook.presto.bytecode.BytecodeBlock in project presto by prestodb.
the class AbstractMinMaxBy method generateCombineMethod.
private void generateCombineMethod(ClassDefinition definition, CallSiteBinder binder, MethodHandle compareMethod, Type keyType, Type valueType, Class<?> stateClass) {
Parameter state = arg("state", stateClass);
Parameter otherState = arg("otherState", stateClass);
MethodDefinition method = definition.declareMethod(a(PUBLIC, STATIC), "combine", type(void.class), state, otherState);
if (keyType.equals(UNKNOWN)) {
method.getBody().ret();
return;
}
Class<?> keyJavaType = keyType.getJavaType();
BytecodeBlock ifBlock = new BytecodeBlock().append(state.invoke("setFirst", void.class, otherState.invoke("getFirst", keyJavaType))).append(state.invoke("setFirstNull", void.class, otherState.invoke("isFirstNull", boolean.class))).append(state.invoke("setSecondNull", void.class, otherState.invoke("isSecondNull", boolean.class)));
if (!valueType.equals(UNKNOWN)) {
ifBlock.append(state.invoke("setSecond", void.class, otherState.invoke("getSecond", valueType.getJavaType())));
}
method.getBody().append(new IfStatement().condition(or(state.invoke("isFirstNull", boolean.class), and(not(otherState.invoke("isFirstNull", boolean.class)), loadConstant(binder, compareMethod, MethodHandle.class).invoke("invokeExact", boolean.class, otherState.invoke("getFirst", keyJavaType), state.invoke("getFirst", keyJavaType))))).ifTrue(ifBlock)).ret();
}
use of com.facebook.presto.bytecode.BytecodeBlock in project presto by prestodb.
the class AccumulatorCompiler method generateInvokeInputFunction.
private static BytecodeBlock generateInvokeInputFunction(Scope scope, FieldDefinition stateField, Variable position, List<Variable> parameterVariables, List<ParameterMetadata> parameterMetadatas, MethodHandle inputFunction, CallSiteBinder callSiteBinder, boolean grouped) {
BytecodeBlock block = new BytecodeBlock();
if (grouped) {
generateSetGroupIdFromGroupIdsBlock(scope, stateField, block);
}
block.comment("Call input function with unpacked Block arguments");
Class<?>[] parameters = inputFunction.type().parameterArray();
int inputChannel = 0;
for (int i = 0; i < parameters.length; i++) {
ParameterMetadata parameterMetadata = parameterMetadatas.get(i);
switch(parameterMetadata.getParameterType()) {
case STATE:
block.append(scope.getThis().getField(stateField));
break;
case BLOCK_INDEX:
block.getVariable(position);
break;
case BLOCK_INPUT_CHANNEL:
case NULLABLE_BLOCK_INPUT_CHANNEL:
block.getVariable(parameterVariables.get(inputChannel));
inputChannel++;
break;
case INPUT_CHANNEL:
BytecodeBlock getBlockBytecode = new BytecodeBlock().getVariable(parameterVariables.get(inputChannel));
pushStackType(scope, block, parameterMetadata.getSqlType(), getBlockBytecode, parameters[i], callSiteBinder);
inputChannel++;
break;
default:
throw new IllegalArgumentException("Unsupported parameter type: " + parameterMetadata.getParameterType());
}
}
block.append(invoke(callSiteBinder.bind(inputFunction), "input"));
return block;
}
use of com.facebook.presto.bytecode.BytecodeBlock in project presto by prestodb.
the class AccumulatorCompiler method generateAddIntermediateAsCombine.
private static void generateAddIntermediateAsCombine(ClassDefinition definition, FieldDefinition stateField, FieldDefinition stateSerializerField, FieldDefinition stateFactoryField, MethodHandle combineFunction, Class<?> singleStateClass, CallSiteBinder callSiteBinder, boolean grouped) {
MethodDefinition method = declareAddIntermediate(definition, grouped);
Scope scope = method.getScope();
BytecodeBlock body = method.getBody();
Variable thisVariable = method.getThis();
Variable block = scope.getVariable("block");
Variable scratchState = scope.declareVariable(singleStateClass, "scratchState");
Variable position = scope.declareVariable(int.class, "position");
body.comment("scratchState = stateFactory.createSingleState();").append(thisVariable.getField(stateFactoryField)).invokeInterface(AccumulatorStateFactory.class, "createSingleState", Object.class).checkCast(scratchState.getType()).putVariable(scratchState);
if (grouped) {
generateEnsureCapacity(scope, stateField, body);
}
BytecodeBlock loopBody = new BytecodeBlock();
if (grouped) {
Variable groupIdsBlock = scope.getVariable("groupIdsBlock");
loopBody.append(thisVariable.getField(stateField).invoke("setGroupId", void.class, groupIdsBlock.invoke("getGroupId", long.class, position)));
}
loopBody.append(thisVariable.getField(stateSerializerField).invoke("deserialize", void.class, block, position, scratchState.cast(Object.class)));
loopBody.comment("combine(state, scratchState)").append(thisVariable.getField(stateField)).append(scratchState).append(invoke(callSiteBinder.bind(combineFunction), "combine"));
if (grouped) {
// skip rows with null group id
IfStatement ifStatement = new IfStatement("if (!groupIdsBlock.isNull(position))").condition(not(scope.getVariable("groupIdsBlock").invoke("isNull", boolean.class, position))).ifTrue(loopBody);
loopBody = new BytecodeBlock().append(ifStatement);
}
body.append(generateBlockNonNullPositionForLoop(scope, position, loopBody)).ret();
}
use of com.facebook.presto.bytecode.BytecodeBlock in project presto by prestodb.
the class AccumulatorCompiler method generateBlockNonNullPositionForLoop.
// Generates a for-loop with a local variable named "position" defined, with the current position in the block,
// loopBody will only be executed for non-null positions in the Block
private static BytecodeBlock generateBlockNonNullPositionForLoop(Scope scope, Variable positionVariable, BytecodeBlock loopBody) {
Variable rowsVariable = scope.declareVariable(int.class, "rows");
Variable blockVariable = scope.getVariable("block");
BytecodeBlock block = new BytecodeBlock().append(blockVariable).invokeInterface(Block.class, "getPositionCount", int.class).putVariable(rowsVariable);
IfStatement ifStatement = new IfStatement("if(!block.isNull(position))").condition(new BytecodeBlock().append(blockVariable).append(positionVariable).invokeInterface(Block.class, "isNull", boolean.class, int.class)).ifFalse(loopBody);
block.append(new ForLoop().initialize(positionVariable.set(constantInt(0))).condition(new BytecodeBlock().append(positionVariable).append(rowsVariable).invokeStatic(CompilerOperations.class, "lessThan", boolean.class, int.class, int.class)).update(new BytecodeBlock().incrementVariable(positionVariable, (byte) 1)).body(ifStatement));
return block;
}
use of com.facebook.presto.bytecode.BytecodeBlock in project presto by prestodb.
the class AccumulatorCompiler method generateAddInput.
private static void generateAddInput(ClassDefinition definition, FieldDefinition stateField, FieldDefinition inputChannelsField, FieldDefinition maskChannelField, List<ParameterMetadata> parameterMetadatas, MethodHandle inputFunction, CallSiteBinder callSiteBinder, boolean grouped) {
ImmutableList.Builder<Parameter> parameters = ImmutableList.builder();
if (grouped) {
parameters.add(arg("groupIdsBlock", GroupByIdBlock.class));
}
Parameter page = arg("page", Page.class);
parameters.add(page);
MethodDefinition method = definition.declareMethod(a(PUBLIC), "addInput", type(void.class), parameters.build());
Scope scope = method.getScope();
BytecodeBlock body = method.getBody();
Variable thisVariable = method.getThis();
if (grouped) {
generateEnsureCapacity(scope, stateField, body);
}
List<Variable> parameterVariables = new ArrayList<>();
for (int i = 0; i < countInputChannels(parameterMetadatas); i++) {
parameterVariables.add(scope.declareVariable(Block.class, "block" + i));
}
Variable masksBlock = scope.declareVariable(Block.class, "masksBlock");
body.comment("masksBlock = maskChannel.map(page.blockGetter()).orElse(null);").append(thisVariable.getField(maskChannelField)).append(page).invokeStatic(type(AggregationUtils.class), "pageBlockGetter", type(Function.class, Integer.class, Block.class), type(Page.class)).invokeVirtual(Optional.class, "map", Optional.class, Function.class).pushNull().invokeVirtual(Optional.class, "orElse", Object.class, Object.class).checkCast(Block.class).putVariable(masksBlock);
// Get all parameter blocks
for (int i = 0; i < countInputChannels(parameterMetadatas); i++) {
body.comment("%s = page.getBlock(inputChannels.get(%d));", parameterVariables.get(i).getName(), i).append(page).append(thisVariable.getField(inputChannelsField)).push(i).invokeInterface(List.class, "get", Object.class, int.class).checkCast(Integer.class).invokeVirtual(Integer.class, "intValue", int.class).invokeVirtual(Page.class, "getBlock", Block.class, int.class).putVariable(parameterVariables.get(i));
}
BytecodeBlock block = generateInputForLoop(stateField, parameterMetadatas, inputFunction, scope, parameterVariables, masksBlock, callSiteBinder, grouped);
body.append(block);
body.ret();
}
Aggregations