use of io.airlift.bytecode.DynamicClassLoader in project trino by trinodb.
the class AccumulatorCompiler method generateAccumulatorFactory.
public static AccumulatorFactory generateAccumulatorFactory(BoundSignature boundSignature, AggregationMetadata metadata, FunctionNullability functionNullability) {
// change types used in Aggregation methods to types used in the core Trino engine to simplify code generation
metadata = normalizeAggregationMethods(metadata);
DynamicClassLoader classLoader = new DynamicClassLoader(AccumulatorCompiler.class.getClassLoader());
List<Boolean> argumentNullable = functionNullability.getArgumentNullable().subList(0, functionNullability.getArgumentNullable().size() - metadata.getLambdaInterfaces().size());
Constructor<? extends Accumulator> accumulatorConstructor = generateAccumulatorClass(boundSignature, Accumulator.class, metadata, argumentNullable, classLoader);
Constructor<? extends GroupedAccumulator> groupedAccumulatorConstructor = generateAccumulatorClass(boundSignature, GroupedAccumulator.class, metadata, argumentNullable, classLoader);
return new CompiledAccumulatorFactory(accumulatorConstructor, groupedAccumulatorConstructor, metadata.getLambdaInterfaces());
}
use of io.airlift.bytecode.DynamicClassLoader in project trino by trinodb.
the class AccumulatorCompiler method generateWindowAccumulatorClass.
public static Constructor<? extends WindowAccumulator> generateWindowAccumulatorClass(BoundSignature boundSignature, AggregationMetadata metadata, FunctionNullability functionNullability) {
DynamicClassLoader classLoader = new DynamicClassLoader(AccumulatorCompiler.class.getClassLoader());
List<Boolean> argumentNullable = functionNullability.getArgumentNullable().subList(0, functionNullability.getArgumentNullable().size() - metadata.getLambdaInterfaces().size());
ClassDefinition definition = new ClassDefinition(a(PUBLIC, FINAL), makeClassName(boundSignature.getName() + WindowAccumulator.class.getSimpleName()), type(Object.class), type(WindowAccumulator.class));
CallSiteBinder callSiteBinder = new CallSiteBinder();
List<AccumulatorStateDescriptor<?>> stateDescriptors = metadata.getAccumulatorStateDescriptors();
List<StateFieldAndDescriptor> stateFieldAndDescriptors = new ArrayList<>();
for (int i = 0; i < stateDescriptors.size(); i++) {
stateFieldAndDescriptors.add(new StateFieldAndDescriptor(stateDescriptors.get(i), definition.declareField(a(PRIVATE, FINAL), "stateSerializer_" + i, AccumulatorStateSerializer.class), definition.declareField(a(PRIVATE, FINAL), "stateFactory_" + i, AccumulatorStateFactory.class), definition.declareField(a(PRIVATE, FINAL), "state_" + i, AccumulatorState.class)));
}
List<FieldDefinition> stateFields = stateFieldAndDescriptors.stream().map(StateFieldAndDescriptor::getStateField).collect(toImmutableList());
int lambdaCount = metadata.getLambdaInterfaces().size();
List<FieldDefinition> lambdaProviderFields = new ArrayList<>(lambdaCount);
for (int i = 0; i < lambdaCount; i++) {
lambdaProviderFields.add(definition.declareField(a(PRIVATE, FINAL), "lambdaProvider_" + i, Supplier.class));
}
// Generate constructor
generateWindowAccumulatorConstructor(definition, stateFieldAndDescriptors, lambdaProviderFields, callSiteBinder);
generateCopyConstructor(definition, stateFieldAndDescriptors, lambdaProviderFields);
// Generate methods
generateCopy(definition, WindowAccumulator.class);
generateAddOrRemoveInputWindowIndex(definition, stateFields, argumentNullable, lambdaProviderFields, metadata.getInputFunction(), "addInput", callSiteBinder);
metadata.getRemoveInputFunction().ifPresent(removeInputFunction -> generateAddOrRemoveInputWindowIndex(definition, stateFields, argumentNullable, lambdaProviderFields, removeInputFunction, "removeInput", callSiteBinder));
generateEvaluateFinal(definition, stateFields, metadata.getOutputFunction(), callSiteBinder);
generateGetEstimatedSize(definition, stateFields);
Class<? extends WindowAccumulator> windowAccumulatorClass = defineClass(definition, WindowAccumulator.class, callSiteBinder.getBindings(), classLoader);
try {
return windowAccumulatorClass.getConstructor(List.class);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
use of io.airlift.bytecode.DynamicClassLoader in project trino by trinodb.
the class TestAccumulatorCompiler method testAccumulatorCompilerForTypeSpecificObjectParameterSeparateClassLoader.
@Test
public void testAccumulatorCompilerForTypeSpecificObjectParameterSeparateClassLoader() throws Exception {
TimestampType parameterType = TimestampType.TIMESTAMP_NANOS;
assertThat(parameterType.getJavaType()).isEqualTo(LongTimestamp.class);
ClassLoader pluginClassLoader = PluginManager.createClassLoader("test", ImmutableList.of());
DynamicClassLoader classLoader = new DynamicClassLoader(pluginClassLoader);
Class<? extends AccumulatorState> stateInterface = IsolatedClass.isolateClass(classLoader, AccumulatorState.class, LongTimestampAggregationState.class, LongTimestampAggregation.class);
assertThat(stateInterface.getCanonicalName()).isEqualTo(LongTimestampAggregationState.class.getCanonicalName());
assertThat(stateInterface).isNotSameAs(LongTimestampAggregationState.class);
Class<?> aggregation = classLoader.loadClass(LongTimestampAggregation.class.getCanonicalName());
assertThat(aggregation.getCanonicalName()).isEqualTo(LongTimestampAggregation.class.getCanonicalName());
assertThat(aggregation).isNotSameAs(LongTimestampAggregation.class);
assertGenerateAccumulator(aggregation, stateInterface);
}
use of io.airlift.bytecode.DynamicClassLoader in project hetu-core by openlookeng.
the class AbstractMinMaxBy method generateAggregation.
private InternalAggregationFunction generateAggregation(Type valueType, Type keyType, FunctionAndTypeManager functionAndTypeManager) {
Class<?> stateClazz = getStateClass(keyType.getJavaType(), valueType.getJavaType());
DynamicClassLoader classLoader = new DynamicClassLoader(getClass().getClassLoader());
// Generate states and serializers:
// For value that is a Block or Slice, we store them as Block/position combination
// to avoid generating long-living objects through getSlice or getObject.
// This can also help reducing cross-region reference in G1GC engine.
// TODO: keys can have the same problem. But usually they are primitive types (given the nature of comparison).
AccumulatorStateFactory<?> stateFactory;
AccumulatorStateSerializer<?> stateSerializer;
if (valueType.getJavaType().isPrimitive()) {
Map<String, Type> stateFieldTypes = ImmutableMap.of("First", keyType, "Second", valueType);
stateFactory = StateCompiler.generateStateFactory(stateClazz, stateFieldTypes, classLoader);
stateSerializer = StateCompiler.generateStateSerializer(stateClazz, stateFieldTypes, classLoader);
} else {
// StateCompiler checks type compatibility.
// Given "Second" in this case is always a Block, we only need to make sure the getter and setter of the Blocks are properly generated.
// We deliberately make "SecondBlock" an array type so that the compiler will treat it as a block to workaround the sanity check.
stateFactory = StateCompiler.generateStateFactory(stateClazz, ImmutableMap.of("First", keyType, "SecondBlock", new ArrayType(valueType)), classLoader);
// States can be generated by StateCompiler given the they are simply classes with getters and setters.
// However, serializers have logic in it. Creating serializers is better than generating them.
stateSerializer = getStateSerializer(keyType, valueType);
}
Type intermediateType = stateSerializer.getSerializedType();
List<Type> inputTypes = ImmutableList.of(valueType, keyType);
CallSiteBinder binder = new CallSiteBinder();
OperatorType operator = min ? LESS_THAN : GREATER_THAN;
MethodHandle compareMethod = functionAndTypeManager.getBuiltInScalarFunctionImplementation(functionAndTypeManager.resolveOperatorFunctionHandle(operator, TypeSignatureProvider.fromTypes(keyType, keyType))).getMethodHandle();
ClassDefinition definition = new ClassDefinition(a(PUBLIC, FINAL), makeClassName("processMaxOrMinBy"), type(Object.class));
definition.declareDefaultConstructor(a(PRIVATE));
generateInputMethod(definition, binder, compareMethod, keyType, valueType, stateClazz);
generateCombineMethod(definition, binder, compareMethod, keyType, valueType, stateClazz);
generateOutputMethod(definition, binder, valueType, stateClazz);
Class<?> generatedClass = defineClass(definition, Object.class, binder.getBindings(), classLoader);
MethodHandle inputMethod = methodHandle(generatedClass, "input", stateClazz, Block.class, Block.class, int.class);
MethodHandle combineMethod = methodHandle(generatedClass, "combine", stateClazz, stateClazz);
MethodHandle outputMethod = methodHandle(generatedClass, "output", stateClazz, BlockBuilder.class);
AggregationMetadata aggregationMetadata = new AggregationMetadata(generateAggregationName(getSignature().getNameSuffix(), valueType.getTypeSignature(), inputTypes.stream().map(Type::getTypeSignature).collect(toImmutableList())), createInputParameterMetadata(valueType, keyType), inputMethod, combineMethod, outputMethod, ImmutableList.of(new AccumulatorStateDescriptor(stateClazz, stateSerializer, stateFactory)), valueType);
GenericAccumulatorFactoryBinder factory = AccumulatorCompiler.generateAccumulatorFactoryBinder(aggregationMetadata, classLoader);
return new InternalAggregationFunction(getSignature().getNameSuffix(), inputTypes, ImmutableList.of(intermediateType), valueType, true, false, factory);
}
use of io.airlift.bytecode.DynamicClassLoader in project hetu-core by openlookeng.
the class AbstractMinMaxByNAggregationFunction method generateAggregation.
protected InternalAggregationFunction generateAggregation(Type valueType, Type keyType) {
DynamicClassLoader classLoader = new DynamicClassLoader(AbstractMinMaxNAggregationFunction.class.getClassLoader());
BlockComparator comparator = typeToComparator.apply(keyType);
List<Type> inputTypes = ImmutableList.of(valueType, keyType, BIGINT);
MinMaxByNStateSerializer stateSerializer = new MinMaxByNStateSerializer(comparator, keyType, valueType);
Type intermediateType = stateSerializer.getSerializedType();
ArrayType outputType = new ArrayType(valueType);
List<AggregationMetadata.ParameterMetadata> inputParameterMetadata = ImmutableList.of(new AggregationMetadata.ParameterMetadata(STATE), new AggregationMetadata.ParameterMetadata(NULLABLE_BLOCK_INPUT_CHANNEL, valueType), new AggregationMetadata.ParameterMetadata(BLOCK_INPUT_CHANNEL, keyType), new AggregationMetadata.ParameterMetadata(BLOCK_INDEX), new AggregationMetadata.ParameterMetadata(INPUT_CHANNEL, BIGINT));
AggregationMetadata metadata = new AggregationMetadata(generateAggregationName(name, valueType.getTypeSignature(), inputTypes.stream().map(Type::getTypeSignature).collect(toImmutableList())), inputParameterMetadata, INPUT_FUNCTION.bindTo(comparator).bindTo(valueType).bindTo(keyType), COMBINE_FUNCTION, OUTPUT_FUNCTION.bindTo(outputType), ImmutableList.of(new AccumulatorStateDescriptor(MinMaxByNState.class, stateSerializer, new MinMaxByNStateFactory())), outputType);
GenericAccumulatorFactoryBinder factory = AccumulatorCompiler.generateAccumulatorFactoryBinder(metadata, classLoader);
return new InternalAggregationFunction(name, inputTypes, ImmutableList.of(intermediateType), outputType, true, false, factory);
}
Aggregations