@Override public Size apply( MethodVisitor methodVisitor, Context implementationContext, MethodDescription instrumentedMethod) { StackManipulation thisReference = MethodVariableAccess.REFERENCE.loadOffset(0); FieldList<?> fieldList = instrumentedType.getDeclaredFields(); StackManipulation[] fieldLoading = new StackManipulation[fieldList.size()]; int index = 0; for (FieldDescription fieldDescription : fieldList) { fieldLoading[index] = new StackManipulation.Compound( thisReference, MethodVariableAccess.forType(fieldDescription.getType().asErasure()) .loadOffset(instrumentedMethod.getParameters().get(index).getOffset()), FieldAccess.forField(fieldDescription).putter()); index++; } StackManipulation.Size stackSize = new StackManipulation.Compound( thisReference, MethodInvocation.invoke(ConstructorCall.INSTANCE.objectTypeDefaultConstructor), new StackManipulation.Compound(fieldLoading), MethodReturn.VOID) .apply(methodVisitor, implementationContext); return new Size(stackSize.getMaximalSize(), instrumentedMethod.getStackSize()); }
@Override public MethodDelegationBinder.ParameterBinding<?> bind( AnnotationDescription.Loadable<FieldValue> annotation, MethodDescription source, ParameterDescription target, Implementation.Target implementationTarget, Assigner assigner) { FieldLocator.Resolution resolution = FieldLocator.of( annotation.getValue(DEFINING_TYPE, TypeDescription.class), implementationTarget.getTypeDescription()) .resolve(annotation.getValue(FIELD_NAME, String.class), source.isStatic()); if (resolution.isResolved()) { StackManipulation stackManipulation = new StackManipulation.Compound( resolution.getFieldDescription().isStatic() ? StackManipulation.Trivial.INSTANCE : MethodVariableAccess.REFERENCE.loadOffset(0), FieldAccess.forField(resolution.getFieldDescription()).getter(), assigner.assign( resolution.getFieldDescription().getType().asErasure(), target.getType().asErasure(), RuntimeType.Verifier.check(target))); return stackManipulation.isValid() ? new MethodDelegationBinder.ParameterBinding.Anonymous(stackManipulation) : MethodDelegationBinder.ParameterBinding.Illegal.INSTANCE; } else { return MethodDelegationBinder.ParameterBinding.Illegal.INSTANCE; } }
private void buildCopyStack( List<StackManipulation> stack, int iterations, Method getMethod, Method putMethod, long stride) throws NoSuchFieldException, NoSuchMethodException { final Field unsafeField = UnsafeCopier.class.getDeclaredField("unsafe"); final StackManipulation copyStack = new StackManipulation.Compound( // unsafe.putLong(dest, destOffset, unsafe.getLong(src)); MethodVariableAccess.REFERENCE.loadOffset(0), // ALOAD 0 this FieldAccess.forField(new FieldDescription.ForLoadedField(unsafeField)) .getter(), // GETFIELD MethodVariableAccess.REFERENCE.loadOffset(1), // ALOAD 1 dest MethodVariableAccess.LONG.loadOffset(4), // LLOAD 4 destOffset MethodVariableAccess.REFERENCE.loadOffset(0), // ALOAD 0 this FieldAccess.forField(new FieldDescription.ForLoadedField(unsafeField)) .getter(), // GETFIELD MethodVariableAccess.LONG.loadOffset(2), // LLOAD 2 src MethodInvocation.invoke(new MethodDescription.ForLoadedMethod(getMethod)), MethodInvocation.invoke(new MethodDescription.ForLoadedMethod(putMethod))); final StackManipulation incrementStack = new StackManipulation.Compound( // destOffset += 8; src += 8; MethodVariableAccess.LONG.loadOffset(4), // LLOAD 4 destOffset LongConstant.forValue(stride), // LDC 8 strideWidth LongAdd.INSTANCE, // LADD MethodVariableStore.LONG.storeOffset(4), // LSTORE 4 MethodVariableAccess.LONG.loadOffset(2), // LLOAD 2 src LongConstant.forValue(stride), // LDC 8 strideWidth LongAdd.INSTANCE, // LADD MethodVariableStore.LONG.storeOffset(2) // LSTORE 2 ); for (int i = 0; i < iterations; i++) { stack.add(copyStack); stack.add(incrementStack); } }