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); }
/** * 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); } }