Search in sources :

Example 41 with BytecodeNode

use of com.facebook.presto.bytecode.BytecodeNode in project presto by prestodb.

the class SwitchCodeGenerator method generateExpression.

@Override
public BytecodeNode generateExpression(BytecodeGeneratorContext generatorContext, Type returnType, List<RowExpression> arguments, Optional<Variable> outputBlockVariable) {
    Scope scope = generatorContext.getScope();
    BytecodeNode elseValue;
    List<RowExpression> whenClauses;
    RowExpression last = arguments.get(arguments.size() - 1);
    if (last instanceof SpecialFormExpression && ((SpecialFormExpression) last).getForm().equals(WHEN)) {
        whenClauses = arguments.subList(1, arguments.size());
        elseValue = new BytecodeBlock().append(generatorContext.wasNull().set(constantTrue())).pushJavaDefault(returnType.getJavaType());
    } else {
        whenClauses = arguments.subList(1, arguments.size() - 1);
        elseValue = generatorContext.generate(last, Optional.empty());
    }
    // determine the type of the value and result
    RowExpression value = arguments.get(0);
    Class<?> valueType = value.getType().getJavaType();
    // We generate SearchedCase as CASE TRUE WHEN p1 THEN v1 WHEN p2 THEN p2...
    boolean searchedCase = (value instanceof ConstantExpression && ((ConstantExpression) value).getType() == BOOLEAN && ((ConstantExpression) value).getValue() == Boolean.TRUE);
    // evaluate the value and store it in a variable
    LabelNode elseLabel = new LabelNode("else");
    LabelNode endLabel = new LabelNode("end");
    BytecodeBlock block = new BytecodeBlock();
    Optional<BytecodeNode> getTempVariableNode;
    if (!searchedCase) {
        BytecodeNode valueBytecode = generatorContext.generate(value, Optional.empty());
        Variable tempVariable = scope.createTempVariable(valueType);
        block.append(valueBytecode).append(BytecodeUtils.ifWasNullClearPopAndGoto(scope, elseLabel, void.class, valueType)).putVariable(tempVariable);
        getTempVariableNode = Optional.of(VariableInstruction.loadVariable(tempVariable));
    } else {
        getTempVariableNode = Optional.empty();
    }
    Variable wasNull = generatorContext.wasNull();
    block.putVariable(wasNull, false);
    Map<RowExpression, LabelNode> resultLabels = new HashMap<>();
    // We already know the P1 .. Pn are all boolean just call them and search for true (false/null don't matter).
    for (RowExpression clause : whenClauses) {
        checkArgument(clause instanceof SpecialFormExpression && ((SpecialFormExpression) clause).getForm().equals(WHEN));
        RowExpression operand = ((SpecialFormExpression) clause).getArguments().get(0);
        BytecodeNode operandBytecode;
        if (searchedCase) {
            operandBytecode = generatorContext.generate(operand, Optional.empty());
        } else {
            // call equals(value, operandBytecode)
            FunctionHandle equalsFunction = generatorContext.getFunctionManager().resolveOperator(EQUAL, fromTypes(value.getType(), operand.getType()));
            operandBytecode = generatorContext.generateCall(EQUAL.name(), generatorContext.getFunctionManager().getJavaScalarFunctionImplementation(equalsFunction), ImmutableList.of(generatorContext.generate(operand, Optional.empty()), getTempVariableNode.get()));
        }
        block.append(operandBytecode);
        IfStatement ifWasNull = new IfStatement().condition(wasNull);
        ifWasNull.ifTrue().putVariable(wasNull, false).pop(// pop the result of the predicate eval
        Boolean.class);
        // Here the TOS  is the result of the predicate.
        RowExpression result = ((SpecialFormExpression) clause).getArguments().get(1);
        LabelNode target = resultLabels.get(result);
        if (target == null) {
            target = new LabelNode(RESULT_LABEL_PREFIX + resultLabels.size());
            resultLabels.put(result, target);
        }
        ifWasNull.ifFalse().ifTrueGoto(target);
        block.append(ifWasNull);
    }
    // Here we evaluate the else result.
    block.visitLabel(elseLabel).append(elseValue).gotoLabel(endLabel);
    // Now generate the result expression code.
    for (Map.Entry<RowExpression, LabelNode> resultLabel : resultLabels.entrySet()) {
        block.visitLabel(resultLabel.getValue()).append(generatorContext.generate(resultLabel.getKey(), Optional.empty())).gotoLabel(endLabel);
    }
    block.visitLabel(endLabel);
    outputBlockVariable.ifPresent(output -> block.append(generateWrite(generatorContext, returnType, output)));
    return block;
}
Also used : LabelNode(com.facebook.presto.bytecode.instruction.LabelNode) Variable(com.facebook.presto.bytecode.Variable) HashMap(java.util.HashMap) ConstantExpression(com.facebook.presto.spi.relation.ConstantExpression) BytecodeBlock(com.facebook.presto.bytecode.BytecodeBlock) RowExpression(com.facebook.presto.spi.relation.RowExpression) IfStatement(com.facebook.presto.bytecode.control.IfStatement) Scope(com.facebook.presto.bytecode.Scope) BytecodeNode(com.facebook.presto.bytecode.BytecodeNode) SpecialFormExpression(com.facebook.presto.spi.relation.SpecialFormExpression) FunctionHandle(com.facebook.presto.spi.function.FunctionHandle) HashMap(java.util.HashMap) Map(java.util.Map)

Example 42 with BytecodeNode

use of com.facebook.presto.bytecode.BytecodeNode in project presto by prestodb.

the class InvokeFunctionBytecodeExpression method invokeFunction.

public static BytecodeExpression invokeFunction(Scope scope, CachedInstanceBinder cachedInstanceBinder, String name, JavaScalarFunctionImplementation function, List<BytecodeExpression> parameters) {
    requireNonNull(scope, "scope is null");
    requireNonNull(function, "function is null");
    Optional<BytecodeNode> instance = Optional.empty();
    if (function instanceof BuiltInScalarFunctionImplementation && ((BuiltInScalarFunctionImplementation) function).getInstanceFactory().isPresent()) {
        FieldDefinition field = cachedInstanceBinder.getCachedInstance(((BuiltInScalarFunctionImplementation) function).getInstanceFactory().get());
        instance = Optional.of(scope.getThis().getField(field));
    }
    return new InvokeFunctionBytecodeExpression(scope, cachedInstanceBinder.getCallSiteBinder(), name, function, instance, parameters);
}
Also used : BuiltInScalarFunctionImplementation(com.facebook.presto.operator.scalar.BuiltInScalarFunctionImplementation) FieldDefinition(com.facebook.presto.bytecode.FieldDefinition) BytecodeNode(com.facebook.presto.bytecode.BytecodeNode)

Aggregations

BytecodeNode (com.facebook.presto.bytecode.BytecodeNode)42 Variable (com.facebook.presto.bytecode.Variable)33 BytecodeBlock (com.facebook.presto.bytecode.BytecodeBlock)29 IfStatement (com.facebook.presto.bytecode.control.IfStatement)23 Scope (com.facebook.presto.bytecode.Scope)21 MethodDefinition (com.facebook.presto.bytecode.MethodDefinition)19 Parameter (com.facebook.presto.bytecode.Parameter)16 LabelNode (com.facebook.presto.bytecode.instruction.LabelNode)12 ClassDefinition (com.facebook.presto.bytecode.ClassDefinition)7 ForLoop (com.facebook.presto.bytecode.control.ForLoop)7 RowExpression (com.facebook.presto.sql.relational.RowExpression)7 ArrayList (java.util.ArrayList)6 FieldDefinition (com.facebook.presto.bytecode.FieldDefinition)5 BytecodeExpression (com.facebook.presto.bytecode.expression.BytecodeExpression)5 Block (com.facebook.presto.common.block.Block)5 Type (com.facebook.presto.common.type.Type)5 FunctionHandle (com.facebook.presto.spi.function.FunctionHandle)5 RowExpression (com.facebook.presto.spi.relation.RowExpression)5 SqlTypeBytecodeExpression (com.facebook.presto.sql.gen.SqlTypeBytecodeExpression)5 ImmutableList (com.google.common.collect.ImmutableList)5