use of com.facebook.presto.bytecode.control.IfStatement in project presto by prestodb.
the class PageFunctionCompiler method generateCommonSubExpressionMethods.
private List<MethodDefinition> generateCommonSubExpressionMethods(ClassDefinition classDefinition, RowExpressionCompiler compiler, Map<Integer, Map<RowExpression, VariableReferenceExpression>> commonSubExpressionsByLevel, Map<VariableReferenceExpression, CommonSubExpressionFields> commonSubExpressionFieldsMap) {
ImmutableList.Builder<MethodDefinition> methods = ImmutableList.builder();
Parameter properties = arg("properties", SqlFunctionProperties.class);
Parameter page = arg("page", Page.class);
Parameter position = arg("position", int.class);
int startLevel = commonSubExpressionsByLevel.keySet().stream().reduce(Math::min).get();
int maxLevel = commonSubExpressionsByLevel.keySet().stream().reduce(Math::max).get();
for (int i = startLevel; i <= maxLevel; i++) {
if (commonSubExpressionsByLevel.containsKey(i)) {
for (Map.Entry<RowExpression, VariableReferenceExpression> entry : commonSubExpressionsByLevel.get(i).entrySet()) {
RowExpression cse = entry.getKey();
Class<?> type = Primitives.wrap(cse.getType().getJavaType());
VariableReferenceExpression cseVariable = entry.getValue();
CommonSubExpressionFields cseFields = commonSubExpressionFieldsMap.get(cseVariable);
MethodDefinition method = classDefinition.declareMethod(a(PRIVATE), "get" + cseVariable.getName(), type(cseFields.getResultType()), ImmutableList.<Parameter>builder().add(properties).add(page).add(position).build());
method.comment("cse: %s", cse);
Scope scope = method.getScope();
BytecodeBlock body = method.getBody();
Variable thisVariable = method.getThis();
declareBlockVariables(ImmutableList.of(cse), page, scope, body);
scope.declareVariable("wasNull", body, constantFalse());
IfStatement ifStatement = new IfStatement().condition(thisVariable.getField(cseFields.getEvaluatedField())).ifFalse(new BytecodeBlock().append(thisVariable).append(compiler.compile(cse, scope, Optional.empty())).append(boxPrimitiveIfNecessary(scope, type)).putField(cseFields.getResultField()).append(thisVariable.setField(cseFields.getEvaluatedField(), constantBoolean(true))));
body.append(ifStatement).append(thisVariable).getField(cseFields.getResultField()).retObject();
methods.add(method);
}
}
}
return methods.build();
}
use of com.facebook.presto.bytecode.control.IfStatement in project presto by prestodb.
the class RowConstructorCodeGenerator method generateExpression.
@Override
public BytecodeNode generateExpression(BytecodeGeneratorContext context, Type rowType, List<RowExpression> arguments, Optional<Variable> outputBlockVariable) {
BytecodeBlock block = new BytecodeBlock().setDescription("Constructor for " + rowType.toString());
CallSiteBinder binder = context.getCallSiteBinder();
Scope scope = context.getScope();
List<Type> types = rowType.getTypeParameters();
block.comment("Create new RowBlockBuilder; beginBlockEntry;");
Variable blockBuilder = scope.createTempVariable(BlockBuilder.class);
Variable singleRowBlockWriter = scope.createTempVariable(BlockBuilder.class);
block.append(blockBuilder.set(constantType(binder, rowType).invoke("createBlockBuilder", BlockBuilder.class, constantNull(BlockBuilderStatus.class), constantInt(1))));
block.append(singleRowBlockWriter.set(blockBuilder.invoke("beginBlockEntry", BlockBuilder.class)));
for (int i = 0; i < arguments.size(); ++i) {
Type fieldType = types.get(i);
Variable field = scope.createTempVariable(fieldType.getJavaType());
block.comment("Clean wasNull and Generate + " + i + "-th field of row");
block.append(context.wasNull().set(constantFalse()));
block.append(context.generate(arguments.get(i), Optional.empty()));
block.putVariable(field);
block.append(new IfStatement().condition(context.wasNull()).ifTrue(singleRowBlockWriter.invoke("appendNull", BlockBuilder.class).pop()).ifFalse(constantType(binder, fieldType).writeValue(singleRowBlockWriter, field).pop()));
}
block.comment("closeEntry; slice the SingleRowBlock; wasNull = false;");
block.append(blockBuilder.invoke("closeEntry", BlockBuilder.class).pop());
block.append(constantType(binder, rowType).invoke("getObject", Object.class, blockBuilder.cast(Block.class), constantInt(0)).cast(Block.class));
block.append(context.wasNull().set(constantFalse()));
outputBlockVariable.ifPresent(output -> block.append(generateWrite(context, rowType, output)));
return block;
}
use of com.facebook.presto.bytecode.control.IfStatement in project presto by prestodb.
the class JoinCompiler method generatePositionEqualsRowWithPageMethod.
private static void generatePositionEqualsRowWithPageMethod(ClassDefinition classDefinition, CallSiteBinder callSiteBinder, List<Type> joinChannelTypes, List<FieldDefinition> joinChannelFields) {
Parameter leftBlockIndex = arg("leftBlockIndex", int.class);
Parameter leftBlockPosition = arg("leftBlockPosition", int.class);
Parameter rightPosition = arg("rightPosition", int.class);
Parameter page = arg("page", Page.class);
Parameter rightChannels = arg("rightChannels", int[].class);
MethodDefinition positionEqualsRowMethod = classDefinition.declareMethod(a(PUBLIC), "positionEqualsRow", type(boolean.class), leftBlockIndex, leftBlockPosition, rightPosition, page, rightChannels);
Variable thisVariable = positionEqualsRowMethod.getThis();
BytecodeBlock body = positionEqualsRowMethod.getBody();
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 = page.invoke("getBlock", Block.class, rightChannels.getElement(index));
body.append(new IfStatement().condition(typeEquals(type, leftBlock, leftBlockPosition, rightBlock, rightPosition)).ifFalse(constantFalse().ret()));
}
body.append(constantTrue().ret());
}
use of com.facebook.presto.bytecode.control.IfStatement in project presto by prestodb.
the class JoinCompiler method typeEquals.
private static BytecodeNode typeEquals(BytecodeExpression type, BytecodeExpression leftBlock, BytecodeExpression leftBlockPosition, BytecodeExpression rightBlock, BytecodeExpression rightBlockPosition) {
IfStatement ifStatement = new IfStatement();
ifStatement.condition().append(leftBlock.invoke("isNull", boolean.class, leftBlockPosition)).append(rightBlock.invoke("isNull", boolean.class, rightBlockPosition)).append(OpCode.IOR);
ifStatement.ifTrue().append(leftBlock.invoke("isNull", boolean.class, leftBlockPosition)).append(rightBlock.invoke("isNull", boolean.class, rightBlockPosition)).append(OpCode.IAND);
ifStatement.ifFalse().append(typeEqualsIgnoreNulls(type, leftBlock, leftBlockPosition, rightBlock, rightBlockPosition));
return ifStatement;
}
use of com.facebook.presto.bytecode.control.IfStatement in project presto by prestodb.
the class OrCodeGenerator method generateExpression.
@Override
public BytecodeNode generateExpression(BytecodeGeneratorContext generator, Type returnType, List<RowExpression> arguments, Optional<Variable> outputBlockVariable) {
Preconditions.checkArgument(arguments.size() == 2);
// We flatten the AND here.
Deque<RowExpression> stack = new ArrayDeque<>();
stack.push(arguments.get(1));
stack.push(arguments.get(0));
ImmutableList.Builder<RowExpression> flattenedArgs = ImmutableList.builder();
do {
RowExpression operand = stack.pop();
if (operand instanceof SpecialFormExpression && ((SpecialFormExpression) operand).getForm() == SpecialFormExpression.Form.OR) {
stack.push(((SpecialFormExpression) operand).getArguments().get(1));
stack.push(((SpecialFormExpression) operand).getArguments().get(0));
} else {
flattenedArgs.add(operand);
}
} while (!stack.isEmpty());
BytecodeBlock block = new BytecodeBlock().comment("OR").setDescription("OR");
LabelNode trueLabel = new LabelNode("true");
LabelNode endLabel = new LabelNode("end");
Variable wasNull = generator.wasNull();
Variable hasNulls = generator.getScope().createTempVariable(boolean.class);
block.initializeVariable(hasNulls);
for (RowExpression expression : flattenedArgs.build()) {
block.comment("do { eval arg; if (wasNull) { hasNull = true; wasNull = false; } else if (true) goto ret_true; }").append(generator.generate(expression, Optional.empty()));
IfStatement ifOperandIsNull = new IfStatement("if left wasNulll...").condition(wasNull);
ifOperandIsNull.ifTrue().comment("clear the null flag and remember there was a null").putVariable(hasNulls, true).putVariable(wasNull, false).pop(boolean.class);
ifOperandIsNull.ifFalse().ifTrueGoto(trueLabel);
block.append(ifOperandIsNull);
}
// We evaluated all operands. So check if any of them was null
IfStatement ifHasNulls = new IfStatement("hasNulls is true");
ifHasNulls.condition().append(hasNulls);
ifHasNulls.ifTrue().comment("at least one of the arguments is null and none of them is true. So set wasNull to true").putVariable(wasNull, true).push(false);
ifHasNulls.ifFalse().push(false);
block.append(ifHasNulls).gotoLabel(endLabel);
block.visitLabel(trueLabel).comment("at least one of the args is true, clear wasNull and return true").push(true).gotoLabel(endLabel);
block.visitLabel(endLabel);
outputBlockVariable.ifPresent(output -> block.append(generateWrite(generator, returnType, output)));
return block;
}
Aggregations