Bug 139749 - @AspectJ aspect causes verify error if call to super method is made in around advice body
Summary: @AspectJ aspect causes verify error if call to super method is made in around...
Status: RESOLVED FIXED
Alias: None
Product: AspectJ
Classification: Tools
Component: Compiler (show other bugs)
Version: 1.5.1   Edit
Hardware: Macintosh Mac OS X - Carbon (unsup.)
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: aspectj inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-05-02 12:34 EDT by Adrian Colyer CLA
Modified: 2007-07-29 09:19 EDT (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Adrian Colyer CLA 2006-05-02 12:34:11 EDT
Given an @AspectJ aspect that extends from some super class, for example:

class ASuperClass {

  protected void takesAPjp(ProceedingJoinPoint pjp) {
     //...
  }

}

@Aspect
public class AroundAdvicePassingPjpAsArgToSuper extends ASuperClass {

  @Around("execution(* foo())")
  public Object passesPjp(ProceedingJoinPoint pjp) throws Throwable {
    takesAPjp(pjp);
    Object ret = pjp.proceed();
    return ret;
  }
}

The resulting compiled class gives a verify error on the generated ajc$inlineAccessMethod.

Overriding the method inside the aspect (and calling super within the overriden method) works just fine.
Comment 1 Adrian Colyer CLA 2006-05-02 13:01:56 EDT
see bugs152/pr139749 for test case to reproduce
Comment 2 Adrian Colyer CLA 2006-05-03 01:22:59 EDT
additional info... the problem only happens when the super-method is not public, thus forcing us to create the inline accessor. In the generated bytecode (extracted into a static method), we use the invokespecial instruction to call the super-type method, this instruction is not appropriate in the extracted context.

BcelAccessForInlineMunger has explicit handling for this case in the openAroundAdvice method (L168 "specific handling for super.foo() calls, where foo is non-public"). However, when compiling from @AspectJ, we never meet the guard condition for the special case logic (callee class name equals aspect supertype name). When compiling from regular AJ we *do* meet the guard. Forcing the execution down this branch does indeed produce correct code.

So the question becomes, why is it that in the @AspectJ style the callee type name is returning as the sub-aspect name, not the super-type name that would be required to execute the logic. I suspect a visitor in the AJ front-end compiler fixes this up... going to look.
Comment 3 Adrian Colyer CLA 2006-05-03 01:35:06 EDT
OK, as suspected, when we compile an AdviceDeclaration we run an AccessForInlineVisitor over it. One of the things this does is fix up MessageSends where send.isSuperAccess() is true. The binding is replaced with a getSuperAccessMethod that is generated, and the receiver is replaced with "this".

So in fact we never go down the special case route in BcelAccessForInline here either, because it is all handled for us upfront before we get there...
Comment 4 Adrian Colyer CLA 2006-05-03 01:44:04 EDT
... and with this information the problem is easily fixed by improving the test in BcelAccessForInlineMunger.openAroundAdvice. The old test compared the aspect supertype name against the class name of the invoke instruction target. This was failing to match, because we have an invokespecial with a target of the sub-aspect. Changing the test to match on the condition we really care about (does the aspect supertype name match the declaring type of the resolved member we are about to dispatch to) cause everything to work smoothly. 

This test will work for a super method in an immediate parent only. After verifying this change doesn't cause any test suite failures, I need to add another test with a three-level deep hierarchy and update the test to check whether the declaring type of the resolved member is an ancestor of the aspect type... this should be the correct long term fix.
Comment 5 Adrian Colyer CLA 2006-05-03 01:58:46 EDT
Even better news (and something I should have noticed to start with - but hey, I was doing this at 6am in the morning!), the BcelAccessForInlineMunger is *only* used for @AspectJ aspects. Which means two things:

1) it's very plausable there's a bug here which hasn't been exercised before (would have been much less likely in AJ style code paths)
2) the fix is localized to only affect @AspectJ declared advice

I fear I'm turning into Andy Clement with all this commentary... ;)
Comment 6 Adrian Colyer CLA 2006-05-03 02:37:01 EDT
Test failure... excellent (!). The test suite already had the super-super method case in it. Just not the direct super case that I stumbled upon.

Changed the test to check for (!aspectType.equals(memberType) && memberType.isAssignableFrom(aspectType)). All tests now pass.

Fix commited in tree. 
Comment 7 Adrian Colyer CLA 2006-05-03 04:36:45 EDT
Fix now available in latest dev build
Comment 8 Eclipse Webmaster CLA 2007-07-29 09:19:44 EDT
Changing OS from Mac OS to Mac OS X as per bug 185991