@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);
    }
  }