-
- private static final class CodecHashCode implements ByteCodeAppender {
- private static final StackManipulation THIRTY_ONE = IntegerConstant.forValue(31);
- private static final StackManipulation LOAD_RESULT = MethodVariableAccess.INTEGER.loadFrom(1);
- private static final StackManipulation STORE_RESULT = MethodVariableAccess.INTEGER.storeAt(1);
- private static final StackManipulation ARRAYS_HASHCODE = invokeMethod(Arrays.class, "hashCode", byte[].class);
- private static final StackManipulation OBJECTS_HASHCODE = invokeMethod(Objects.class, "hashCode", Object.class);
-
- private final ImmutableMap<StackManipulation, Method> properties;
-
- CodecHashCode(final ImmutableMap<StackManipulation, Method> properties) {
- this.properties = requireNonNull(properties);
- }
-
- @Override
- public Size apply(final MethodVisitor methodVisitor, final Context implementationContext,
- final MethodDescription instrumentedMethod) {
- final List<StackManipulation> manipulations = new ArrayList<>(properties.size() * 8 + 4);
- // int result = 1;
- manipulations.add(IntegerConstant.ONE);
- manipulations.add(STORE_RESULT);
-
- for (Entry<StackManipulation, Method> entry : properties.entrySet()) {
- // result = 31 * result + java.util.(Objects,Arrays).hashCode(getFoo());
- manipulations.add(THIRTY_ONE);
- manipulations.add(LOAD_RESULT);
- manipulations.add(Multiplication.INTEGER);
- manipulations.add(THIS);
- manipulations.add(entry.getKey());
- manipulations.add(entry.getValue().getReturnType().isArray() ? ARRAYS_HASHCODE : OBJECTS_HASHCODE);
- manipulations.add(Addition.INTEGER);
- manipulations.add(STORE_RESULT);
- }
- // return result;
- manipulations.add(LOAD_RESULT);
- manipulations.add(MethodReturn.INTEGER);
-
- StackManipulation.Size operandStackSize = new StackManipulation.Compound(manipulations)
- .apply(methodVisitor, implementationContext);
- return new Size(operandStackSize.getMaximalSize(), instrumentedMethod.getStackSize() + 1);
- }
- }