public <T> AccumulatorStateSerializer<T> generateStateSerializer( Class<T> clazz, DynamicClassLoader classLoader) { AccumulatorStateMetadata metadata = getMetadataAnnotation(clazz); if (metadata != null && metadata.stateSerializerClass() != void.class) { try { return (AccumulatorStateSerializer<T>) metadata.stateSerializerClass().getConstructor().newInstance(); } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { throw Throwables.propagate(e); } } ClassDefinition definition = new ClassDefinition( a(PUBLIC, FINAL), makeClassName(clazz.getSimpleName() + "Serializer"), type(Object.class), type(AccumulatorStateSerializer.class)); CallSiteBinder callSiteBinder = new CallSiteBinder(); // Generate constructor definition.declareDefaultConstructor(a(PUBLIC)); List<StateField> fields = enumerateFields(clazz); generateGetSerializedType(definition, fields, callSiteBinder); generateSerialize(definition, clazz, fields); generateDeserialize(definition, clazz, fields); Class<? extends AccumulatorStateSerializer> serializerClass = defineClass( definition, AccumulatorStateSerializer.class, callSiteBinder.getBindings(), classLoader); try { return (AccumulatorStateSerializer<T>) serializerClass.newInstance(); } catch (InstantiationException | IllegalAccessException e) { throw Throwables.propagate(e); } }
private static Class<?> generateArrayConstructor(List<Class<?>> stackTypes, Type elementType) { List<String> stackTypeNames = stackTypes.stream().map(Class::getSimpleName).collect(toImmutableList()); ClassDefinition definition = new ClassDefinition( a(PUBLIC, FINAL), CompilerUtils.makeClassName(Joiner.on("").join(stackTypeNames) + "ArrayConstructor"), type(Object.class)); // Generate constructor definition.declareDefaultConstructor(a(PRIVATE)); // Generate arrayConstructor() ImmutableList.Builder<Parameter> parameters = ImmutableList.builder(); for (int i = 0; i < stackTypes.size(); i++) { Class<?> stackType = stackTypes.get(i); parameters.add(arg("arg" + i, stackType)); } MethodDefinition method = definition.declareMethod( a(PUBLIC, STATIC), "arrayConstructor", type(Slice.class), parameters.build()); Scope scope = method.getScope(); Block body = method.getBody(); Variable elementTypeVariable = scope.declareVariable(Type.class, "elementTypeVariable"); CallSiteBinder binder = new CallSiteBinder(); body.comment("elementTypeVariable = elementType;") .append(constantType(binder, elementType)) .putVariable(elementTypeVariable); Variable valuesVariable = scope.declareVariable(List.class, "values"); body.comment("List<Object> values = new ArrayList();") .newObject(ArrayList.class) .dup() .invokeConstructor(ArrayList.class) .putVariable(valuesVariable); for (int i = 0; i < stackTypes.size(); i++) { body.comment("values.add(arg%d);", i) .getVariable(valuesVariable) .append(scope.getVariable("arg" + i)); Class<?> stackType = stackTypes.get(i); if (stackType.isPrimitive()) { body.append(ByteCodeUtils.boxPrimitiveIfNecessary(scope, stackType)); } body.invokeInterface(List.class, "add", boolean.class, Object.class); } body.comment("return toStackRepresentation(values, elementType);") .getVariable(valuesVariable) .getVariable(elementTypeVariable) .invokeStatic(ArrayType.class, "toStackRepresentation", Slice.class, List.class, Type.class) .retObject(); return defineClass( definition, Object.class, binder.getBindings(), new DynamicClassLoader(ArrayConstructor.class.getClassLoader())); }