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);
    }
  }
  private void buildSetupStack(List<StackManipulation> stack)
      throws NoSuchFieldException, NoSuchMethodException {

    final StackManipulation setupStack =
        new StackManipulation.Compound(
            LongConstant.forValue(offset), // LDC offset
            MethodVariableStore.LONG.storeOffset(4) // LSTORE 4
            );

    stack.add(setupStack);
  }
예제 #3
0
 /**
  * Returns a fixed value from any intercepted method. The fixed value is stored in the constant
  * pool if this is possible. Java is capable of storing any primitive value, {@link String} values
  * and {@link Class} references in the constant pool. Since Java 7, {@code MethodHandle} as well
  * as {@code MethodType} references are also supported. Alternatively, the fixed value is stored
  * in a static field.
  *
  * <p>When a value is stored in the class's constant pool, its identity is lost. If an object's
  * identity is important, the {@link FixedValue#reference(Object)} method should be used instead.
  *
  * @param fixedValue The fixed value to return from the method.
  * @return An implementation for the given {@code fixedValue}.
  */
 public static AssignerConfigurable value(Object fixedValue) {
   Class<?> type = fixedValue.getClass();
   if (type == String.class) {
     return new ForPoolValue(
         new TextConstant((String) fixedValue),
         TypeDescription.STRING,
         Assigner.DEFAULT,
         Assigner.Typing.STATIC);
   } else if (type == Class.class) {
     return new ForPoolValue(
         ClassConstant.of(new TypeDescription.ForLoadedType((Class<?>) fixedValue)),
         TypeDescription.CLASS,
         Assigner.DEFAULT,
         Assigner.Typing.STATIC);
   } else if (type == Boolean.class) {
     return new ForPoolValue(
         IntegerConstant.forValue((Boolean) fixedValue),
         new TypeDescription.ForLoadedType(boolean.class),
         Assigner.DEFAULT,
         Assigner.Typing.STATIC);
   } else if (type == Byte.class) {
     return new ForPoolValue(
         IntegerConstant.forValue((Byte) fixedValue),
         new TypeDescription.ForLoadedType(byte.class),
         Assigner.DEFAULT,
         Assigner.Typing.STATIC);
   } else if (type == Short.class) {
     return new ForPoolValue(
         IntegerConstant.forValue((Short) fixedValue),
         new TypeDescription.ForLoadedType(short.class),
         Assigner.DEFAULT,
         Assigner.Typing.STATIC);
   } else if (type == Character.class) {
     return new ForPoolValue(
         IntegerConstant.forValue((Character) fixedValue),
         new TypeDescription.ForLoadedType(char.class),
         Assigner.DEFAULT,
         Assigner.Typing.STATIC);
   } else if (type == Integer.class) {
     return new ForPoolValue(
         IntegerConstant.forValue((Integer) fixedValue),
         new TypeDescription.ForLoadedType(int.class),
         Assigner.DEFAULT,
         Assigner.Typing.STATIC);
   } else if (type == Long.class) {
     return new ForPoolValue(
         LongConstant.forValue((Long) fixedValue),
         new TypeDescription.ForLoadedType(long.class),
         Assigner.DEFAULT,
         Assigner.Typing.STATIC);
   } else if (type == Float.class) {
     return new ForPoolValue(
         FloatConstant.forValue((Float) fixedValue),
         new TypeDescription.ForLoadedType(float.class),
         Assigner.DEFAULT,
         Assigner.Typing.STATIC);
   } else if (type == Double.class) {
     return new ForPoolValue(
         DoubleConstant.forValue((Double) fixedValue),
         new TypeDescription.ForLoadedType(double.class),
         Assigner.DEFAULT,
         Assigner.Typing.STATIC);
   } else if (JavaType.METHOD_HANDLE.getTypeStub().isAssignableFrom(type)) {
     return new ForPoolValue(
         MethodHandleConstant.of(JavaInstance.MethodHandle.of(fixedValue)),
         new TypeDescription.ForLoadedType(type),
         Assigner.DEFAULT,
         Assigner.Typing.STATIC);
   } else if (JavaType.METHOD_TYPE.getTypeStub().represents(type)) {
     return new ForPoolValue(
         MethodTypeConstant.of(JavaInstance.MethodType.of(fixedValue)),
         new TypeDescription.ForLoadedType(type),
         Assigner.DEFAULT,
         Assigner.Typing.STATIC);
   } else {
     return reference(fixedValue);
   }
 }