use of com.facebook.presto.bytecode.Variable in project presto by prestodb.
the class LambdaBytecodeGenerator method defineLambdaMethod.
private static CompiledLambda defineLambdaMethod(RowExpressionCompiler innerExpressionCompiler, ClassDefinition classDefinition, String methodName, List<Parameter> inputParameters, LambdaDefinitionExpression lambda) {
checkCondition(inputParameters.size() <= 254, NOT_SUPPORTED, "Too many arguments for lambda expression");
Class<?> returnType = Primitives.wrap(lambda.getBody().getType().getJavaType());
MethodDefinition method = classDefinition.declareMethod(a(PUBLIC), methodName, type(returnType), inputParameters);
Scope scope = method.getScope();
Variable wasNull = scope.declareVariable(boolean.class, "wasNull");
BytecodeNode compiledBody = innerExpressionCompiler.compile(lambda.getBody(), scope, Optional.empty());
method.getBody().putVariable(wasNull, false).append(compiledBody).append(boxPrimitiveIfNecessary(scope, returnType)).ret(returnType);
Handle lambdaAsmHandle = new Handle(Opcodes.H_INVOKEVIRTUAL, method.getThis().getType().getClassName(), method.getName(), method.getMethodDescriptor(), false);
return new CompiledLambda(lambdaAsmHandle, method.getReturnType(), method.getParameterTypes());
}
use of com.facebook.presto.bytecode.Variable 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.bytecode.Variable in project presto by prestodb.
the class JoinFilterFunctionCompiler method generateConstructor.
private static void generateConstructor(ClassDefinition classDefinition, FieldDefinition propertiesField, CachedInstanceBinder cachedInstanceBinder) {
Parameter propertiesParameter = arg("properties", SqlFunctionProperties.class);
MethodDefinition constructorDefinition = classDefinition.declareConstructor(a(PUBLIC), propertiesParameter);
BytecodeBlock body = constructorDefinition.getBody();
Variable thisVariable = constructorDefinition.getThis();
body.comment("super();").append(thisVariable).invokeConstructor(Object.class);
body.append(thisVariable.setField(propertiesField, propertiesParameter));
cachedInstanceBinder.generateInitializations(thisVariable, body);
body.ret();
}
use of com.facebook.presto.bytecode.Variable in project presto by prestodb.
the class JoinFilterFunctionCompiler method generateFilterMethod.
private void generateFilterMethod(SqlFunctionProperties sqlFunctionProperties, Map<SqlFunctionId, SqlInvokedFunction> sessionFunctions, ClassDefinition classDefinition, CallSiteBinder callSiteBinder, CachedInstanceBinder cachedInstanceBinder, Map<LambdaDefinitionExpression, CompiledLambda> compiledLambdaMap, RowExpression filter, int leftBlocksSize, FieldDefinition propertiesField) {
// int leftPosition, Page leftPage, int rightPosition, Page rightPage
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 method = classDefinition.declareMethod(a(PUBLIC), "filter", type(boolean.class), ImmutableList.<Parameter>builder().add(leftPosition).add(leftPage).add(rightPosition).add(rightPage).build());
method.comment("filter: %s", filter.toString());
BytecodeBlock body = method.getBody();
Scope scope = method.getScope();
Variable wasNullVariable = scope.declareVariable("wasNull", body, constantFalse());
scope.declareVariable("properties", body, method.getThis().getField(propertiesField));
RowExpressionCompiler compiler = new RowExpressionCompiler(classDefinition, callSiteBinder, cachedInstanceBinder, fieldReferenceCompiler(callSiteBinder, leftPosition, leftPage, rightPosition, rightPage, leftBlocksSize), metadata, sqlFunctionProperties, sessionFunctions, compiledLambdaMap);
BytecodeNode visitorBody = compiler.compile(filter, scope, Optional.empty());
Variable result = scope.declareVariable(boolean.class, "result");
body.append(visitorBody).putVariable(result).append(new IfStatement().condition(wasNullVariable).ifTrue(constantFalse().ret()).ifFalse(result.ret()));
}
use of com.facebook.presto.bytecode.Variable 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;
}
Aggregations