use of net.bytebuddy.implementation.bytecode.StackManipulation in project beam by apache.
the class ByteBuddyUtils method createCollectionTransformFunction.
// When processing a container (e.g. List<T>) we need to recursively process the element type.
// This function
// generates a subclass of Function that can be used to recursively transform each element of the
// container.
static Class createCollectionTransformFunction(Type fromType, Type toType, Function<StackManipulation, StackManipulation> convertElement) {
// Generate a TypeDescription for the class we want to generate.
TypeDescription.Generic functionGenericType = TypeDescription.Generic.Builder.parameterizedType(Function.class, Primitives.wrap((Class) fromType), Primitives.wrap((Class) toType)).build();
DynamicType.Builder<Function> builder = (DynamicType.Builder<Function>) BYTE_BUDDY.with(new InjectPackageStrategy((Class) fromType)).subclass(functionGenericType).method(ElementMatchers.named("apply")).intercept(new Implementation() {
@Override
public ByteCodeAppender appender(Target target) {
return (methodVisitor, implementationContext, instrumentedMethod) -> {
// this + method parameters.
int numLocals = 1 + instrumentedMethod.getParameters().size();
StackManipulation readValue = MethodVariableAccess.REFERENCE.loadFrom(1);
StackManipulation stackManipulation = new StackManipulation.Compound(convertElement.apply(readValue), MethodReturn.REFERENCE);
StackManipulation.Size size = stackManipulation.apply(methodVisitor, implementationContext);
return new ByteCodeAppender.Size(size.getMaximalSize(), numLocals);
};
}
@Override
public InstrumentedType prepare(InstrumentedType instrumentedType) {
return instrumentedType;
}
});
return builder.visit(new AsmVisitorWrapper.ForDeclaredMethods().writerFlags(ClassWriter.COMPUTE_FRAMES)).make().load(ReflectHelpers.findClassLoader(((Class) fromType).getClassLoader()), ClassLoadingStrategy.Default.INJECTION).getLoaded();
}
use of net.bytebuddy.implementation.bytecode.StackManipulation in project beam by apache.
the class AvroByteBuddyUtils method readAndConvertParameter.
private static StackManipulation readAndConvertParameter(Class<?> constructorParameterType, int index) {
TypeConversionsFactory typeConversionsFactory = new AvroTypeConversionFactory();
// The types in the AVRO-generated constructor might be the types returned by Beam's Row class,
// so we have to convert the types used by Beam's Row class.
// We know that AVRO generates constructor parameters in the same order as fields
// in the schema, so we can just add the parameters sequentially.
TypeConversion<Type> convertType = typeConversionsFactory.createTypeConversion(true);
// Map the AVRO-generated type to the one Beam will use.
ForLoadedType convertedType = new ForLoadedType((Class) convertType.convert(TypeDescriptor.of(constructorParameterType)));
// This will run inside the generated creator. Read the parameter and convert it to the
// type required by the SpecificRecord constructor.
StackManipulation readParameter = new StackManipulation.Compound(MethodVariableAccess.REFERENCE.loadFrom(1), IntegerConstant.forValue(index), ArrayAccess.REFERENCE.load(), TypeCasting.to(convertedType));
// Convert to the parameter accepted by the SpecificRecord constructor.
return typeConversionsFactory.createSetterConversions(readParameter).convert(TypeDescriptor.of(constructorParameterType));
}
use of net.bytebuddy.implementation.bytecode.StackManipulation in project byte-buddy by raphw.
the class FixedValue method apply.
/**
* Blueprint method that for applying the actual implementation.
*
* @param methodVisitor The method visitor to which the implementation is applied to.
* @param implementationContext The implementation context for the given implementation.
* @param instrumentedMethod The instrumented method that is target of the implementation.
* @param fixedValueType A description of the type of the fixed value that is loaded by the
* {@code valueLoadingInstruction}.
* @param valueLoadingInstruction A stack manipulation that represents the loading of the fixed value onto the
* operand stack.
* @return A representation of the stack and variable array sized that are required for this implementation.
*/
protected ByteCodeAppender.Size apply(MethodVisitor methodVisitor, Context implementationContext, MethodDescription instrumentedMethod, TypeDescription.Generic fixedValueType, StackManipulation valueLoadingInstruction) {
StackManipulation assignment = assigner.assign(fixedValueType, instrumentedMethod.getReturnType(), typing);
if (!assignment.isValid()) {
throw new IllegalArgumentException("Cannot return value of type " + fixedValueType + " for " + instrumentedMethod);
}
StackManipulation.Size stackSize = new StackManipulation.Compound(valueLoadingInstruction, assignment, MethodReturn.of(instrumentedMethod.getReturnType())).apply(methodVisitor, implementationContext);
return new ByteCodeAppender.Size(stackSize.getMaximalSize(), instrumentedMethod.getStackSize());
}
use of net.bytebuddy.implementation.bytecode.StackManipulation in project byte-buddy by raphw.
the class MethodDelegationBinderTerminationHandlerTest method testReturning.
@Test
public void testReturning() throws Exception {
when(source.getReturnType()).thenReturn(genericSourceType);
when(target.getReturnType()).thenReturn(genericTargetType);
when(genericSourceType.asErasure()).thenReturn(sourceType);
when(genericTargetType.asErasure()).thenReturn(targetType);
when(assigner.assign(genericTargetType, genericSourceType, Assigner.Typing.STATIC)).thenReturn(stackManipulation);
StackManipulation stackManipulation = MethodDelegationBinder.TerminationHandler.Default.RETURNING.resolve(assigner, Assigner.Typing.STATIC, source, target);
assertThat(stackManipulation, is((StackManipulation) new StackManipulation.Compound(this.stackManipulation, MethodReturn.REFERENCE)));
verify(assigner).assign(genericTargetType, genericSourceType, Assigner.Typing.STATIC);
}
use of net.bytebuddy.implementation.bytecode.StackManipulation in project byte-buddy by raphw.
the class TypeProxyCreationTest method testForReflectionFactoryConstruction.
@Test
public void testForReflectionFactoryConstruction() throws Exception {
when(implementationTarget.getInstrumentedType()).thenReturn(foo);
when(invocationFactory.invoke(eq(implementationTarget), eq(foo), any(MethodDescription.class))).thenReturn(specialMethodInvocation);
when(specialMethodInvocation.isValid()).thenReturn(true);
when(specialMethodInvocation.apply(any(MethodVisitor.class), any(Implementation.Context.class))).thenReturn(new StackManipulation.Size(0, 0));
when(methodAccessorFactory.registerAccessorFor(specialMethodInvocation, MethodAccessorFactory.AccessType.DEFAULT)).thenReturn(proxyMethod);
StackManipulation stackManipulation = new TypeProxy.ForSuperMethodByReflectionFactory(foo, implementationTarget, true, false);
MethodVisitor methodVisitor = mock(MethodVisitor.class);
Implementation.Context implementationContext = mock(Implementation.Context.class);
when(implementationContext.register(any(AuxiliaryType.class))).thenReturn(new TypeDescription.ForLoadedType(FooProxyMake.class));
assertThat(stackManipulation.isValid(), is(true));
StackManipulation.Size size = stackManipulation.apply(methodVisitor, implementationContext);
assertThat(size.getSizeImpact(), is(1));
assertThat(size.getMaximalSize(), is(3));
verify(implementationContext).register(any(AuxiliaryType.class));
verifyNoMoreInteractions(implementationContext);
verify(methodVisitor).visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(FooProxyMake.class), TypeProxy.REFLECTION_METHOD, Type.getMethodDescriptor(FooProxyMake.class.getDeclaredMethod("make")), false);
verify(methodVisitor).visitInsn(Opcodes.DUP);
verify(methodVisitor).visitFieldInsn(Opcodes.PUTFIELD, Type.getInternalName(FooProxyMake.class), TypeProxy.INSTANCE_FIELD, Type.getDescriptor(Void.class));
verify(methodVisitor).visitVarInsn(Opcodes.ALOAD, 0);
verifyNoMoreInteractions(methodVisitor);
}
Aggregations