Browse Source

inlining of around for @AJ works unless non public member accessed from within the advice

splitted ajc150 xml test file
tags/PRE_ANDY
avasseur 19 years ago
parent
commit
fd380fe072

+ 15
- 0
testing/newsrc/org/aspectj/testing/AutowiredXMLBasedAjcTestCase.java View File

@@ -135,5 +135,20 @@ public abstract class AutowiredXMLBasedAjcTestCase extends XMLBasedAjcTestCase {
super.setUp();
}

/**
* This helper method runs the test with the given title in the
* suite spec file. All tests steps in given ajc-test execute
* in the same sandbox.
*/
protected void runTest(String title) {
AjcTest currentTest = (AjcTest) testMap.get(title);
if (currentTest == null) {
fail("No test '" + title + "' in suite.");
}
ajc.setShouldEmptySandbox(true);
currentTest.runTest(this);
}



}

+ 103
- 0
tests/java5/ataspectj/ataspectj/BindingTest.java View File

@@ -17,10 +17,13 @@ import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Aspects;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

import java.security.PrivilegedAction;

/**
* @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
*/
@@ -43,6 +46,10 @@ public class BindingTest extends TestCase {
return i*3;//see x3 here
}

public int echo(int i) {
return i;
}

public void testAroundArgs() {
int res = substract(3, 2);// should be 2 without around advice
assertEquals(1, res);
@@ -54,6 +61,35 @@ public class BindingTest extends TestCase {
callWithinStatic();
}

public void testProceedInInner() {
int res = echo(3);//advice will x2 using an inner
assertEquals(6, res);
}

public void testNoProceed() {
int res = echo(3);//advice will return 0 and not proceed
assertEquals(0, res);
}

public void testDoubleProceed() {
int res = echo(3);//advice will proceed twice and add the returned values
assertEquals(6, res);
}

public void testDoubleProceedOneInner() {
int res = echo(3);//advice will proceed twice with one in inner and add the returned values
assertEquals(6, res);
}

public void testAccessAspectState() {
//TestAspect_1 aspect = (TestAspect_1) Aspects.aspectOf(TestAspect_1.class);
//aspect.m_count = 0;
int res = echo(3);
res += echo(3);
assertEquals(6, res);
//assertEquals(2, aspect.m_count);
}

private static void callWithinStatic() {
int res = dup((3+1));
assertEquals(6, res);
@@ -62,9 +98,12 @@ public class BindingTest extends TestCase {
@Aspect
public static class TestAspect_1 {

private int m_count = 0;

@Pointcut("call(int substract(int, int)) && within(ataspectj.BindingTest) && args(arg1, arg2)")
void pc(int arg2, int arg1) {}// see rather fancy ordering here..

// see return int here.
@Around("pc(argAdvice2, argAdvice1) && target(t)")//see here ordering remade consistent
public int aaround(ProceedingJoinPoint jp, BindingTest t, int argAdvice1, int argAdvice2) throws Throwable {
int res = ((Integer)jp.proceed()).intValue();
@@ -79,5 +118,69 @@ public class BindingTest extends TestCase {
int res = ((Integer)jp.proceed(new Object[]{new Integer(argAdvice1-1)})).intValue();
return new Integer(res/3*2);
}

@Around("call(int echo(int)) && withincode(void ataspectj.BindingTest.testProceedInInner()) && args(i)")
public int aaround3(int i, final ProceedingJoinPoint jp) throws Throwable {
final StringBuffer sb = new StringBuffer();
Runnable r = new Runnable() {
public void run() {
try {
int res = ((Integer)jp.proceed()).intValue();
sb.append(res);
} catch (Throwable t) {
fail(t.toString());
}
}
};
Thread t = new Thread(r);
t.start();
t.join();
assertEquals(i, Integer.parseInt(sb.toString()));
return Integer.parseInt(sb.toString())*2;
}

@Around("call(int echo(int)) && withincode(void ataspectj.BindingTest.testNoProceed()) && args(i)")
public int aaround4(int i, final ProceedingJoinPoint jp) throws Throwable {
// since no proceed() is call, this advice won't be inlined
return 0;
}

@Around("call(int echo(int)) && withincode(void ataspectj.BindingTest.testDoubleProceed()) && args(i)")
public int aaround5(int i, final ProceedingJoinPoint jp) throws Throwable {
int i1 = ((Integer)jp.proceed()).intValue();
int i2 = ((Integer)jp.proceed()).intValue();
return i1 + i2;
}

@Around("call(int echo(int)) && withincode(void ataspectj.BindingTest.testDoubleProceedOneInner()) && args(i)")
public int aaround6(int i, final ProceedingJoinPoint jp) throws Throwable {
int i1 = ((Integer)jp.proceed()).intValue();
Object io2 = new PrivilegedAction() {
public Object run() {
try {
return jp.proceed();
} catch (Throwable t) {
fail(t.toString());
return null;
}
}
}.run();
if (io2 == null) {
// since inlining occured, proceed was never called
fail("should not happen - advice was probably inlined while it must not be");
return i1 * 2;
} else {
int i2 = ((Integer)io2).intValue();
return i1 + i2;
}
}

@Around("call(int echo(int)) && withincode(void ataspectj.BindingTest.testAccessAspectState()) && args(i)")
public Object aaround7(int i, final ProceedingJoinPoint jp) throws Throwable {
//m_count++;// what if inlined ?
return jp.proceed();
}

}

}

+ 1
- 1
tests/src/org/aspectj/systemtest/ajc150/ataspectj/AtAjAnnotationGenTests.java View File

@@ -28,7 +28,7 @@ public class AtAjAnnotationGenTests extends XMLBasedAjcTestCase {
}

protected File getSpecFile() {
return new File("../tests/src/org/aspectj/systemtest/ajc150/ataspectj/atajc150.xml");
return new File("../tests/src/org/aspectj/systemtest/ajc150/ataspectj/annotationgen.xml");
}
public void testSimpleAspect() {

+ 4
- 46
tests/src/org/aspectj/systemtest/ajc150/ataspectj/AtAjSyntaxTests.java View File

@@ -16,63 +16,21 @@ import java.io.File;
import junit.framework.Test;

import org.aspectj.testing.XMLBasedAjcTestCase;
import org.aspectj.testing.AutowiredXMLBasedAjcTestCase;

/**
* A suite for @AspectJ aspects located in java5/ataspectj
*
* @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
*/
public class AtAjSyntaxTests extends XMLBasedAjcTestCase {
public class AtAjSyntaxTests extends AutowiredXMLBasedAjcTestCase {
public static Test suite() {
return XMLBasedAjcTestCase.loadSuite(AtAjSyntaxTests.class);
return AutowiredXMLBasedAjcTestCase.loadSuite(AtAjSyntaxTests.class);
}

protected File getSpecFile() {
return new File("../tests/src/org/aspectj/systemtest/ajc150/ataspectj/atajc150.xml");
return new File("../tests/src/org/aspectj/systemtest/ajc150/ataspectj/syntax.xml");
}
public void testSimpleBefore() {
runTest("SimpleBefore");
}

public void testSimpleAfter() {
runTest("SimpleAfter");
}

public void testSingletonAspectBinding() {
runTest("singletonAspectBindings");
}

public void testCflow() {
runTest("CflowTest");
}

public void testPointcutReference() {
runTest("PointcutReferenceTest");
}

public void testXXJoinPoint() {
runTest("XXJoinPointTest");
}

public void testPrecedence() {
runTest("PrecedenceTest");
}

// FIXME alex restore when AJC can compile it... #86452
// public void testAfterX() {
// runTest("AfterXTest");
// }

//FIXME AV uncomment when IfPointcutTest.TestAspect can be compiled ie if() pcd can be parsed.
// right now the aspect is commented out.
// public void testIfPointcut() {
// runTest("IfPointcutTest");
// }

// FIXME alex java.lang.VerifyError: (class: ataspectj/BindingTest, method: dup_aroundBody5$advice signature: (ILorg/aspectj/lang/JoinPoint;Lataspectj/BindingTest$TestAspect_1;ILorg/aspectj/lang/ProceedingJoinPoint;)Ljava/lang/Object;) Register 0 contains wrong type
// public void testBindings() {
// runTest("BindingTest");
// }
}

+ 140
- 0
tests/src/org/aspectj/systemtest/ajc150/ataspectj/annotationgen.xml View File

@@ -0,0 +1,140 @@
<!DOCTYPE suite SYSTEM "../tests/ajcTestSuite.dtd"[]>

<suite>
<!-- @AspectJ v1.5.0 Tests -->

<!-- ================================================================= -->
<!-- Adrian's tests for generation of @AspectJ annotations from ajc -->
<!-- ================================================================= -->

<ajc-test dir="java5/ataspectj/annotationGen" title="annotation gen for simple aspect">
<compile files="SimpleAspect.aj" options="-1.5"/>
<run class="SimpleAspect"/>
</ajc-test>

<ajc-test dir="java5/ataspectj/annotationGen" title="annotation gen for simple annotated aspect">
<compile files="SimpleAnnotatedAspect.aj" options="-1.5"/>
<run class="SimpleAnnotatedAspect"/>
</ajc-test>

<ajc-test dir="java5/ataspectj/annotationGen" title="annotation gen for simple aspect pre 1.5">
<compile files="Simple14Aspect.aj" options="-1.4"/>
<compile files="Simple14AspectTest.java" options="-1.5"/>
<run class="Simple14AspectTest"/>
</ajc-test>

<ajc-test dir="java5/ataspectj/annotationGen" title="annotation gen for privileged aspect">
<compile files="PrivilegedAspect.aj" options="-1.5"/>
<run class="PrivilegedAspect"/>
</ajc-test>

<ajc-test dir="java5/ataspectj/annotationGen" title="annotation gen for perthis aspect">
<compile files="PerThisAspect.aj" options="-1.5"/>
<run class="PerThisAspect"/>
</ajc-test>

<ajc-test dir="java5/ataspectj/annotationGen" title="annotation gen for pertarget aspect">
<compile files="PerTargetAspect.aj" options="-1.5"/>
<run class="PerTargetAspect"/>
</ajc-test>

<ajc-test dir="java5/ataspectj/annotationGen" title="annotation gen for percflow aspect">
<compile files="PerCflowAspect.aj" options="-1.5"/>
<run class="PerCflowAspect"/>
</ajc-test>

<ajc-test dir="java5/ataspectj/annotationGen" title="annotation gen for percflowbelow aspect">
<compile files="PerCflowbelowAspect.aj" options="-1.5"/>
<run class="PerCflowbelowAspect"/>
</ajc-test>

<ajc-test dir="java5/ataspectj/annotationGen" title="annotation gen for pertypewithin aspect">
<compile files="PerTypeWithinAspect.aj" options="-1.5"/>
<run class="PerTypeWithinAspect"/>
</ajc-test>

<ajc-test dir="java5/ataspectj/annotationGen" title="annotation gen for inner aspect of aspect">
<compile files="InnerAspectAspect.aj" options="-1.5"/>
<run class="InnerAspectAspect"/>
</ajc-test>

<ajc-test dir="java5/ataspectj/annotationGen" title="annotation gen for inner aspect of class">
<compile files="InnerAspectClass.aj" options="-1.5"/>
<run class="InnerAspectClass"/>
</ajc-test>

<ajc-test dir="java5/ataspectj/annotationGen" title="annotation gen for advice declarations">
<compile files="BasicAdvice.aj" options="-1.5"/>
<run class="BasicAdvice"/>
</ajc-test>

<ajc-test dir="java5/ataspectj/annotationGen" title="annotation gen for simple pointcut">
<compile files="SimplePointcut.aj" options="-1.5"/>
<run class="SimplePointcut"/>
</ajc-test>

<ajc-test dir="java5/ataspectj/annotationGen" title="annotation gen for pointcut modifiers">
<compile files="PointcutModifiers.aj" options="-1.5"/>
<run class="PointcutModifiers"/>
</ajc-test>

<ajc-test dir="java5/ataspectj/annotationGen" title="annotation gen for pointcut params">
<compile files="PointcutsWithParams.aj" options="-1.5"/>
<run class="PointcutsWithParams"/>
</ajc-test>

<ajc-test dir="java5/ataspectj/annotationGen" title="annotation gen for pointcut refs">
<compile files="ReferencePointcuts.aj" options="-1.5"/>
<run class="ReferencePointcuts"/>
</ajc-test>

<ajc-test dir="java5/ataspectj/annotationGen" title="before ann with non-void return">
<compile files="BeforeWithBadReturn.java" options="-1.5">
<message kind="error" line="7" text="This advice must return void"/>
<message kind="error" line="7" text="This method must return a result of type String"/>
</compile>
</ajc-test>

<ajc-test dir="java5/ataspectj/annotationGen" title="two anns on same element">
<compile files="TwoForThePriceOfOne.java" options="-1.5">
<message kind="error" line="7" text="The annotation @Pointcut is disallowed for this location"/>
</compile>
</ajc-test>

<ajc-test dir="java5/ataspectj/annotationGen" title="bad pcut in after advice">
<compile files="AfterReturningWithBadPCut.java" options="-1.5">
<message kind="error" line="6" text="Syntax error on token &quot;excution(* *.*(..))&quot;"/>
</compile>
</ajc-test>

<ajc-test dir="java5/ataspectj/annotationGen" title="bad parameter binding in advice">
<compile files="BadParameterBinding.java" options="-1.5">
<message kind="warning" line="11" text="no match for this type name: bpb"/>
<message kind="warning" line="15" text="no match for this type name: TheUnknownType"/>
</compile>
</ajc-test>

<ajc-test dir="java5/ataspectj/annotationGen" title="simple pointcut no params">
<compile files="APointcut.java" options="-1.5"/>
<run class="APointcut"/>
</ajc-test>

<ajc-test dir="java5/ataspectj/annotationGen" title="pointcut medley">
<compile files="PointcutAssortment.java" options="-1.5">
<message kind="error" line="9" text="Methods annotated with @Pointcut must return void"/>
<message kind="error" line="9" text="This method must return a result of type String"/>
<message kind="error" line="15" text="Pointcuts should have an empty method body"/>
<message kind="error" line="28" text="Duplicate annotation @Pointcut"/>
<message kind="error" line="29" text="Duplicate annotation @Pointcut"/>
<message kind="error" line="11" text="can't find referenced pointcut foo"/>
<message kind="warning" line="32" text="no match for this type name: foo [Xlint:invalidAbsoluteTypeName]"/>
</compile>
</ajc-test>

<ajc-test dir="java5/ataspectj/annotationGen" title="advice in a class">
<compile files="AdviceInAClass.java" options="-1.5">
<message kind="error" line="6" text="Advice must be declared inside an aspect type"/>
</compile>
</ajc-test>

</suite>

+ 54
- 54
tests/src/org/aspectj/systemtest/ajc150/ataspectj/misuse.xml View File

@@ -4,20 +4,20 @@

<suite>

<comment>this one is ok - too simple - could be removed..</comment>
<ajc-test dir="java5/ataspectj"
pr="" title="@Aspect class extending @Aspect class">
<compile files="ataspectj/misuse/Test005.java" options="-1.5 -Xdev:NoAtAspectJProcessing">
</compile>
</ajc-test>
<comment>just a warning - might be skept if further optimized in Aj5Attributes..</comment>
<ajc-test dir="java5/ataspectj"
pr="" title="class with @Before extending @Aspect class">
<compile files="ataspectj/misuse/Test006.java" options="-1.5 -Xdev:NoAtAspectJProcessing">
<message kind="warning" line="11" text="Found @AspectJ annotations in a non @Aspect type 'ataspectj.misuse.Test006B'"/>
</compile>
</ajc-test>
<!-- <comment>this one is ok - too simple - could be removed..</comment>-->
<!-- <ajc-test dir="java5/ataspectj"-->
<!-- pr="" title="@Aspect class extending @Aspect class">-->
<!-- <compile files="ataspectj/misuse/Test005.java" options="-1.5 -Xdev:NoAtAspectJProcessing">-->
<!-- </compile>-->
<!-- </ajc-test>-->
<!---->
<!-- <comment>just a warning - might be skept if further optimized in Aj5Attributes..</comment>-->
<!-- <ajc-test dir="java5/ataspectj"-->
<!-- pr="" title="class with @Before extending @Aspect class">-->
<!-- <compile files="ataspectj/misuse/Test006.java" options="-1.5 -Xdev:NoAtAspectJProcessing">-->
<!-- <message kind="warning" line="11" text="Found @AspectJ annotations in a non @Aspect type 'ataspectj.misuse.Test006B'"/>-->
<!-- </compile>-->
<!-- </ajc-test>-->

<comment>a warning. We ignore the pointcut (TBD) - line is enclosing class (TBD Andy do better ?)</comment>
<ajc-test dir="java5/ataspectj"
@@ -35,46 +35,46 @@
<!-- </compile>-->
<!-- </ajc-test>-->

<comment>line is enclosing class - TBD</comment>
<ajc-test dir="java5/ataspectj"
pr="" title="@Pointcut with garbage string">
<compile files="ataspectj/misuse/Test014.java" options="-1.5 -Xdev:NoAtAspectJProcessing">
<message kind="error" line="7" text="Cannot parse @Pointcut 'call%dddd"/>
</compile>
</ajc-test>
<comment>line is enclosing class - TBD</comment>
<ajc-test dir="java5/ataspectj"
pr="" title="@Pointcut with throws clause">
<compile files="ataspectj/misuse/Test016.java" options="-1.5 -Xdev:NoAtAspectJProcessing">
<message kind="warning" line="7" text="Found @Pointcut on a method throwing exception 'someCall()V'"/>
</compile>
</ajc-test>
<comment>very dirty hack - can't get this location to work properly so added match all error..</comment>
<ajc-test dir="java5/ataspectj"
pr="" title="@AfterReturning with wrong number of args">
<compile files="ataspectj/misuse/Test019.java" options="-1.5 -Xdev:NoAtAspectJProcessing -Xlint:ignore">
<message kind="error" line="1" text="the parameter x is not bound"/>
<message kind="error"/>
</compile>
</ajc-test>
<comment>line number is enclosing type</comment>
<ajc-test dir="java5/ataspectj"
pr="" title="@Before on non-public method">
<compile files="ataspectj/misuse/Test020.java" options="-1.5 -Xdev:NoAtAspectJProcessing -Xlint:ignore">
<message kind="error" line="7" text="Found @AspectJ annotation on a non public advice 'someCall()V'"/>
</compile>
</ajc-test>
<comment>line number is enclosing type</comment>
<ajc-test dir="java5/ataspectj"
pr="" title="@Before on method not returning void">
<compile files="ataspectj/misuse/Test021.java" options="-1.5 -Xdev:NoAtAspectJProcessing -Xlint:ignore">
<message kind="error" line="7" text="Found @AspectJ annotation on a non around advice not returning void 'someCall()I'"/>
</compile>
</ajc-test>
<!-- <comment>line is enclosing class - TBD</comment>-->
<!-- <ajc-test dir="java5/ataspectj"-->
<!-- pr="" title="@Pointcut with garbage string">-->
<!-- <compile files="ataspectj/misuse/Test014.java" options="-1.5 -Xdev:NoAtAspectJProcessing">-->
<!-- <message kind="error" line="7" text="Cannot parse @Pointcut 'call%dddd"/>-->
<!-- </compile>-->
<!-- </ajc-test>-->
<!---->
<!-- <comment>line is enclosing class - TBD</comment>-->
<!-- <ajc-test dir="java5/ataspectj"-->
<!-- pr="" title="@Pointcut with throws clause">-->
<!-- <compile files="ataspectj/misuse/Test016.java" options="-1.5 -Xdev:NoAtAspectJProcessing">-->
<!-- <message kind="warning" line="7" text="Found @Pointcut on a method throwing exception 'someCall()V'"/>-->
<!-- </compile>-->
<!-- </ajc-test>-->
<!---->
<!-- <comment>very dirty hack - can't get this location to work properly so added match all error..</comment>-->
<!-- <ajc-test dir="java5/ataspectj"-->
<!-- pr="" title="@AfterReturning with wrong number of args">-->
<!-- <compile files="ataspectj/misuse/Test019.java" options="-1.5 -Xdev:NoAtAspectJProcessing -Xlint:ignore">-->
<!-- <message kind="error" line="1" text="the parameter x is not bound"/>-->
<!-- <message kind="error"/>-->
<!-- </compile>-->
<!-- </ajc-test>-->
<!---->
<!-- <comment>line number is enclosing type</comment>-->
<!-- <ajc-test dir="java5/ataspectj"-->
<!-- pr="" title="@Before on non-public method">-->
<!-- <compile files="ataspectj/misuse/Test020.java" options="-1.5 -Xdev:NoAtAspectJProcessing -Xlint:ignore">-->
<!-- <message kind="error" line="7" text="Found @AspectJ annotation on a non public advice 'someCall()V'"/>-->
<!-- </compile>-->
<!-- </ajc-test>-->
<!---->
<!-- <comment>line number is enclosing type</comment>-->
<!-- <ajc-test dir="java5/ataspectj"-->
<!-- pr="" title="@Before on method not returning void">-->
<!-- <compile files="ataspectj/misuse/Test021.java" options="-1.5 -Xdev:NoAtAspectJProcessing -Xlint:ignore">-->
<!-- <message kind="error" line="7" text="Found @AspectJ annotation on a non around advice not returning void 'someCall()I'"/>-->
<!-- </compile>-->
<!-- </ajc-test>-->

<!--
ALEX: todo

+ 82
- 0
tests/src/org/aspectj/systemtest/ajc150/ataspectj/syntax.xml View File

@@ -0,0 +1,82 @@
<!DOCTYPE suite SYSTEM "../tests/ajcTestSuite.dtd"[]>
<suite>

<ajc-test dir="java5/ataspectj" title="SimpleBefore">
<compile files="SimpleBefore.java" options="-1.5 -showWeaveInfo -XnoInline">
<message kind="weave" text="(SimpleBefore.java:23) advised by before advice from 'SimpleBefore$X' (SimpleBefore.java:1)"/>
</compile>
<run class="SimpleBefore"/>
<compile files="SimpleBefore.java" options="-1.5 -showWeaveInfo -XnoInline -Xdev:NoAtAspectJProcessing">
<message kind="weave" text="(SimpleBefore.java:23) advised by before advice from 'SimpleBefore$X' (SimpleBefore.java:1)"/>
</compile>
<run class="SimpleBefore"/>
</ajc-test>

<ajc-test dir="java5/ataspectj" title="SimpleAfter">
<compile files="SimpleAfter.java" options="-1.5 -showWeaveInfo -XnoInline">
<message kind="weave" text="(SimpleAfter.java:13) advised by after advice from 'SimpleAfter$X'"/>
</compile>
<run class="SimpleAfter"/>
<compile files="SimpleAfter.java" options="-1.5 -showWeaveInfo -XnoInline -Xdev:NoAtAspectJProcessing">
<message kind="weave" text="(SimpleAfter.java:13) advised by after advice from 'SimpleAfter$X'"/>
</compile>
<run class="SimpleAfter"/>
</ajc-test>

<ajc-test dir="java5/ataspectj" title="singletonAspectBindings">
<compile files="ataspectj/SingletonAspectBindingsTest.java,ataspectj/TestHelper.java" options="-1.5 -XnoInline"/>
<run class="ataspectj.SingletonAspectBindingsTest"/>
<compile files="ataspectj/SingletonAspectBindingsTest.java,ataspectj/TestHelper.java" options="-1.5 -XnoInline -Xdev:NoAtAspectJProcessing"/>
<run class="ataspectj.SingletonAspectBindingsTest"/>
</ajc-test>

<ajc-test dir="java5/ataspectj" title="CflowTest">
<compile files="ataspectj/CflowTest.java,ataspectj/TestHelper.java" options="-1.5"/>
<run class="ataspectj.CflowTest"/>
<compile files="ataspectj/CflowTest.java,ataspectj/TestHelper.java" options="-1.5 -Xdev:NoAtAspectJProcessing"/>
<run class="ataspectj.CflowTest"/>
</ajc-test>

<ajc-test dir="java5/ataspectj" title="PointcutReferenceTest">
<compile files="ataspectj/PointcutReferenceTest.java,ataspectj/TestHelper.java" options="-1.5"/>
<run class="ataspectj.PointcutReferenceTest"/>
<compile files="ataspectj/PointcutReferenceTest.java,ataspectj/TestHelper.java" options="-1.5 -Xdev:NoAtAspectJProcessing"/>
<run class="ataspectj.PointcutReferenceTest"/>
</ajc-test>

<ajc-test dir="java5/ataspectj" title="XXJoinPointTest">
<compile files="ataspectj/XXJoinPointTest.java,ataspectj/TestHelper.java" options="-1.5"/>
<run class="ataspectj.XXJoinPointTest"/>
<compile files="ataspectj/XXJoinPointTest.java,ataspectj/TestHelper.java" options="-1.5 -Xdev:NoAtAspectJProcessing"/>
<run class="ataspectj.XXJoinPointTest"/>
</ajc-test>

<ajc-test dir="java5/ataspectj" title="PrecedenceTest">
<compile files="ataspectj/PrecedenceTest.java,ataspectj/TestHelper.java" options="-1.5"/>
<run class="ataspectj.PrecedenceTest"/>
<compile files="ataspectj/PrecedenceTest.java,ataspectj/TestHelper.java" options="-1.5 -Xdev:NoAtAspectJProcessing"/>
<run class="ataspectj.PrecedenceTest"/>
</ajc-test>

<!-- <comment>FIXME AV when JDT of M6 is in</comment>-->
<!-- <ajc-test dir="java5/ataspectj" title="AfterXTest">-->
<!-- <compile files="ataspectj/AfterXTest.java,ataspectj/TestHelper.java" options="-1.5"/>-->
<!-- <run class="ataspectj.AfterXTest"/>-->
<!-- </ajc-test>-->

<!-- <comment>FIXME AV when we impl if support in pointcut parser and weaver</comment>-->
<!-- <ajc-test dir="java5/ataspectj" title="IfPointcutTest">-->
<!-- <compile files="ataspectj/IfPointcutTest.java,ataspectj/TestHelper.java" options="-1.5"/>-->
<!-- <run class="ataspectj.IfPointcutTest"/>-->
<!-- </ajc-test>-->

<ajc-test dir="java5/ataspectj" title="BindingTest">
<compile files="ataspectj/BindingTest.java,ataspectj/TestHelper.java" options="-1.5"/>
<run class="ataspectj.BindingTest"/>
</ajc-test>

<ajc-test dir="java5/ataspectj" title="BindingTest no inline">
<compile files="ataspectj/BindingTest.java,ataspectj/TestHelper.java" options="-1.5 -XnoInline"/>
<run class="ataspectj.BindingTest"/>
</ajc-test>
</suite>

+ 193
- 75
weaver/src/org/aspectj/weaver/bcel/BcelShadow.java View File

@@ -1939,7 +1939,47 @@ public class BcelShadow extends Shadow {
weaveAroundClosure(munger, hasDynamicTest);
return;
}

// specific test for @AJ proceedInInners
if (munger.getConcreteAspect().isAnnotationStyleAspect()) {
//FIXME
// if we can't find one proceed()
// we suspect that the call is happening in an inner class
// so we don't inline it.
// Note: for code style, this is done at Aspect compilation time.
// Limitation: if there is two calls and one is done in an inner class, inlining will happen
// since we will see the non proceed in inner one as if it was the sole one.
// The one made in the inner class will never be madeXXX. Should be documented.
boolean canSeeProceedPassedToOther = false;
InstructionHandle curr = adviceMethod.getBody().getStart();
InstructionHandle end = adviceMethod.getBody().getEnd();
ConstantPoolGen cpg = adviceMethod.getEnclosingClass().getConstantPoolGen();
while (curr != end) {
InstructionHandle next = curr.getNext();
Instruction inst = curr.getInstruction();
/*if ((inst instanceof INVOKEINTERFACE)
&& "proceed".equals(((INVOKEINTERFACE) inst).getMethodName(cpg))) {
canSeeProceed = true;
//continue since we may have a proceed in inner or pjp as arg
} else*/ if ((inst instanceof InvokeInstruction)
&& ((InvokeInstruction)inst).getSignature(cpg).indexOf("Lorg/aspectj/lang/ProceedingJoinPoint;") > 0) {
// we may want to refine to exclude stuff returning jp ?
// does code style skip inline if i write dump(thisJoinPoint) ?
canSeeProceedPassedToOther = true;// we see one pjp passed around - dangerous
break;
}
curr = next;
}
if (canSeeProceedPassedToOther) {
// remember this decision to avoid re-analysis
adviceMethod.setCanInline(false);
weaveAroundClosure(munger, hasDynamicTest);
return;
}
}



// We can't inline around methods if they have around advice on them, this
// is because the weaving will extract the body and hence the proceed call.
//??? should consider optimizations to recognize simple cases that don't require body extraction
@@ -1954,8 +1994,9 @@ public class BcelShadow extends Shadow {
NameMangler.aroundCallbackMethodName(
getSignature(),
getEnclosingClass()),
Modifier.PRIVATE,
munger);
Modifier.PRIVATE,
munger
);
// now extract the advice into its own method
@@ -2164,18 +2205,22 @@ public class BcelShadow extends Shadow {
Instruction inst = curr.getInstruction();
if ((inst instanceof INVOKEINTERFACE)
&& "proceed".equals(((INVOKEINTERFACE) inst).getMethodName(cpg))) {
//TODO proceed(...varargs) will need some stuff there
InstructionList insteadProceedIl =
getRedoneProceedCallForAnnotationStyle(
final boolean isProceedWithArgs;
if (((INVOKEINTERFACE) inst).getArgumentTypes(cpg).length == 1) {
// proceed with args as a boxed Object[]
isProceedWithArgs = true;
} else {
isProceedWithArgs = false;
}
InstructionList insteadProceedIl = getRedoneProceedCallForAnnotationStyle(
fact,
extractedMethod,
munger,
localAdviceMethod,
proceedVarList);
//TODO optimize, a POP is added somewhere, what for non void ?
localAdviceMethod.getBody().append(
curr, insteadProceedIl);

proceedVarList,
isProceedWithArgs
);
localAdviceMethod.getBody().append(curr, insteadProceedIl);
Utility.deleteInstruction(curr, localAdviceMethod);
}
curr = next;
@@ -2242,6 +2287,7 @@ public class BcelShadow extends Shadow {
* @param munger
* @param localAdviceMethod
* @param argVarList
* @param isProceedWithArgs
* @return
*/
private InstructionList getRedoneProceedCallForAnnotationStyle(
@@ -2249,57 +2295,129 @@ public class BcelShadow extends Shadow {
LazyMethodGen callbackMethod,
BcelAdvice munger,
LazyMethodGen localAdviceMethod,
List argVarList)
List argVarList,
boolean isProceedWithArgs)
{
//if (true) return new InstructionList();
// Notes:
// proceedingjp is on stack (since user was calling pjp.proceed(...)
// the boxed args to proceed() are on stack as well (Object[]) unless
// the call is to pjp.proceed(<noarg>)

//TODO I think we just don't care about the proceed map
// since that one must be the exact same of the advice sig.
// perhaps with custom jp ?
// new Object[]{new Integer(argAdvice1-1)};// arg of proceed
// call to proceed(..) is NOT made
// instead we do
// itar callback args i
// get from array i, convert it to the callback arg i
// if ask for JP, push the one we got on the stack
// invoke callback, create conversion back to Object/Integer

// we have on stack all the arguments for the ADVICE call.
// we have in frame somewhere all the arguments for the non-advice call.
BcelVar[] adviceVars = munger.getExposedStateAsBcelVars();
IntMap proceedMap = makeProceedArgumentMap(adviceVars);
// rest of method -- (hence all those conversions)
// intValue() from original code
// int res = .. from original code

//System.out.println(proceedMap + " for " + this);
//System.out.println(argVarList);

ResolvedTypeX[] proceedParamTypes =
world.resolve(munger.getSignature().getParameterTypes());
//System.out.println(proceedParamTypes);
//Note: we just don't care about the proceed map etc

InstructionList ret = new InstructionList();
ret.append(new POP());//the joinpoint instance is there

for (int i=0, len=callbackMethod.getArgumentTypes().length; i < len; i++) {
Type stateType = callbackMethod.getArgumentTypes()[i];
ResolvedTypeX stateTypeX = BcelWorld.fromBcel(stateType).resolve(world);
if (proceedMap.hasKey(i)) {
ret.append(new ALOAD(i));
//throw new RuntimeException("unimplemented");
//proceedVars[proceedMap.get(i)].appendLoadAndConvert(ret, fact, stateTypeX);
} else {
//FIXME Alex: odd code there
//((BcelVar) argVarList.get(i)).appendLoad(ret, fact);
//ret.append(new ALOAD(i));
// store the Object[] array on stack if proceed with args
if (isProceedWithArgs) {
Type objectArrayType = Type.getType("[Ljava/lang/Object;");
int localProceedArgArray = localAdviceMethod.allocateLocal(objectArrayType);
ret.append(InstructionFactory.createStore(objectArrayType, localProceedArgArray));

Type proceedingJpType = Type.getType("Lorg/aspectj/lang/ProceedingJoinPoint;");
int localJp = localAdviceMethod.allocateLocal(proceedingJpType);
ret.append(InstructionFactory.createStore(proceedingJpType, localJp));

// push on stack each element of the object array
// that is assumed to be consistent with the callback argument (ie munger args)
// TODO do we want to try catch ClassCast and AOOBE exception ?

// special logic when withincode is static or not
int startIndex = 0;
if (thisVar != null) {
startIndex = 1;
//TODO this logic is actually depending on target as well - test me
ret.append(new ALOAD(0));//thisVar
}
for (int i = startIndex, len=callbackMethod.getArgumentTypes().length; i < len; i++) {
Type stateType = callbackMethod.getArgumentTypes()[i];
ResolvedTypeX stateTypeX = BcelWorld.fromBcel(stateType).resolve(world);
if ("Lorg/aspectj/lang/JoinPoint;".equals(stateType.getSignature())) {
ret.append(new ALOAD(i));
ret.append(new ALOAD(localJp));// from localAdvice signature
} else {
ret.append(new ALOAD(i));
ret.append(InstructionFactory.createLoad(objectArrayType, localProceedArgArray));
ret.append(Utility.createConstant(fact, i-startIndex));
ret.append(InstructionFactory.createArrayLoad(Type.OBJECT));
ret.append(Utility.createConversion(
fact,
Type.OBJECT,
stateType
));
}
}
} else {
Type proceedingJpType = Type.getType("Lorg/aspectj/lang/ProceedingJoinPoint;");
int localJp = localAdviceMethod.allocateLocal(proceedingJpType);
ret.append(InstructionFactory.createStore(proceedingJpType, localJp));

for (int i = 0, len=callbackMethod.getArgumentTypes().length; i < len; i++) {
Type stateType = callbackMethod.getArgumentTypes()[i];
ResolvedTypeX stateTypeX = BcelWorld.fromBcel(stateType).resolve(world);
if ("Lorg/aspectj/lang/JoinPoint;".equals(stateType.getSignature())) {
ret.append(new ALOAD(localJp));// from localAdvice signature
} else {
ret.append(InstructionFactory.createLoad(stateType, i));
}
}
}

// do the callback invoke
ret.append(Utility.createInvoke(fact, callbackMethod));
ret.append(Utility.createConversion(fact, callbackMethod.getReturnType(),
BcelWorld.makeBcelType(munger.getSignature().getReturnType())));

ret.append(new ACONST_NULL());//will be POPed //FIXME Alex: if so clean up
if (true) return ret;

// box it again. Handles cases where around advice does return something else than Object
if (!TypeX.OBJECT.equals(munger.getSignature().getReturnType())) {
ret.append(Utility.createConversion(
fact,
callbackMethod.getReturnType(),
Type.OBJECT
));
}
ret.append(Utility.createConversion(
fact,
callbackMethod.getReturnType(),
BcelWorld.makeBcelType(munger.getSignature().getReturnType())
));

return ret;

//
//
//
// if (proceedMap.hasKey(i)) {
// ret.append(new ALOAD(i));
// //throw new RuntimeException("unimplemented");
// //proceedVars[proceedMap.get(i)].appendLoadAndConvert(ret, fact, stateTypeX);
// } else {
// //((BcelVar) argVarList.get(i)).appendLoad(ret, fact);
// //ret.append(new ALOAD(i));
// if ("Lorg/aspectj/lang/JoinPoint;".equals(stateType.getSignature())) {
// ret.append(new ALOAD(i));
// } else {
// ret.append(new ALOAD(i));
// }
// }
// }
//
// ret.append(Utility.createInvoke(fact, callbackMethod));
// ret.append(Utility.createConversion(fact, callbackMethod.getReturnType(),
// BcelWorld.makeBcelType(munger.getSignature().getReturnType())));
//
// //ret.append(new ACONST_NULL());//will be POPed
// if (true) return ret;
//
//
//
// // we have on stack all the arguments for the ADVICE call.
// // we have in frame somewhere all the arguments for the non-advice call.
//
@@ -2311,36 +2429,36 @@ public class BcelShadow extends Shadow {
//
// ResolvedTypeX[] proceedParamTypes =
// world.resolve(munger.getSignature().getParameterTypes());
// remove this*JoinPoint* as arguments to proceed
if (munger.getBaseParameterCount()+1 < proceedParamTypes.length) {
int len = munger.getBaseParameterCount()+1;
ResolvedTypeX[] newTypes = new ResolvedTypeX[len];
System.arraycopy(proceedParamTypes, 0, newTypes, 0, len);
proceedParamTypes = newTypes;
}
//System.out.println("stateTypes: " + Arrays.asList(stateTypes));
BcelVar[] proceedVars =
Utility.pushAndReturnArrayOfVars(proceedParamTypes, ret, fact, localAdviceMethod);
Type[] stateTypes = callbackMethod.getArgumentTypes();
// System.out.println("stateTypes: " + Arrays.asList(stateTypes));
for (int i=0, len=stateTypes.length; i < len; i++) {
Type stateType = stateTypes[i];
ResolvedTypeX stateTypeX = BcelWorld.fromBcel(stateType).resolve(world);
if (proceedMap.hasKey(i)) {
//throw new RuntimeException("unimplemented");
proceedVars[proceedMap.get(i)].appendLoadAndConvert(ret, fact, stateTypeX);
} else {
((BcelVar) argVarList.get(i)).appendLoad(ret, fact);
}
}
ret.append(Utility.createInvoke(fact, callbackMethod));
ret.append(Utility.createConversion(fact, callbackMethod.getReturnType(),
BcelWorld.makeBcelType(munger.getSignature().getReturnType())));
return ret;
// // remove this*JoinPoint* as arguments to proceed
// if (munger.getBaseParameterCount()+1 < proceedParamTypes.length) {
// int len = munger.getBaseParameterCount()+1;
// ResolvedTypeX[] newTypes = new ResolvedTypeX[len];
// System.arraycopy(proceedParamTypes, 0, newTypes, 0, len);
// proceedParamTypes = newTypes;
// }
//
// //System.out.println("stateTypes: " + Arrays.asList(stateTypes));
// BcelVar[] proceedVars =
// Utility.pushAndReturnArrayOfVars(proceedParamTypes, ret, fact, localAdviceMethod);
//
// Type[] stateTypes = callbackMethod.getArgumentTypes();
//// System.out.println("stateTypes: " + Arrays.asList(stateTypes));
//
// for (int i=0, len=stateTypes.length; i < len; i++) {
// Type stateType = stateTypes[i];
// ResolvedTypeX stateTypeX = BcelWorld.fromBcel(stateType).resolve(world);
// if (proceedMap.hasKey(i)) {
// //throw new RuntimeException("unimplemented");
// proceedVars[proceedMap.get(i)].appendLoadAndConvert(ret, fact, stateTypeX);
// } else {
// ((BcelVar) argVarList.get(i)).appendLoad(ret, fact);
// }
// }
//
// ret.append(Utility.createInvoke(fact, callbackMethod));
// ret.append(Utility.createConversion(fact, callbackMethod.getReturnType(),
// BcelWorld.makeBcelType(munger.getSignature().getReturnType())));
// return ret;
}

public void weaveAroundClosure(

Loading…
Cancel
Save