use of com.facebook.presto.bytecode.instruction.LabelNode in project presto by prestodb.
the class InCodeGenerator method buildInCase.
private static BytecodeBlock buildInCase(BytecodeGeneratorContext generatorContext, Scope scope, Type type, LabelNode caseLabel, LabelNode matchLabel, LabelNode noMatchLabel, Collection<BytecodeNode> testValues, boolean checkForNulls) {
// caseWasNull is set to true the first time a null in `testValues` is encountered
Variable caseWasNull = null;
if (checkForNulls) {
caseWasNull = scope.createTempVariable(boolean.class);
}
BytecodeBlock caseBlock = new BytecodeBlock().visitLabel(caseLabel);
if (checkForNulls) {
caseBlock.putVariable(caseWasNull, false);
}
LabelNode elseLabel = new LabelNode("else");
BytecodeBlock elseBlock = new BytecodeBlock().visitLabel(elseLabel);
Variable wasNull = generatorContext.wasNull();
if (checkForNulls) {
elseBlock.append(wasNull.set(caseWasNull));
}
elseBlock.gotoLabel(noMatchLabel);
ScalarFunctionImplementation operator = generatorContext.getRegistry().getScalarFunctionImplementation(internalOperator(EQUAL, BOOLEAN, ImmutableList.of(type, type)));
Binding equalsFunction = generatorContext.getCallSiteBinder().bind(operator.getMethodHandle());
BytecodeNode elseNode = elseBlock;
for (BytecodeNode testNode : testValues) {
LabelNode testLabel = new LabelNode("test");
IfStatement test = new IfStatement();
test.condition().visitLabel(testLabel).dup(type.getJavaType()).append(testNode);
if (checkForNulls) {
IfStatement wasNullCheck = new IfStatement("if wasNull, set caseWasNull to true, clear wasNull, pop 2 values of type, and goto next test value");
wasNullCheck.condition(wasNull);
wasNullCheck.ifTrue(new BytecodeBlock().append(caseWasNull.set(constantTrue())).append(wasNull.set(constantFalse())).pop(type.getJavaType()).pop(type.getJavaType()).gotoLabel(elseLabel));
test.condition().append(wasNullCheck);
}
test.condition().append(invoke(equalsFunction, EQUAL.name()));
test.ifTrue().gotoLabel(matchLabel);
test.ifFalse(elseNode);
elseNode = test;
elseLabel = testLabel;
}
caseBlock.append(elseNode);
return caseBlock;
}
use of com.facebook.presto.bytecode.instruction.LabelNode in project presto by prestodb.
the class BytecodeUtils method generateInvocation.
public static BytecodeNode generateInvocation(Scope scope, String name, ScalarFunctionImplementation function, Optional<BytecodeNode> instance, List<BytecodeNode> arguments, Binding binding) {
MethodType methodType = binding.getType();
Class<?> returnType = methodType.returnType();
Class<?> unboxedReturnType = Primitives.unwrap(returnType);
LabelNode end = new LabelNode("end");
BytecodeBlock block = new BytecodeBlock().setDescription("invoke " + name);
List<Class<?>> stackTypes = new ArrayList<>();
if (function.getInstanceFactory().isPresent()) {
checkArgument(instance.isPresent());
}
// Index of current parameter in the MethodHandle
int currentParameterIndex = 0;
// Index of parameter (without @IsNull) in Presto function
int realParameterIndex = 0;
boolean boundInstance = false;
while (currentParameterIndex < methodType.parameterArray().length) {
Class<?> type = methodType.parameterArray()[currentParameterIndex];
stackTypes.add(type);
if (function.getInstanceFactory().isPresent() && !boundInstance) {
checkState(type.equals(function.getInstanceFactory().get().type().returnType()), "Mismatched type for instance parameter");
block.append(instance.get());
boundInstance = true;
} else if (type == ConnectorSession.class) {
block.append(scope.getVariable("session"));
} else {
block.append(arguments.get(realParameterIndex));
if (!function.getNullableArguments().get(realParameterIndex)) {
checkArgument(!Primitives.isWrapperType(type), "Non-nullable argument must not be primitive wrapper type");
block.append(ifWasNullPopAndGoto(scope, end, unboxedReturnType, Lists.reverse(stackTypes)));
} else {
if (function.getNullFlags().get(realParameterIndex)) {
if (type == Void.class) {
block.append(boxPrimitiveIfNecessary(scope, type));
}
block.append(scope.getVariable("wasNull"));
stackTypes.add(boolean.class);
currentParameterIndex++;
} else {
block.append(boxPrimitiveIfNecessary(scope, type));
}
block.append(scope.getVariable("wasNull").set(constantFalse()));
}
realParameterIndex++;
}
currentParameterIndex++;
}
block.append(invoke(binding, name));
if (function.isNullable()) {
block.append(unboxPrimitiveIfNecessary(scope, returnType));
}
block.visitLabel(end);
return block;
}
use of com.facebook.presto.bytecode.instruction.LabelNode in project presto by prestodb.
the class JoinCompiler method generateRowEqualsRowMethod.
private static void generateRowEqualsRowMethod(ClassDefinition classDefinition, CallSiteBinder callSiteBinder, List<Type> joinChannelTypes) {
Parameter leftPosition = arg("leftPosition", int.class);
Parameter leftPage = arg("leftPage", Page.class);
Parameter rightPosition = arg("rightPosition", int.class);
Parameter rightPage = arg("rightPage", Page.class);
MethodDefinition rowEqualsRowMethod = classDefinition.declareMethod(a(PUBLIC), "rowEqualsRow", type(boolean.class), leftPosition, leftPage, rightPosition, rightPage);
for (int index = 0; index < joinChannelTypes.size(); index++) {
BytecodeExpression type = constantType(callSiteBinder, joinChannelTypes.get(index));
BytecodeExpression leftBlock = leftPage.invoke("getBlock", Block.class, constantInt(index));
BytecodeExpression rightBlock = rightPage.invoke("getBlock", Block.class, constantInt(index));
LabelNode checkNextField = new LabelNode("checkNextField");
rowEqualsRowMethod.getBody().append(typeEquals(type, leftBlock, leftPosition, rightBlock, rightPosition)).ifTrueGoto(checkNextField).push(false).retBoolean().visitLabel(checkNextField);
}
rowEqualsRowMethod.getBody().push(true).retInt();
}
use of com.facebook.presto.bytecode.instruction.LabelNode 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