use of com.facebook.presto.spi.relation.RowExpression in project presto by prestodb.
the class LambdaBytecodeGenerator method generateLambda.
public static BytecodeNode generateLambda(BytecodeGeneratorContext context, List<RowExpression> captureExpressions, CompiledLambda compiledLambda, Class lambdaInterface) {
if (!lambdaInterface.isAnnotationPresent(FunctionalInterface.class)) {
// lambdaInterface is checked to be annotated with FunctionalInterface when generating ScalarFunctionImplementation
throw new VerifyException("lambda should be generated as class annotated with FunctionalInterface");
}
BytecodeBlock block = new BytecodeBlock().setDescription("Partial apply");
Scope scope = context.getScope();
Variable wasNull = scope.getVariable("wasNull");
// generate values to be captured
ImmutableList.Builder<BytecodeExpression> captureVariableBuilder = ImmutableList.builder();
for (RowExpression captureExpression : captureExpressions) {
Class<?> valueType = Primitives.wrap(captureExpression.getType().getJavaType());
Variable valueVariable = scope.createTempVariable(valueType);
block.append(context.generate(captureExpression, Optional.empty()));
block.append(boxPrimitiveIfNecessary(scope, valueType));
block.putVariable(valueVariable);
block.append(wasNull.set(constantFalse()));
captureVariableBuilder.add(valueVariable);
}
List<BytecodeExpression> captureVariables = ImmutableList.<BytecodeExpression>builder().add(scope.getThis(), scope.getVariable("properties")).addAll(captureVariableBuilder.build()).build();
Type instantiatedMethodAsmType = getMethodType(compiledLambda.getReturnType().getAsmType(), compiledLambda.getParameterTypes().stream().skip(// skip capture variables and ConnectorSession
captureExpressions.size() + 1).map(ParameterizedType::getAsmType).collect(toImmutableList()).toArray(new Type[0]));
block.append(invokeDynamic(LAMBDA_CAPTURE_METHOD, ImmutableList.of(getType(getSingleApplyMethod(lambdaInterface)), compiledLambda.getLambdaAsmHandle(), instantiatedMethodAsmType), "apply", type(lambdaInterface), captureVariables));
return block;
}
use of com.facebook.presto.spi.relation.RowExpression 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;
}
use of com.facebook.presto.spi.relation.RowExpression in project presto by prestodb.
the class InCodeGenerator method checkSwitchGenerationCase.
@VisibleForTesting
static SwitchGenerationCase checkSwitchGenerationCase(Type type, List<RowExpression> values) {
if (values.size() > 32) {
// * Benchmark shows performance of SET_CONTAINS is better at 50, but similar at 25.
return SwitchGenerationCase.SET_CONTAINS;
}
if (!(type instanceof IntegerType || type instanceof BigintType || type instanceof DateType)) {
return SwitchGenerationCase.HASH_SWITCH;
}
for (RowExpression expression : values) {
// Same argument applies for nulls.
if (!(expression instanceof ConstantExpression)) {
continue;
}
Object constant = ((ConstantExpression) expression).getValue();
if (constant == null) {
continue;
}
long longConstant = ((Number) constant).longValue();
if (longConstant < Integer.MIN_VALUE || longConstant > Integer.MAX_VALUE) {
return SwitchGenerationCase.HASH_SWITCH;
}
}
return SwitchGenerationCase.DIRECT_SWITCH;
}
use of com.facebook.presto.spi.relation.RowExpression in project presto by prestodb.
the class NullIfCodeGenerator method generateExpression.
@Override
public BytecodeNode generateExpression(BytecodeGeneratorContext generatorContext, Type returnType, List<RowExpression> arguments, Optional<Variable> outputBlockVariable) {
Scope scope = generatorContext.getScope();
RowExpression first = arguments.get(0);
RowExpression second = arguments.get(1);
LabelNode notMatch = new LabelNode("notMatch");
// push first arg on the stack
Variable firstValue = scope.createTempVariable(first.getType().getJavaType());
BytecodeBlock block = new BytecodeBlock().comment("check if first arg is null").append(generatorContext.generate(first, Optional.empty())).append(ifWasNullPopAndGoto(scope, notMatch, void.class)).dup(first.getType().getJavaType()).putVariable(firstValue);
Type firstType = first.getType();
Type secondType = second.getType();
// if (equal(cast(first as <common type>), cast(second as <common type>))
FunctionAndTypeManager functionAndTypeManager = generatorContext.getFunctionManager();
FunctionHandle equalFunction = functionAndTypeManager.resolveOperator(EQUAL, fromTypes(firstType, secondType));
FunctionMetadata equalFunctionMetadata = functionAndTypeManager.getFunctionMetadata(equalFunction);
JavaScalarFunctionImplementation equalsFunction = generatorContext.getFunctionManager().getJavaScalarFunctionImplementation(equalFunction);
BytecodeNode equalsCall = generatorContext.generateCall(EQUAL.name(), equalsFunction, ImmutableList.of(cast(generatorContext, firstValue, firstType, equalFunctionMetadata.getArgumentTypes().get(0)), cast(generatorContext, generatorContext.generate(second, Optional.empty()), secondType, equalFunctionMetadata.getArgumentTypes().get(1))));
BytecodeBlock conditionBlock = new BytecodeBlock().append(equalsCall).append(BytecodeUtils.ifWasNullClearPopAndGoto(scope, notMatch, void.class, boolean.class));
// if first and second are equal, return null
BytecodeBlock trueBlock = new BytecodeBlock().append(generatorContext.wasNull().set(constantTrue())).pop(first.getType().getJavaType()).pushJavaDefault(first.getType().getJavaType());
// else return first (which is still on the stack
block.append(new IfStatement().condition(conditionBlock).ifTrue(trueBlock).ifFalse(notMatch));
outputBlockVariable.ifPresent(output -> block.append(generateWrite(generatorContext, returnType, output)));
return block;
}
use of com.facebook.presto.spi.relation.RowExpression in project presto by prestodb.
the class IsNullCodeGenerator method generateExpression.
@Override
public BytecodeNode generateExpression(BytecodeGeneratorContext generatorContext, Type returnType, List<RowExpression> arguments, Optional<Variable> outputBlockVariable) {
Preconditions.checkArgument(arguments.size() == 1);
RowExpression argument = arguments.get(0);
if (argument.getType().equals(UNKNOWN)) {
return loadBoolean(true);
}
BytecodeNode value = generatorContext.generate(argument, Optional.empty());
// evaluate the expression, pop the produced value, and load the null flag
Variable wasNull = generatorContext.wasNull();
BytecodeBlock block = new BytecodeBlock().comment("is null").append(value).pop(argument.getType().getJavaType()).append(wasNull);
// clear the null flag
block.append(wasNull.set(constantFalse()));
outputBlockVariable.ifPresent(output -> block.append(generateWrite(generatorContext, returnType, output)));
return block;
}
Aggregations