예제 #1
0
 @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());
 }
예제 #2
0
 @Override
 public Size apply(
     MethodVisitor methodVisitor,
     Context implementationContext,
     MethodDescription instrumentedMethod) {
   StackManipulation thisReference =
       MethodVariableAccess.forType(instrumentedType).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, FieldAccess.forField(fieldDescription).getter());
   }
   StackManipulation.Size stackSize =
       new StackManipulation.Compound(
               new StackManipulation.Compound(fieldLoading),
               MethodInvocation.invoke(accessorMethod),
               assigner.assign(
                   accessorMethod.getReturnType().asErasure(),
                   instrumentedMethod.getReturnType().asErasure(),
                   Assigner.Typing.DYNAMIC),
               MethodReturn.returning(instrumentedMethod.getReturnType().asErasure()))
           .apply(methodVisitor, implementationContext);
   return new Size(stackSize.getMaximalSize(), instrumentedMethod.getStackSize());
 }
 @Test
 public void testBoxing() throws Exception {
   StackManipulation boxingStackManipulation =
       PrimitiveBoxingDelegate.forPrimitive(primitiveTypeDescription)
           .assignBoxedTo(targetType, chainedAssigner, Assigner.Typing.STATIC);
   assertThat(boxingStackManipulation.isValid(), is(true));
   StackManipulation.Size size =
       boxingStackManipulation.apply(methodVisitor, implementationContext);
   assertThat(size.getSizeImpact(), is(sizeChange));
   assertThat(size.getMaximalSize(), is(0));
   verify(primitiveTypeDescription).represents(primitiveType);
   verify(primitiveTypeDescription, atLeast(1)).represents(any(Class.class));
   verifyNoMoreInteractions(primitiveTypeDescription);
   verify(chainedAssigner)
       .assign(referenceTypeDescription.asGenericType(), targetType, Assigner.Typing.STATIC);
   verifyNoMoreInteractions(chainedAssigner);
   verify(methodVisitor)
       .visitMethodInsn(
           Opcodes.INVOKESTATIC,
           referenceTypeDescription.getInternalName(),
           VALUE_OF,
           boxingMethodDescriptor,
           false);
   verifyNoMoreInteractions(methodVisitor);
   verify(stackManipulation, atLeast(1)).isValid();
   verify(stackManipulation).apply(methodVisitor, implementationContext);
   verifyNoMoreInteractions(stackManipulation);
 }
 @Test
 public void testLegalSlackBinding() throws Exception {
   when(target.getIndex()).thenReturn(1);
   when(annotation.value()).thenReturn(AllArguments.Assignment.SLACK);
   when(stackManipulation.isValid()).thenReturn(false);
   when(source.getParameters())
       .thenReturn(new ParameterList.Explicit.ForTypes(source, firstSourceType, secondSourceType));
   when(source.isStatic()).thenReturn(false);
   when(targetType.isArray()).thenReturn(true);
   when(targetType.getComponentType()).thenReturn(componentType);
   when(componentType.getStackSize()).thenReturn(StackSize.SINGLE);
   when(target.getType()).thenReturn(targetType);
   when(target.getDeclaredAnnotations()).thenReturn(new AnnotationList.Empty());
   when(rawComponentType.getInternalName()).thenReturn(FOO);
   MethodDelegationBinder.ParameterBinding<?> parameterBinding =
       AllArguments.Binder.INSTANCE.bind(
           annotationDescription, source, target, implementationTarget, assigner);
   MethodVisitor methodVisitor = mock(MethodVisitor.class);
   Implementation.Context implementationContext = mock(Implementation.Context.class);
   StackManipulation.Size size = parameterBinding.apply(methodVisitor, implementationContext);
   assertThat(size.getSizeImpact(), is(1));
   assertThat(size.getMaximalSize(), is(1));
   verify(methodVisitor).visitInsn(Opcodes.ICONST_0);
   verify(methodVisitor).visitTypeInsn(Opcodes.ANEWARRAY, FOO);
   verifyNoMoreInteractions(methodVisitor);
   verifyZeroInteractions(implementationContext);
   assertThat(parameterBinding.isValid(), is(true));
   verify(source, atLeast(1)).getParameters();
   verify(source, atLeast(1)).isStatic();
   verify(target, atLeast(1)).getType();
   verify(target, atLeast(1)).getDeclaredAnnotations();
   verify(assigner).assign(firstSourceType, componentType, Assigner.Typing.STATIC);
   verify(assigner).assign(secondSourceType, componentType, Assigner.Typing.STATIC);
   verifyNoMoreInteractions(assigner);
 }
 @Test
 public void testAssignmentEqual() throws Exception {
   StackManipulation stackManipulation =
       Assigner.EqualTypesOnly.INSTANCE.assign(first, first, dynamicallyTyped);
   assertThat(stackManipulation.isValid(), is(true));
   StackManipulation.Size size = stackManipulation.apply(methodVisitor, implementationContext);
   assertThat(size.getSizeImpact(), is(0));
   assertThat(size.getMaximalSize(), is(0));
 }
 @Test
 public void testPrimitiveAssignabilityWhenEqual() throws Exception {
   TypeDescription primitiveType =
       new TypeDescription.ForLoadedType(int.class); // Note: cannot mock equals
   StackManipulation stackManipulation =
       ReferenceTypeAwareAssigner.INSTANCE.assign(primitiveType, primitiveType, true);
   assertThat(stackManipulation.isValid(), is(true));
   StackManipulation.Size size = stackManipulation.apply(methodVisitor, implementationContext);
   assertThat(size.getSizeImpact(), is(0));
   assertThat(size.getMaximalSize(), is(0));
   verifyZeroInteractions(methodVisitor);
 }
 @Test
 public void testSourceToTargetAssignable() throws Exception {
   defineAssignability(true, false);
   StackManipulation stackManipulation =
       ReferenceTypeAwareAssigner.INSTANCE.assign(
           sourceTypeDescription, targetTypeDescription, false);
   assertThat(stackManipulation.isValid(), is(true));
   StackManipulation.Size size = stackManipulation.apply(methodVisitor, implementationContext);
   assertThat(size.getSizeImpact(), is(0));
   assertThat(size.getMaximalSize(), is(0));
   verifyZeroInteractions(methodVisitor);
 }
 @Test
 public void testTargetToSourceAssignableRuntimeType() throws Exception {
   defineAssignability(false, false);
   when(targetTypeDescription.getInternalName()).thenReturn(FOO);
   StackManipulation stackManipulation =
       ReferenceTypeAwareAssigner.INSTANCE.assign(
           sourceTypeDescription, targetTypeDescription, true);
   assertThat(stackManipulation.isValid(), is(true));
   StackManipulation.Size size = stackManipulation.apply(methodVisitor, implementationContext);
   assertThat(size.getSizeImpact(), is(0));
   assertThat(size.getMaximalSize(), is(0));
   verify(methodVisitor).visitTypeInsn(Opcodes.CHECKCAST, FOO);
   verifyNoMoreInteractions(methodVisitor);
 }
 @Test
 public void testSuperConstructorIsInvokable() throws Exception {
   when(superMethod.isConstructor()).thenReturn(true);
   Implementation.SpecialMethodInvocation specialMethodInvocation =
       implementationTarget.invokeSuper(superMethod, methodLookup);
   assertThat(specialMethodInvocation.isValid(), is(true));
   assertThat(specialMethodInvocation.getMethodDescription(), is(superMethodConstructor));
   assertThat(specialMethodInvocation.getTypeDescription(), is(superType));
   MethodVisitor methodVisitor = mock(MethodVisitor.class);
   Implementation.Context implementationContext = mock(Implementation.Context.class);
   StackManipulation.Size size =
       specialMethodInvocation.apply(methodVisitor, implementationContext);
   verify(methodVisitor).visitMethodInsn(Opcodes.INVOKESPECIAL, BAR, QUXBAZ, BAZBAR, false);
   verifyNoMoreInteractions(methodVisitor);
   verifyZeroInteractions(implementationContext);
   assertThat(size.getSizeImpact(), is(0));
   assertThat(size.getMaximalSize(), is(0));
 }
  public Size apply(
      MethodVisitor methodVisitor,
      Implementation.Context implementationContext,
      MethodDescription instrumentedMethod) {

    checkMethodSignature(instrumentedMethod);

    try {
      StackManipulation stack = buildStack();
      StackManipulation.Size finalStackSize = stack.apply(methodVisitor, implementationContext);

      return new Size(
          finalStackSize.getMaximalSize(),
          instrumentedMethod.getStackSize() + 2); // 2 stack slots for a single local variable

    } catch (NoSuchMethodException | NoSuchFieldException e) {
      throw new RuntimeException(e);
    }
  }
예제 #11
0
 /**
  * Blueprint method that for applying the actual implementation.
  *
  * @param methodVisitor The method visitor to which the implementation is applied to.
  * @param implementationContext The implementation context for the given implementation.
  * @param instrumentedMethod The instrumented method that is target of the implementation.
  * @param fixedValueType A description of the type of the fixed value that is loaded by the {@code
  *     valueLoadingInstruction}.
  * @param valueLoadingInstruction A stack manipulation that represents the loading of the fixed
  *     value onto the operand stack.
  * @return A representation of the stack and variable array sized that are required for this
  *     implementation.
  */
 protected ByteCodeAppender.Size apply(
     MethodVisitor methodVisitor,
     Context implementationContext,
     MethodDescription instrumentedMethod,
     TypeDescription.Generic fixedValueType,
     StackManipulation valueLoadingInstruction) {
   StackManipulation assignment =
       assigner.assign(fixedValueType, instrumentedMethod.getReturnType(), typing);
   if (!assignment.isValid()) {
     throw new IllegalArgumentException(
         "Cannot return value of type " + fixedValueType + " for " + instrumentedMethod);
   }
   StackManipulation.Size stackSize =
       new StackManipulation.Compound(
               valueLoadingInstruction,
               assignment,
               MethodReturn.returning(instrumentedMethod.getReturnType().asErasure()))
           .apply(methodVisitor, implementationContext);
   return new ByteCodeAppender.Size(stackSize.getMaximalSize(), instrumentedMethod.getStackSize());
 }
 @Test
 public void testPreservation() throws Exception {
   MethodRebaseResolver.Resolution resolution =
       new MethodRebaseResolver.Resolution.ForRebasedMethod(
           methodDescription, methodNameTransformer);
   assertThat(resolution.isRebased(), is(true));
   assertThat(resolution.getResolvedMethod().getDeclaringType(), is(typeDescription));
   assertThat(resolution.getResolvedMethod().getInternalName(), is(QUX));
   assertThat(
       resolution.getResolvedMethod().getModifiers(),
       is(MethodRebaseResolver.REBASED_METHOD_MODIFIER));
   assertThat(resolution.getResolvedMethod().getReturnType(), is(returnType));
   assertThat(
       resolution.getResolvedMethod().getParameters(),
       is(
           ParameterList.Explicit.latent(
               resolution.getResolvedMethod(), Collections.singletonList(parameterType))));
   StackManipulation.Size size =
       resolution.getAdditionalArguments().apply(methodVisitor, implementationContext);
   assertThat(size.getSizeImpact(), is(0));
   assertThat(size.getMaximalSize(), is(0));
   verifyZeroInteractions(methodVisitor);
   verifyZeroInteractions(implementationContext);
 }