Search in sources :

Example 26 with Variable

use of io.airlift.bytecode.Variable in project hetu-core by openlookeng.

the class PageFunctionCompiler method definePageProjectWorkClass.

private ClassDefinition definePageProjectWorkClass(RowExpression projection, CallSiteBinder callSiteBinder, Optional<String> classNameSuffix) {
    ClassDefinition classDefinition = new ClassDefinition(a(PUBLIC, FINAL), generateProjectionWorkClassName(classNameSuffix), type(Object.class), type(Work.class));
    FieldDefinition blockBuilderField = classDefinition.declareField(a(PRIVATE), "blockBuilder", BlockBuilder.class);
    FieldDefinition sessionField = classDefinition.declareField(a(PRIVATE), "session", ConnectorSession.class);
    FieldDefinition pageField = classDefinition.declareField(a(PRIVATE), "page", Page.class);
    FieldDefinition selectedPositionsField = classDefinition.declareField(a(PRIVATE), "selectedPositions", SelectedPositions.class);
    FieldDefinition nextIndexOrPositionField = classDefinition.declareField(a(PRIVATE), "nextIndexOrPosition", int.class);
    FieldDefinition resultField = classDefinition.declareField(a(PRIVATE), "result", Block.class);
    CachedInstanceBinder cachedInstanceBinder = new CachedInstanceBinder(classDefinition, callSiteBinder);
    // process
    generateProcessMethod(classDefinition, blockBuilderField, sessionField, pageField, selectedPositionsField, nextIndexOrPositionField, resultField);
    // getResult
    MethodDefinition method = classDefinition.declareMethod(a(PUBLIC), "getResult", type(Object.class), ImmutableList.of());
    method.getBody().append(method.getThis().getField(resultField)).ret(Object.class);
    // evaluate
    Map<LambdaDefinitionExpression, CompiledLambda> compiledLambdaMap = generateMethodsForLambda(classDefinition, callSiteBinder, cachedInstanceBinder, projection);
    generateEvaluateMethod(classDefinition, callSiteBinder, cachedInstanceBinder, compiledLambdaMap, projection, blockBuilderField);
    // constructor
    Parameter blockBuilder = arg("blockBuilder", BlockBuilder.class);
    Parameter session = arg("session", ConnectorSession.class);
    Parameter page = arg("page", Page.class);
    Parameter selectedPositions = arg("selectedPositions", SelectedPositions.class);
    MethodDefinition constructorDefinition = classDefinition.declareConstructor(a(PUBLIC), blockBuilder, session, page, selectedPositions);
    BytecodeBlock body = constructorDefinition.getBody();
    Variable thisVariable = constructorDefinition.getThis();
    body.comment("super();").append(thisVariable).invokeConstructor(Object.class).append(thisVariable.setField(blockBuilderField, blockBuilder)).append(thisVariable.setField(sessionField, session)).append(thisVariable.setField(pageField, page)).append(thisVariable.setField(selectedPositionsField, selectedPositions)).append(thisVariable.setField(nextIndexOrPositionField, selectedPositions.invoke("getOffset", int.class))).append(thisVariable.setField(resultField, constantNull(Block.class)));
    cachedInstanceBinder.generateInitializations(thisVariable, body);
    body.ret();
    return classDefinition;
}
Also used : CompiledLambda(io.prestosql.sql.gen.LambdaBytecodeGenerator.CompiledLambda) Variable(io.airlift.bytecode.Variable) MethodDefinition(io.airlift.bytecode.MethodDefinition) FieldDefinition(io.airlift.bytecode.FieldDefinition) Work(io.prestosql.operator.Work) BytecodeBlock(io.airlift.bytecode.BytecodeBlock) Parameter(io.airlift.bytecode.Parameter) ClassDefinition(io.airlift.bytecode.ClassDefinition) LambdaDefinitionExpression(io.prestosql.spi.relation.LambdaDefinitionExpression)

Example 27 with Variable

use of io.airlift.bytecode.Variable in project hetu-core by openlookeng.

the class PageFunctionCompiler method generatePageFilterMethod.

private static MethodDefinition generatePageFilterMethod(ClassDefinition classDefinition, FieldDefinition selectedPositionsField) {
    Parameter session = arg("session", ConnectorSession.class);
    Parameter page = arg("page", Page.class);
    MethodDefinition method = classDefinition.declareMethod(a(PUBLIC), "filter", type(SelectedPositions.class), ImmutableList.<Parameter>builder().add(session).add(page).build());
    Scope scope = method.getScope();
    Variable thisVariable = method.getThis();
    BytecodeBlock body = method.getBody();
    Variable positionCount = scope.declareVariable("positionCount", body, page.invoke("getPositionCount", int.class));
    body.append(new IfStatement("grow selectedPositions if necessary").condition(lessThan(thisVariable.getField(selectedPositionsField).length(), positionCount)).ifTrue(thisVariable.setField(selectedPositionsField, newArray(type(boolean[].class), positionCount))));
    Variable selectedPositions = scope.declareVariable("selectedPositions", body, thisVariable.getField(selectedPositionsField));
    Variable position = scope.declareVariable(int.class, "position");
    body.append(new ForLoop().initialize(position.set(constantInt(0))).condition(lessThan(position, positionCount)).update(position.increment()).body(selectedPositions.setElement(position, thisVariable.invoke("filter", boolean.class, session, page, position))));
    body.append(invokeStatic(PageFilter.class, "positionsArrayToSelectedPositions", SelectedPositions.class, selectedPositions, positionCount).ret());
    return method;
}
Also used : IfStatement(io.airlift.bytecode.control.IfStatement) Variable(io.airlift.bytecode.Variable) Scope(io.airlift.bytecode.Scope) ForLoop(io.airlift.bytecode.control.ForLoop) MethodDefinition(io.airlift.bytecode.MethodDefinition) SelectedPositions(io.prestosql.operator.project.SelectedPositions) BytecodeBlock(io.airlift.bytecode.BytecodeBlock) Parameter(io.airlift.bytecode.Parameter)

Example 28 with Variable

use of io.airlift.bytecode.Variable in project hetu-core by openlookeng.

the class SwitchCodeGenerator method generateExpression.

@Override
public BytecodeNode generateExpression(FunctionHandle functionHandle, BytecodeGeneratorContext generatorContext, Type returnType, List<RowExpression> arguments) {
    // TODO: compile as
    /*
            hashCode = hashCode(<value>)

            // all constant expressions before a non-constant
            switch (hashCode) {
                case ...:
                    if (<value> == <constant1>) {
                       ...
                    }
                    else if (<value> == <constant2>) {
                       ...
                    }
                    else if (...) {
                    }
                case ...:
                    ...
            }

            if (<value> == <non-constant1>) {
                ...
            }
            else if (<value> == <non-constant2>) {
                ...
            }
            ...

            // repeat with next sequence of constant expressions
         */
    Scope scope = generatorContext.getScope();
    // process value, else, and all when clauses
    RowExpression value = arguments.get(0);
    BytecodeNode valueBytecode = generatorContext.generate(value);
    BytecodeNode elseValue;
    List<RowExpression> whenClauses;
    RowExpression last = arguments.get(arguments.size() - 1);
    if (last instanceof SpecialForm && ((SpecialForm) last).getForm() == 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);
    }
    // determine the type of the value and result
    Class<?> valueType = value.getType().getJavaType();
    // evaluate the value and store it in a variable
    LabelNode nullValue = new LabelNode("nullCondition");
    Variable tempVariable = scope.createTempVariable(valueType);
    BytecodeBlock block = new BytecodeBlock().append(valueBytecode).append(BytecodeUtils.ifWasNullClearPopAndGoto(scope, nullValue, void.class, valueType)).putVariable(tempVariable);
    BytecodeNode getTempVariableNode = VariableInstruction.loadVariable(tempVariable);
    // build the statements
    elseValue = new BytecodeBlock().visitLabel(nullValue).append(elseValue);
    // reverse list because current if statement builder doesn't support if/else so we need to build the if statements bottom up
    for (RowExpression clause : Lists.reverse(whenClauses)) {
        Preconditions.checkArgument(clause instanceof SpecialForm && ((SpecialForm) clause).getForm() == WHEN);
        RowExpression operand = ((SpecialForm) clause).getArguments().get(0);
        RowExpression result = ((SpecialForm) clause).getArguments().get(1);
        // call equals(value, operand)
        FunctionHandle equalsFunction = generatorContext.getFunctionManager().resolveOperatorFunctionHandle(EQUAL, fromTypes(value.getType(), operand.getType()));
        // TODO: what if operand is null? It seems that the call will return "null" (which is cleared below)
        // and the code only does the right thing because the value in the stack for that scenario is
        // Java's default for boolean == false
        // This code should probably be checking for wasNull after the call and "failing" the equality
        // check if wasNull is true
        BytecodeNode equalsCall = generatorContext.generateCall(EQUAL.name(), generatorContext.getFunctionManager().getBuiltInScalarFunctionImplementation(equalsFunction), ImmutableList.of(generatorContext.generate(operand, Optional.empty()), getTempVariableNode));
        BytecodeBlock condition = new BytecodeBlock().append(equalsCall).append(generatorContext.wasNull().set(constantFalse()));
        elseValue = new IfStatement("when").condition(condition).ifTrue(generatorContext.generate(result)).ifFalse(elseValue);
    }
    return block.append(elseValue);
}
Also used : LabelNode(io.airlift.bytecode.instruction.LabelNode) IfStatement(io.airlift.bytecode.control.IfStatement) Variable(io.airlift.bytecode.Variable) Scope(io.airlift.bytecode.Scope) BytecodeBlock(io.airlift.bytecode.BytecodeBlock) RowExpression(io.prestosql.spi.relation.RowExpression) BytecodeNode(io.airlift.bytecode.BytecodeNode) FunctionHandle(io.prestosql.spi.function.FunctionHandle) SpecialForm(io.prestosql.spi.relation.SpecialForm)

Example 29 with Variable

use of io.airlift.bytecode.Variable in project hetu-core by openlookeng.

the class VarArgsToMapAdapterGenerator method generateVarArgsToMapAdapter.

/**
 * Generate byte code that
 * <p><ul>
 * <li>takes a specified number of variables as arguments (types of the arguments are provided in {@code javaTypes})
 * <li>put the variables in a map (keys of the map are provided in {@code names})
 * <li>invoke the provided {@code function} with the map
 * <li>return with the result of the function call (type must match {@code returnType})
 * </ul></p>
 */
public static MethodHandle generateVarArgsToMapAdapter(Class<?> returnType, List<Class<?>> javaTypes, List<String> names, Function<Map<String, Object>, Object> function) {
    checkCondition(javaTypes.size() <= 254, NOT_SUPPORTED, "Too many arguments for vararg function");
    CallSiteBinder callSiteBinder = new CallSiteBinder();
    ClassDefinition classDefinition = new ClassDefinition(a(PUBLIC, FINAL), makeClassName("VarArgsToMapAdapter"), type(Object.class));
    ImmutableList.Builder<Parameter> parameterListBuilder = ImmutableList.builder();
    for (int i = 0; i < javaTypes.size(); i++) {
        Class<?> javaType = javaTypes.get(i);
        parameterListBuilder.add(arg("input_" + i, javaType));
    }
    ImmutableList<Parameter> parameterList = parameterListBuilder.build();
    MethodDefinition methodDefinition = classDefinition.declareMethod(a(PUBLIC, STATIC), "varArgsToMap", type(returnType), parameterList);
    BytecodeBlock body = methodDefinition.getBody();
    // ImmutableMap.Builder can not be used here because it doesn't allow nulls.
    Variable map = methodDefinition.getScope().declareVariable("map", methodDefinition.getBody(), invokeStatic(Maps.class, "newHashMapWithExpectedSize", HashMap.class, constantInt(javaTypes.size())));
    for (int i = 0; i < javaTypes.size(); i++) {
        body.append(map.invoke("put", Object.class, constantString(names.get(i)).cast(Object.class), parameterList.get(i).cast(Object.class)));
    }
    body.append(loadConstant(callSiteBinder, function, Function.class).invoke("apply", Object.class, map.cast(Object.class)).cast(returnType).ret());
    Class<?> generatedClass = defineClass(classDefinition, Object.class, callSiteBinder.getBindings(), new DynamicClassLoader(VarArgsToMapAdapterGenerator.class.getClassLoader()));
    return Reflection.methodHandle(generatedClass, "varArgsToMap", javaTypes.toArray(new Class<?>[javaTypes.size()]));
}
Also used : DynamicClassLoader(io.airlift.bytecode.DynamicClassLoader) Variable(io.airlift.bytecode.Variable) HashMap(java.util.HashMap) ImmutableList(com.google.common.collect.ImmutableList) BytecodeBlock(io.airlift.bytecode.BytecodeBlock) ClassDefinition(io.airlift.bytecode.ClassDefinition) Maps(com.google.common.collect.Maps) MethodDefinition(io.airlift.bytecode.MethodDefinition) Parameter(io.airlift.bytecode.Parameter) CompilerUtils.defineClass(io.prestosql.util.CompilerUtils.defineClass)

Example 30 with Variable

use of io.airlift.bytecode.Variable in project hetu-core by openlookeng.

the class BytecodeUtils method unboxPrimitiveIfNecessary.

public static BytecodeBlock unboxPrimitiveIfNecessary(Scope scope, Class<?> boxedType) {
    BytecodeBlock block = new BytecodeBlock();
    LabelNode end = new LabelNode("end");
    Class<?> unboxedType = Primitives.unwrap(boxedType);
    Variable wasNull = scope.getVariable("wasNull");
    if (unboxedType.isPrimitive()) {
        LabelNode notNull = new LabelNode("notNull");
        block.dup(boxedType).ifNotNullGoto(notNull).append(wasNull.set(constantTrue())).comment("swap boxed null with unboxed default").pop(boxedType).pushJavaDefault(unboxedType).gotoLabel(end).visitLabel(notNull).append(unboxPrimitive(unboxedType));
    } else {
        block.dup(boxedType).ifNotNullGoto(end).append(wasNull.set(constantTrue()));
    }
    block.visitLabel(end);
    return block;
}
Also used : LabelNode(io.airlift.bytecode.instruction.LabelNode) Variable(io.airlift.bytecode.Variable) BytecodeBlock(io.airlift.bytecode.BytecodeBlock)

Aggregations

Variable (io.airlift.bytecode.Variable)148 BytecodeBlock (io.airlift.bytecode.BytecodeBlock)114 MethodDefinition (io.airlift.bytecode.MethodDefinition)102 Parameter (io.airlift.bytecode.Parameter)86 IfStatement (io.airlift.bytecode.control.IfStatement)70 Scope (io.airlift.bytecode.Scope)63 BytecodeExpression (io.airlift.bytecode.expression.BytecodeExpression)50 BytecodeNode (io.airlift.bytecode.BytecodeNode)39 LabelNode (io.airlift.bytecode.instruction.LabelNode)32 ClassDefinition (io.airlift.bytecode.ClassDefinition)30 FieldDefinition (io.airlift.bytecode.FieldDefinition)26 ImmutableList (com.google.common.collect.ImmutableList)24 ForLoop (io.airlift.bytecode.control.ForLoop)21 ArrayList (java.util.ArrayList)21 Type (io.trino.spi.type.Type)16 ImmutableList.toImmutableList (com.google.common.collect.ImmutableList.toImmutableList)15 Block (io.prestosql.spi.block.Block)15 Type (io.prestosql.spi.type.Type)14 List (java.util.List)14 Block (io.trino.spi.block.Block)13