Search in sources :

Example 16 with DynamicClassLoader

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());
}
Also used : DynamicClassLoader(io.airlift.bytecode.DynamicClassLoader)

Example 17 with DynamicClassLoader

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);
    }
}
Also used : DynamicClassLoader(io.airlift.bytecode.DynamicClassLoader) AccumulatorStateDescriptor(io.trino.operator.aggregation.AggregationMetadata.AccumulatorStateDescriptor) FieldDefinition(io.airlift.bytecode.FieldDefinition) ArrayList(java.util.ArrayList) ClassDefinition(io.airlift.bytecode.ClassDefinition) CallSiteBinder(io.trino.sql.gen.CallSiteBinder) Supplier(java.util.function.Supplier)

Example 18 with DynamicClassLoader

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);
}
Also used : DynamicClassLoader(io.airlift.bytecode.DynamicClassLoader) TimestampType(io.trino.spi.type.TimestampType) DynamicClassLoader(io.airlift.bytecode.DynamicClassLoader) Test(org.testng.annotations.Test)

Example 19 with DynamicClassLoader

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);
}
Also used : DynamicClassLoader(io.airlift.bytecode.DynamicClassLoader) AccumulatorStateDescriptor(io.prestosql.operator.aggregation.AggregationMetadata.AccumulatorStateDescriptor) GenericAccumulatorFactoryBinder(io.prestosql.operator.aggregation.GenericAccumulatorFactoryBinder) ClassDefinition(io.airlift.bytecode.ClassDefinition) InternalAggregationFunction(io.prestosql.operator.aggregation.InternalAggregationFunction) OperatorType(io.prestosql.spi.function.OperatorType) ArrayType(io.prestosql.spi.type.ArrayType) SqlTypeBytecodeExpression.constantType(io.prestosql.sql.gen.SqlTypeBytecodeExpression.constantType) OperatorType(io.prestosql.spi.function.OperatorType) Type(io.prestosql.spi.type.Type) ArrayType(io.prestosql.spi.type.ArrayType) CallSiteBinder(io.prestosql.sql.gen.CallSiteBinder) AggregationMetadata(io.prestosql.operator.aggregation.AggregationMetadata) MethodHandle(java.lang.invoke.MethodHandle)

Example 20 with DynamicClassLoader

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);
}
Also used : DynamicClassLoader(io.airlift.bytecode.DynamicClassLoader) AccumulatorStateDescriptor(io.prestosql.operator.aggregation.AggregationMetadata.AccumulatorStateDescriptor) AbstractMinMaxNAggregationFunction(io.prestosql.operator.aggregation.AbstractMinMaxNAggregationFunction) GenericAccumulatorFactoryBinder(io.prestosql.operator.aggregation.GenericAccumulatorFactoryBinder) InternalAggregationFunction(io.prestosql.operator.aggregation.InternalAggregationFunction) ArrayType(io.prestosql.spi.type.ArrayType) Type(io.prestosql.spi.type.Type) ArrayType(io.prestosql.spi.type.ArrayType) BlockComparator(io.prestosql.operator.aggregation.BlockComparator) AggregationMetadata(io.prestosql.operator.aggregation.AggregationMetadata)

Aggregations

DynamicClassLoader (io.airlift.bytecode.DynamicClassLoader)38 Type (io.prestosql.spi.type.Type)20 AccumulatorStateDescriptor (io.prestosql.operator.aggregation.AggregationMetadata.AccumulatorStateDescriptor)19 MethodHandle (java.lang.invoke.MethodHandle)14 ClassDefinition (io.airlift.bytecode.ClassDefinition)11 ImmutableList (com.google.common.collect.ImmutableList)7 BytecodeBlock (io.airlift.bytecode.BytecodeBlock)7 MethodDefinition (io.airlift.bytecode.MethodDefinition)7 Parameter (io.airlift.bytecode.Parameter)7 Variable (io.airlift.bytecode.Variable)7 ArrayType (io.prestosql.spi.type.ArrayType)7 ImmutableList.toImmutableList (com.google.common.collect.ImmutableList.toImmutableList)5 Scope (io.airlift.bytecode.Scope)5 AggregationMetadata (io.prestosql.operator.aggregation.AggregationMetadata)5 ParameterMetadata (io.prestosql.operator.aggregation.AggregationMetadata.ParameterMetadata)5 GenericAccumulatorFactoryBinder (io.prestosql.operator.aggregation.GenericAccumulatorFactoryBinder)5 InternalAggregationFunction (io.prestosql.operator.aggregation.InternalAggregationFunction)5 IfStatement (io.airlift.bytecode.control.IfStatement)4 BytecodeExpression (io.airlift.bytecode.expression.BytecodeExpression)4 CallSiteBinder (io.trino.sql.gen.CallSiteBinder)4