use of com.facebook.presto.bytecode.MethodDefinition in project presto by prestodb.
the class TryCodeGenerator method defineTryMethod.
public static MethodDefinition defineTryMethod(BytecodeExpressionVisitor innerExpressionVisitor, ClassDefinition classDefinition, String methodName, List<Parameter> inputParameters, Class<?> returnType, RowExpression innerRowExpression, CallSiteBinder callSiteBinder) {
MethodDefinition method = classDefinition.declareMethod(a(PUBLIC), methodName, type(returnType), inputParameters);
Scope calleeMethodScope = method.getScope();
Variable wasNull = calleeMethodScope.declareVariable(boolean.class, "wasNull");
BytecodeNode innerExpression = innerRowExpression.accept(innerExpressionVisitor, calleeMethodScope);
MethodType exceptionHandlerType = methodType(returnType, PrestoException.class);
MethodHandle exceptionHandler = methodHandle(TryCodeGenerator.class, EXCEPTION_HANDLER_NAME, PrestoException.class).asType(exceptionHandlerType);
Binding binding = callSiteBinder.bind(exceptionHandler);
method.comment("Try projection: %s", innerRowExpression.toString());
method.getBody().append(wasNull.set(constantBoolean(false))).append(new TryCatch(new BytecodeBlock().append(innerExpression).append(boxPrimitiveIfNecessary(calleeMethodScope, returnType)), new BytecodeBlock().append(invoke(binding, EXCEPTION_HANDLER_NAME)), ParameterizedType.type(PrestoException.class))).ret(returnType);
return method;
}
use of com.facebook.presto.bytecode.MethodDefinition in project presto by prestodb.
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) {
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", ParameterizedType.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(HashMap.class, "map");
body.append(map.set(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 com.facebook.presto.bytecode.MethodDefinition in project presto by prestodb.
the class AbstractMinMaxBy method generateInputMethod.
private void generateInputMethod(ClassDefinition definition, CallSiteBinder binder, MethodHandle compareMethod, Type keyType, Type valueType, Class<?> stateClass) {
Parameter state = arg("state", stateClass);
Parameter value = arg("value", Block.class);
Parameter key = arg("key", Block.class);
Parameter position = arg("position", int.class);
MethodDefinition method = definition.declareMethod(a(PUBLIC, STATIC), "input", type(void.class), state, value, key, position);
if (keyType.equals(UNKNOWN)) {
method.getBody().ret();
return;
}
SqlTypeBytecodeExpression keySqlType = constantType(binder, keyType);
BytecodeBlock ifBlock = new BytecodeBlock().append(state.invoke("setFirst", void.class, keySqlType.getValue(key, position))).append(state.invoke("setFirstNull", void.class, constantBoolean(false))).append(state.invoke("setSecondNull", void.class, value.invoke("isNull", boolean.class, position)));
if (!valueType.equals(UNKNOWN)) {
SqlTypeBytecodeExpression valueSqlType = constantType(binder, valueType);
ifBlock.append(new IfStatement().condition(value.invoke("isNull", boolean.class, position)).ifFalse(state.invoke("setSecond", void.class, valueSqlType.getValue(value, position))));
}
method.getBody().append(new IfStatement().condition(or(state.invoke("isFirstNull", boolean.class), and(not(key.invoke("isNull", boolean.class, position)), loadConstant(binder, compareMethod, MethodHandle.class).invoke("invokeExact", boolean.class, keySqlType.getValue(key, position), state.invoke("getFirst", keyType.getJavaType()))))).ifTrue(ifBlock)).ret();
}
use of com.facebook.presto.bytecode.MethodDefinition in project presto by prestodb.
the class AbstractMinMaxBy method generateCombineMethod.
private void generateCombineMethod(ClassDefinition definition, CallSiteBinder binder, MethodHandle compareMethod, Type keyType, Type valueType, Class<?> stateClass) {
Parameter state = arg("state", stateClass);
Parameter otherState = arg("otherState", stateClass);
MethodDefinition method = definition.declareMethod(a(PUBLIC, STATIC), "combine", type(void.class), state, otherState);
if (keyType.equals(UNKNOWN)) {
method.getBody().ret();
return;
}
Class<?> keyJavaType = keyType.getJavaType();
BytecodeBlock ifBlock = new BytecodeBlock().append(state.invoke("setFirst", void.class, otherState.invoke("getFirst", keyJavaType))).append(state.invoke("setFirstNull", void.class, otherState.invoke("isFirstNull", boolean.class))).append(state.invoke("setSecondNull", void.class, otherState.invoke("isSecondNull", boolean.class)));
if (!valueType.equals(UNKNOWN)) {
ifBlock.append(state.invoke("setSecond", void.class, otherState.invoke("getSecond", valueType.getJavaType())));
}
method.getBody().append(new IfStatement().condition(or(state.invoke("isFirstNull", boolean.class), and(not(otherState.invoke("isFirstNull", boolean.class)), loadConstant(binder, compareMethod, MethodHandle.class).invoke("invokeExact", boolean.class, otherState.invoke("getFirst", keyJavaType), state.invoke("getFirst", keyJavaType))))).ifTrue(ifBlock)).ret();
}
use of com.facebook.presto.bytecode.MethodDefinition in project presto by prestodb.
the class AccumulatorCompiler method generateAddIntermediateAsCombine.
private static void generateAddIntermediateAsCombine(ClassDefinition definition, FieldDefinition stateField, FieldDefinition stateSerializerField, FieldDefinition stateFactoryField, MethodHandle combineFunction, Class<?> singleStateClass, CallSiteBinder callSiteBinder, boolean grouped) {
MethodDefinition method = declareAddIntermediate(definition, grouped);
Scope scope = method.getScope();
BytecodeBlock body = method.getBody();
Variable thisVariable = method.getThis();
Variable block = scope.getVariable("block");
Variable scratchState = scope.declareVariable(singleStateClass, "scratchState");
Variable position = scope.declareVariable(int.class, "position");
body.comment("scratchState = stateFactory.createSingleState();").append(thisVariable.getField(stateFactoryField)).invokeInterface(AccumulatorStateFactory.class, "createSingleState", Object.class).checkCast(scratchState.getType()).putVariable(scratchState);
if (grouped) {
generateEnsureCapacity(scope, stateField, body);
}
BytecodeBlock loopBody = new BytecodeBlock();
if (grouped) {
Variable groupIdsBlock = scope.getVariable("groupIdsBlock");
loopBody.append(thisVariable.getField(stateField).invoke("setGroupId", void.class, groupIdsBlock.invoke("getGroupId", long.class, position)));
}
loopBody.append(thisVariable.getField(stateSerializerField).invoke("deserialize", void.class, block, position, scratchState.cast(Object.class)));
loopBody.comment("combine(state, scratchState)").append(thisVariable.getField(stateField)).append(scratchState).append(invoke(callSiteBinder.bind(combineFunction), "combine"));
if (grouped) {
// skip rows with null group id
IfStatement ifStatement = new IfStatement("if (!groupIdsBlock.isNull(position))").condition(not(scope.getVariable("groupIdsBlock").invoke("isNull", boolean.class, position))).ifTrue(loopBody);
loopBody = new BytecodeBlock().append(ifStatement);
}
body.append(generateBlockNonNullPositionForLoop(scope, position, loopBody)).ret();
}
Aggregations