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;
}
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;
}
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);
}
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()]));
}
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;
}
Aggregations