aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoravasseur <avasseur>2005-05-03 14:43:43 +0000
committeravasseur <avasseur>2005-05-03 14:43:43 +0000
commit9e2ef17dadcfb72eb462e59d996282e0ff0da76b (patch)
treef6e29a4b3a0d1985f30acffa5a54d16abc23a527
parenta89568a77f2d3e74b0d23f3f7b0e112d7ca92d74 (diff)
downloadaspectj-9e2ef17dadcfb72eb462e59d996282e0ff0da76b.tar.gz
aspectj-9e2ef17dadcfb72eb462e59d996282e0ff0da76b.zip
@AJ around inline + test, fix a bug in BcelClassWeaver on my way
-rw-r--r--tests/java5/ataspectj/ataspectj/AroundInlineMungerTest.java108
-rw-r--r--tests/src/org/aspectj/systemtest/ajc150/ataspectj/AtAjSyntaxTests.java2
-rw-r--r--tests/src/org/aspectj/systemtest/ajc150/ataspectj/misuse.xml109
-rw-r--r--tests/src/org/aspectj/systemtest/ajc150/ataspectj/syntax.xml6
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelAccessForInlineMunger.java464
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java2
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelPerClauseAspectAdder.java9
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java11
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/PerCflow.java7
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/PerObject.java7
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/PerSingleton.java6
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/PerTypeWithin.java7
12 files changed, 676 insertions, 62 deletions
diff --git a/tests/java5/ataspectj/ataspectj/AroundInlineMungerTest.java b/tests/java5/ataspectj/ataspectj/AroundInlineMungerTest.java
new file mode 100644
index 000000000..8be6217b4
--- /dev/null
+++ b/tests/java5/ataspectj/ataspectj/AroundInlineMungerTest.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Alexandre Vasseur initial implementation
+ *******************************************************************************/
+package ataspectj;
+
+import junit.framework.TestCase;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Before;
+import org.aspectj.lang.ProceedingJoinPoint;
+
+/**
+ * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
+ */
+public class AroundInlineMungerTest extends TestCase {
+
+ public static void main(String[] args) {
+ TestHelper.runAndThrowOnFailure(suite());
+ }
+
+ public static junit.framework.Test suite() {
+ return new junit.framework.TestSuite(AroundInlineMungerTest.class);
+ }
+
+ public void testAccessNonPublicFromAroundAdvice() {
+ target();
+ assertEquals(3, Open.aroundCount);
+ assertEquals(6, Open.beforeCount);
+ }
+
+ public void target() {}
+
+ public static class OpenBase {
+ protected void superMethod() {}
+ }
+
+ public static class OpenSubBase extends OpenBase {}
+
+ // aspect will be prepared for inlining
+ @Aspect
+ public static class Open extends OpenSubBase {
+
+ public static int aroundCount = 0;
+ public static int beforeCount = 0;
+
+ private int i;
+ private static int I;
+
+ @Around("execution(* ataspectj.AroundInlineMungerTest.target())")
+ public Object around1(ProceedingJoinPoint jp) throws Throwable {
+ aroundCount++;
+ priv(1, 2L, 3);
+ super.superMethod();
+ new Inner().priv();//fails to be wrapped so this advice will not be inlined but previous call were still prepared
+ return jp.proceed();
+ }
+
+ // this advice to test around advice body call/get/set advising
+ @Before("(call(* ataspectj.AroundInlineMungerTest.Open.priv(..))" +
+ " || get(int ataspectj.AroundInlineMungerTest.Open.i)" +
+ " || set(int ataspectj.AroundInlineMungerTest.Open.i)" +
+ " || get(int ataspectj.AroundInlineMungerTest.Open.I)" +
+ " || set(int ataspectj.AroundInlineMungerTest.Open.I)" +
+ " )&& this(ataspectj.AroundInlineMungerTest.Open)")
+ public void before1() {
+ beforeCount++;
+ }
+
+ @Around("execution(* ataspectj.AroundInlineMungerTest.target())")
+ public Object around2(ProceedingJoinPoint jp) throws Throwable {
+ aroundCount++;
+ super.superMethod();
+ new Inner().priv();//fails to be wrapped so next calls won't be prepared but previous was
+ priv(1, 2L, 3);
+ return jp.proceed();
+ }
+
+ @Around("execution(* ataspectj.AroundInlineMungerTest.target())")
+ public Object around3(ProceedingJoinPoint jp) throws Throwable {
+ aroundCount++;
+ // all those field access will be wrapped
+ int li = i;
+ i = li;
+ int lI = I;
+ I = lI;
+ return jp.proceed();
+ }
+
+ // -- some private member for which access will be wrapped so that around advice can be inlined
+
+ private void priv(int i, long j, int k) {
+ long l = i + j + k;
+ }
+
+ private static class Inner {
+ private Inner() {}
+ private void priv() {};
+ }
+ }
+}
diff --git a/tests/src/org/aspectj/systemtest/ajc150/ataspectj/AtAjSyntaxTests.java b/tests/src/org/aspectj/systemtest/ajc150/ataspectj/AtAjSyntaxTests.java
index 0ff079345..7927a2675 100644
--- a/tests/src/org/aspectj/systemtest/ajc150/ataspectj/AtAjSyntaxTests.java
+++ b/tests/src/org/aspectj/systemtest/ajc150/ataspectj/AtAjSyntaxTests.java
@@ -18,7 +18,7 @@ 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>
diff --git a/tests/src/org/aspectj/systemtest/ajc150/ataspectj/misuse.xml b/tests/src/org/aspectj/systemtest/ajc150/ataspectj/misuse.xml
index d56357c80..d9c0ba75c 100644
--- a/tests/src/org/aspectj/systemtest/ajc150/ataspectj/misuse.xml
+++ b/tests/src/org/aspectj/systemtest/ajc150/ataspectj/misuse.xml
@@ -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"
@@ -27,7 +27,6 @@
</compile>
</ajc-test>
-
<!-- <ajc-test dir="java5/ataspectj"-->
<!-- pr="" title="@Aspect on interface">-->
<!-- <compile files="ataspectj/misuse/Test010.java" options="-1.5 -Xdev:NoAtAspectJProcessing">-->
@@ -35,46 +34,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
diff --git a/tests/src/org/aspectj/systemtest/ajc150/ataspectj/syntax.xml b/tests/src/org/aspectj/systemtest/ajc150/ataspectj/syntax.xml
index daeb4da84..eab2949e5 100644
--- a/tests/src/org/aspectj/systemtest/ajc150/ataspectj/syntax.xml
+++ b/tests/src/org/aspectj/systemtest/ajc150/ataspectj/syntax.xml
@@ -87,4 +87,10 @@
<run class="ataspectj.PerClauseTest"/>
</ajc-test>
+ <ajc-test dir="java5/ataspectj" title="AroundInlineMunger">
+ <compile files="ataspectj/AroundInlineMungerTest.java,ataspectj/TestHelper.java" options="-1.5 -XnoInline -Xdev:NoAtAspectJProcessing -Xlint:ignore"/>
+ <run class="ataspectj.AroundInlineMungerTest"/>
+ <compile files="ataspectj/AroundInlineMungerTest.java,ataspectj/TestHelper.java" options="-1.5 -Xdev:NoAtAspectJProcessing -Xlint:ignore"/>
+ <run class="ataspectj.AroundInlineMungerTest"/>
+ </ajc-test>
</suite> \ No newline at end of file
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelAccessForInlineMunger.java b/weaver/src/org/aspectj/weaver/bcel/BcelAccessForInlineMunger.java
new file mode 100644
index 000000000..c174ee3cd
--- /dev/null
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelAccessForInlineMunger.java
@@ -0,0 +1,464 @@
+/*******************************************************************************
+ * Copyright (c) 2005 Contributors.
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Alexandre Vasseur initial implementation
+ *******************************************************************************/
+package org.aspectj.weaver.bcel;
+
+import org.aspectj.apache.bcel.Constants;
+import org.aspectj.apache.bcel.generic.ConstantPoolGen;
+import org.aspectj.apache.bcel.generic.FieldInstruction;
+import org.aspectj.apache.bcel.generic.GETFIELD;
+import org.aspectj.apache.bcel.generic.GETSTATIC;
+import org.aspectj.apache.bcel.generic.Instruction;
+import org.aspectj.apache.bcel.generic.InstructionConstants;
+import org.aspectj.apache.bcel.generic.InstructionFactory;
+import org.aspectj.apache.bcel.generic.InstructionHandle;
+import org.aspectj.apache.bcel.generic.InstructionList;
+import org.aspectj.apache.bcel.generic.InvokeInstruction;
+import org.aspectj.apache.bcel.generic.Type;
+import org.aspectj.weaver.AjAttribute;
+import org.aspectj.weaver.AjcMemberMaker;
+import org.aspectj.weaver.Member;
+import org.aspectj.weaver.NameMangler;
+import org.aspectj.weaver.ResolvedMember;
+import org.aspectj.weaver.ResolvedTypeX;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.TypeX;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.List;
+
+/**
+ * Looks for all access to method or field that are not public within the body of the around advices and replace
+ * the invocations to a wrapper call so that the around advice can further be inlined.
+ * <p/>
+ * This munger is used for @AJ aspects for which inlining wrapper is not done at compile time.
+ * <p/>
+ * Specific state and logic is kept in the munger ala ITD so that call/get/set pointcuts can still be matched
+ * on the wrapped member thanks to the EffectiveSignature attribute.
+ *
+ * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
+ */
+public class BcelAccessForInlineMunger extends BcelTypeMunger {
+
+ /**
+ * Wrapper member cache, key is wrapper name.
+ * This structure is queried when regular shadow matching in the advice body (call/get/set) occurs
+ */
+ private Map m_inlineAccessorBcelMethods;
+
+ /**
+ * The aspect we act for
+ */
+ private LazyClassGen m_aspectGen;
+
+ /**
+ * The wrapper method we need to add. Those are added at the end of the munging
+ */
+ private Set m_inlineAccessorMethodGens;
+
+ public BcelAccessForInlineMunger(ResolvedTypeX aspectType) {
+ super(null, aspectType);
+ }
+
+ public boolean munge(BcelClassWeaver weaver) {
+ m_aspectGen = weaver.getLazyClassGen();
+ m_inlineAccessorBcelMethods = new HashMap(0);
+ m_inlineAccessorMethodGens = new HashSet();
+
+ // look for all @Around advices
+ for (Iterator iterator = m_aspectGen.getMethodGens().iterator(); iterator.hasNext();) {
+ LazyMethodGen methodGen = (LazyMethodGen) iterator.next();
+ if (methodGen.hasAnnotation(TypeX.forName("org/aspectj/lang/annotation/Around"))) {
+ openAroundAdvice(methodGen);
+ }
+ }
+
+ // add the accessors
+ for (Iterator iterator = m_inlineAccessorMethodGens.iterator(); iterator.hasNext();) {
+ LazyMethodGen lazyMethodGen = (LazyMethodGen) iterator.next();
+ m_aspectGen.addMethodGen(lazyMethodGen);
+ }
+
+ // flush some
+ m_inlineAccessorMethodGens = null;
+ // we keep m_inlineAccessorsResolvedMembers for shadow matching
+
+ return true;
+ }
+
+ /**
+ * Looks in the wrapper we have added so that we can find their effective signature if needed
+ *
+ * @param member
+ * @return
+ */
+ public ResolvedMember getMatchingSyntheticMember(Member member) {
+ return (ResolvedMember) m_inlineAccessorBcelMethods.get(member.getName());
+ }
+
+ public ResolvedMember getSignature() {
+ return null;
+ }
+
+ /**
+ * Match only the aspect for which we act
+ *
+ * @param onType
+ * @return
+ */
+ public boolean matches(ResolvedTypeX onType) {
+ return aspectType.equals(onType);
+ }
+
+ /**
+ * Prepare the around advice, flag it as cannot be inlined if it can't be
+ *
+ * @param aroundAdvice
+ */
+ private void openAroundAdvice(LazyMethodGen aroundAdvice) {
+ InstructionHandle curr = aroundAdvice.getBody().getStart();
+ InstructionHandle end = aroundAdvice.getBody().getEnd();
+ ConstantPoolGen cpg = aroundAdvice.getEnclosingClass().getConstantPoolGen();
+ InstructionFactory factory = aroundAdvice.enclosingClass.getFactory();
+
+ boolean realizedCannotInline = false;
+ while (curr != end) {
+ if (realizedCannotInline) {
+ // we know we cannot inline this advice so no need for futher handling
+ break;
+ }
+ InstructionHandle next = curr.getNext();
+ Instruction inst = curr.getInstruction();
+
+ // open-up method call
+ if ((inst instanceof InvokeInstruction)) {
+ InvokeInstruction invoke = (InvokeInstruction) inst;
+ ResolvedTypeX callee = m_aspectGen.getWorld().resolve(TypeX.forName(invoke.getClassName(cpg)));
+
+ // look in the whole method list and not just declared for super calls and alike
+ List methods = callee.getMethodsWithoutIterator();
+ for (Iterator iter = methods.iterator(); iter.hasNext();) {
+ BcelMethod resolvedMember = (BcelMethod) iter.next();
+ if (invoke.getName(cpg).equals(resolvedMember.getName())
+ && invoke.getSignature(cpg).equals(resolvedMember.getSignature())
+ && !resolvedMember.isPublic()) {
+ if ("<init>".equals(invoke.getName(cpg))) {
+ // skipping open up for private constructor
+ // can occur when aspect new a private inner type
+ // too complex to handle new + dup + .. + invokespecial here.
+ aroundAdvice.setCanInline(false);
+ realizedCannotInline = true;
+ } else {
+ // specific handling for super.foo() calls, where foo is non public
+ if (aspectType.getSuperclass() != null
+ && aspectType.getSuperclass().getName().equals(callee.getName())) {
+ ResolvedMember accessor = createOrGetInlineAccessorForSuperDispatch(resolvedMember);
+ InvokeInstruction newInst = factory.createInvoke(
+ aspectType.getName(),
+ accessor.getName(),
+ BcelWorld.makeBcelType(accessor.getReturnType()),
+ BcelWorld.makeBcelTypes(accessor.getParameterTypes()),
+ Constants.INVOKEVIRTUAL
+ );
+ curr.setInstruction(newInst);
+ } else {
+ ResolvedMember accessor = createOrGetInlineAccessorForMethod(resolvedMember);
+ InvokeInstruction newInst = factory.createInvoke(
+ aspectType.getName(),
+ accessor.getName(),
+ BcelWorld.makeBcelType(accessor.getReturnType()),
+ BcelWorld.makeBcelTypes(accessor.getParameterTypes()),
+ Constants.INVOKESTATIC
+ );
+ curr.setInstruction(newInst);
+ }
+ }
+
+ break;//ok we found a matching callee member and swapped the instruction with the accessor
+ }
+ }
+ } else if (inst instanceof FieldInstruction) {
+ FieldInstruction invoke = (FieldInstruction) inst;
+ ResolvedTypeX callee = m_aspectGen.getWorld().resolve(TypeX.forName(invoke.getClassName(cpg)));
+ for (int i = 0; i < callee.getDeclaredJavaFields().length; i++) {
+ ResolvedMember resolvedMember = callee.getDeclaredJavaFields()[i];
+ if (invoke.getName(cpg).equals(resolvedMember.getName())
+ && invoke.getSignature(cpg).equals(resolvedMember.getSignature())
+ && !resolvedMember.isPublic()) {
+ final ResolvedMember accessor;
+ if ((inst instanceof GETFIELD) || (inst instanceof GETSTATIC)) {
+ accessor = createOrGetInlineAccessorForFieldGet(resolvedMember);
+ } else {
+ accessor = createOrGetInlineAccessorForFieldSet(resolvedMember);
+ }
+ InvokeInstruction newInst = factory.createInvoke(
+ aspectType.getName(),
+ accessor.getName(),
+ BcelWorld.makeBcelType(accessor.getReturnType()),
+ BcelWorld.makeBcelTypes(accessor.getParameterTypes()),
+ Constants.INVOKESTATIC
+ );
+ curr.setInstruction(newInst);
+
+ break;//ok we found a matching callee member and swapped the instruction with the accessor
+ }
+ }
+ }
+
+ curr = next;
+ }
+ }
+
+ /**
+ * Add an inline wrapper for a non public method call
+ *
+ * @param resolvedMember
+ * @return
+ */
+ private ResolvedMember createOrGetInlineAccessorForMethod(ResolvedMember resolvedMember) {
+ String accessor = NameMangler.inlineAccessMethodForMethod(
+ resolvedMember.getName(), resolvedMember.getDeclaringType(), aspectType
+ );
+ ResolvedMember inlineAccessor = (ResolvedMember) m_inlineAccessorBcelMethods.get(accessor);
+ if (inlineAccessor == null) {
+ // add static method to aspect
+ inlineAccessor = AjcMemberMaker.inlineAccessMethodForMethod(
+ aspectType,
+ resolvedMember
+ );
+
+ //add new accessor method to aspect bytecode
+ InstructionFactory factory = m_aspectGen.getFactory();
+ LazyMethodGen method = makeMethodGen(m_aspectGen, inlineAccessor);
+ // flag it synthetic, AjSynthetic
+ method.makeSynthetic();
+ method.addAttribute(
+ BcelAttributes.bcelAttribute(new AjAttribute.AjSynthetic(), m_aspectGen.getConstantPoolGen())
+ );
+ // flag the effective signature, so that we can deobfuscate the signature to apply method call pointcut
+ method.addAttribute(
+ BcelAttributes.bcelAttribute(
+ new AjAttribute.EffectiveSignatureAttribute(resolvedMember, Shadow.MethodCall, false),
+ m_aspectGen.getConstantPoolGen()
+ )
+ );
+
+ m_inlineAccessorMethodGens.add(method);
+
+ InstructionList il = method.getBody();
+ int register = 0;
+ for (int i = 0; i < inlineAccessor.getParameterTypes().length; i++) {
+ TypeX typeX = inlineAccessor.getParameterTypes()[i];
+ Type type = BcelWorld.makeBcelType(typeX);
+ il.append(InstructionFactory.createLoad(type, register));
+ register += type.getSize();
+ }
+ il.append(
+ Utility.createInvoke(
+ factory,
+ resolvedMember.isStatic() ? Constants.INVOKESTATIC : Constants.INVOKESPECIAL,
+ resolvedMember
+ )
+ );
+ il.append(InstructionFactory.createReturn(BcelWorld.makeBcelType(inlineAccessor.getReturnType())));
+
+ m_inlineAccessorBcelMethods.put(
+ accessor,
+ new BcelMethod(m_aspectGen.getBcelObjectType(), method.getMethod())
+ );
+ }
+ return inlineAccessor;
+ }
+
+ /**
+ * Add an inline wrapper for a non public super.method call
+ *
+ * @param resolvedMember
+ * @return
+ */
+ private ResolvedMember createOrGetInlineAccessorForSuperDispatch(ResolvedMember resolvedMember) {
+ String accessor = NameMangler.superDispatchMethod(
+ aspectType, resolvedMember.getName()
+ );
+ ResolvedMember inlineAccessor = (ResolvedMember) m_inlineAccessorBcelMethods.get(accessor);
+ if (inlineAccessor == null) {
+ // add static method to aspect
+ inlineAccessor = AjcMemberMaker.superAccessMethod(
+ aspectType,
+ resolvedMember
+ );
+
+ //add new accessor method to aspect bytecode
+ InstructionFactory factory = m_aspectGen.getFactory();
+ LazyMethodGen method = makeMethodGen(m_aspectGen, inlineAccessor);
+ // flag it synthetic, AjSynthetic
+ method.makeSynthetic();
+ method.addAttribute(
+ BcelAttributes.bcelAttribute(new AjAttribute.AjSynthetic(), m_aspectGen.getConstantPoolGen())
+ );
+ // flag the effective signature, so that we can deobfuscate the signature to apply method call pointcut
+ method.addAttribute(
+ BcelAttributes.bcelAttribute(
+ new AjAttribute.EffectiveSignatureAttribute(resolvedMember, Shadow.MethodCall, false),
+ m_aspectGen.getConstantPoolGen()
+ )
+ );
+
+ m_inlineAccessorMethodGens.add(method);
+
+ InstructionList il = method.getBody();
+ il.append(InstructionConstants.ALOAD_0);
+ int register = 0;
+ for (int i = 0; i < inlineAccessor.getParameterTypes().length; i++) {
+ TypeX typeX = inlineAccessor.getParameterTypes()[i];
+ Type type = BcelWorld.makeBcelType(typeX);
+ il.append(InstructionFactory.createLoad(type, register));
+ register += type.getSize();
+ }
+ il.append(
+ Utility.createInvoke(
+ factory,
+ Constants.INVOKESPECIAL,
+ resolvedMember
+ )
+ );
+ il.append(InstructionFactory.createReturn(BcelWorld.makeBcelType(inlineAccessor.getReturnType())));
+
+ m_inlineAccessorBcelMethods.put(
+ accessor,
+ new BcelMethod(m_aspectGen.getBcelObjectType(), method.getMethod())
+ );
+ }
+ return inlineAccessor;
+ }
+
+ /**
+ * Add an inline wrapper for a non public field get
+ *
+ * @param resolvedMember
+ * @return
+ */
+ private ResolvedMember createOrGetInlineAccessorForFieldGet(ResolvedMember resolvedMember) {
+ String accessor = NameMangler.inlineAccessMethodForFieldGet(
+ resolvedMember.getName(), resolvedMember.getDeclaringType(), aspectType
+ );
+ ResolvedMember inlineAccessor = (ResolvedMember) m_inlineAccessorBcelMethods.get(accessor);
+ if (inlineAccessor == null) {
+ // add static method to aspect
+ inlineAccessor = AjcMemberMaker.inlineAccessMethodForFieldGet(
+ aspectType,
+ resolvedMember
+ );
+
+ //add new accessor method to aspect bytecode
+ InstructionFactory factory = m_aspectGen.getFactory();
+ LazyMethodGen method = makeMethodGen(m_aspectGen, inlineAccessor);
+ // flag it synthetic, AjSynthetic
+ method.makeSynthetic();
+ method.addAttribute(
+ BcelAttributes.bcelAttribute(new AjAttribute.AjSynthetic(), m_aspectGen.getConstantPoolGen())
+ );
+ // flag the effective signature, so that we can deobfuscate the signature to apply method call pointcut
+ method.addAttribute(
+ BcelAttributes.bcelAttribute(
+ new AjAttribute.EffectiveSignatureAttribute(resolvedMember, Shadow.FieldGet, false),
+ m_aspectGen.getConstantPoolGen()
+ )
+ );
+
+ m_inlineAccessorMethodGens.add(method);
+
+ InstructionList il = method.getBody();
+ if (resolvedMember.isStatic()) {
+ // field accessed is static so no "this" as accessor sole parameter
+ } else {
+ il.append(InstructionConstants.ALOAD_0);
+ }
+ il.append(
+ Utility.createGet(
+ factory,
+ resolvedMember
+ )
+ );
+ il.append(InstructionFactory.createReturn(BcelWorld.makeBcelType(inlineAccessor.getReturnType())));
+
+ m_inlineAccessorBcelMethods.put(
+ accessor,
+ new BcelMethod(m_aspectGen.getBcelObjectType(), method.getMethod())
+ );
+ }
+ return inlineAccessor;
+ }
+
+ /**
+ * Add an inline wrapper for a non public field set
+ *
+ * @param resolvedMember
+ * @return
+ */
+ private ResolvedMember createOrGetInlineAccessorForFieldSet(ResolvedMember resolvedMember) {
+ String accessor = NameMangler.inlineAccessMethodForFieldSet(
+ resolvedMember.getName(), resolvedMember.getDeclaringType(), aspectType
+ );
+ ResolvedMember inlineAccessor = (ResolvedMember) m_inlineAccessorBcelMethods.get(accessor);
+ if (inlineAccessor == null) {
+ // add static method to aspect
+ inlineAccessor = AjcMemberMaker.inlineAccessMethodForFieldSet(
+ aspectType,
+ resolvedMember
+ );
+
+ //add new accessor method to aspect bytecode
+ InstructionFactory factory = m_aspectGen.getFactory();
+ LazyMethodGen method = makeMethodGen(m_aspectGen, inlineAccessor);
+ // flag it synthetic, AjSynthetic
+ method.makeSynthetic();
+ method.addAttribute(
+ BcelAttributes.bcelAttribute(new AjAttribute.AjSynthetic(), m_aspectGen.getConstantPoolGen())
+ );
+ // flag the effective signature, so that we can deobfuscate the signature to apply method call pointcut
+ method.addAttribute(
+ BcelAttributes.bcelAttribute(
+ new AjAttribute.EffectiveSignatureAttribute(resolvedMember, Shadow.FieldSet, false),
+ m_aspectGen.getConstantPoolGen()
+ )
+ );
+
+ m_inlineAccessorMethodGens.add(method);
+
+ InstructionList il = method.getBody();
+ if (resolvedMember.isStatic()) {
+ // field accessed is static so sole parameter is field value to be set
+ il.append(InstructionFactory.createLoad(BcelWorld.makeBcelType(resolvedMember.getReturnType()), 0));
+ } else {
+ il.append(InstructionConstants.ALOAD_0);
+ il.append(InstructionFactory.createLoad(BcelWorld.makeBcelType(resolvedMember.getReturnType()), 1));
+ }
+ il.append(
+ Utility.createSet(
+ factory,
+ resolvedMember
+ )
+ );
+ il.append(InstructionConstants.RETURN);
+
+ m_inlineAccessorBcelMethods.put(
+ accessor,
+ new BcelMethod(m_aspectGen.getBcelObjectType(), method.getMethod())
+ );
+ }
+ return inlineAccessor;
+ }
+}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java b/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java
index 16ac151db..fc5668c24 100644
--- a/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java
@@ -1505,7 +1505,7 @@ class BcelClassWeaver implements IClassWeaver {
annotations = resolvedDooberry.getAnnotationTypes();
}
} else if (rm.getKind()==Member.METHOD && !rm.isAbstract()) {
- if (methodName.startsWith("ajc$inlineAccessMethod")) {
+ if (methodName.startsWith("ajc$inlineAccessMethod") || methodName.startsWith("ajc$superDispatch")) {
ResolvedMember resolvedDooberry = world.resolve(declaredSig);
annotations = resolvedDooberry.getAnnotationTypes();
} else {
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelPerClauseAspectAdder.java b/weaver/src/org/aspectj/weaver/bcel/BcelPerClauseAspectAdder.java
index 254f429fe..c3b158179 100644
--- a/weaver/src/org/aspectj/weaver/bcel/BcelPerClauseAspectAdder.java
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelPerClauseAspectAdder.java
@@ -119,25 +119,24 @@ public class BcelPerClauseAspectAdder extends BcelTypeMunger {
generatePerTWGetInstanceMethod(gen);
generatePerTWCreateAspectInstanceMethod(gen);
} else {
- throw new RuntimeException("TODO not yet implemented perClause " + kind.getName());
+ throw new Error("should not happen - not such kind " + kind.getName());
}
return true;
}
public ResolvedMember getMatchingSyntheticMember(Member member) {
- //TODO is that ok ?
return null;
}
public ResolvedMember getSignature() {
- // TODO what to do here ?
return null;
- //throw new RuntimeException("not implemented - BcelPerClauseAspectAdder");
}
public boolean matches(ResolvedTypeX onType) {
- return true;//onType.equals(aspectType);
+ //we cannot return onType.equals(aspectType)
+ //since we need to eagerly create the nested ajcMighHaveAspect interface on LTW
+ return true;
}
private void generatePerClauseMembers(LazyClassGen classGen) {
diff --git a/weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java b/weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java
index f465bc2f1..5a62d9fc7 100644
--- a/weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java
+++ b/weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java
@@ -1354,4 +1354,15 @@ public final class LazyMethodGen {
public void setCanInline(boolean canInline) {
this.canInline = canInline;
}
+
+ /**
+ * Adds an attribute to the method
+ * @param attr
+ */
+ public void addAttribute(Attribute attr) {
+ Attribute[] newAttributes = new Attribute[attributes.length + 1];
+ System.arraycopy(attributes, 0, newAttributes, 0, attributes.length);
+ newAttributes[attributes.length] = attr;
+ attributes = newAttributes;
+ }
}
diff --git a/weaver/src/org/aspectj/weaver/patterns/PerCflow.java b/weaver/src/org/aspectj/weaver/patterns/PerCflow.java
index cded77643..3d647c455 100644
--- a/weaver/src/org/aspectj/weaver/patterns/PerCflow.java
+++ b/weaver/src/org/aspectj/weaver/patterns/PerCflow.java
@@ -34,6 +34,8 @@ import org.aspectj.weaver.Shadow;
import org.aspectj.weaver.TypeX;
import org.aspectj.weaver.VersionedDataInputStream;
import org.aspectj.weaver.World;
+import org.aspectj.weaver.bcel.BcelAccessForInlineMunger;
+import org.aspectj.weaver.ataspectj.Ajc5MemberMaker;
import org.aspectj.weaver.ast.Expr;
import org.aspectj.weaver.ast.Test;
@@ -103,6 +105,11 @@ public class PerCflow extends PerClause {
);
}
+ //ATAJ inline around advice support
+ if (Ajc5MemberMaker.isAnnotationStyleAspect(inAspect)) {
+ inAspect.crosscuttingMembers.addTypeMunger(new BcelAccessForInlineMunger(inAspect));
+ }
+
return ret;
}
diff --git a/weaver/src/org/aspectj/weaver/patterns/PerObject.java b/weaver/src/org/aspectj/weaver/patterns/PerObject.java
index 79426942e..2374b8e2c 100644
--- a/weaver/src/org/aspectj/weaver/patterns/PerObject.java
+++ b/weaver/src/org/aspectj/weaver/patterns/PerObject.java
@@ -29,6 +29,8 @@ import org.aspectj.weaver.ResolvedTypeX;
import org.aspectj.weaver.Shadow;
import org.aspectj.weaver.VersionedDataInputStream;
import org.aspectj.weaver.World;
+import org.aspectj.weaver.bcel.BcelAccessForInlineMunger;
+import org.aspectj.weaver.ataspectj.Ajc5MemberMaker;
import org.aspectj.weaver.ast.Expr;
import org.aspectj.weaver.ast.Test;
import org.aspectj.weaver.ast.Var;
@@ -113,6 +115,11 @@ public class PerObject extends PerClause {
);
}
+ //ATAJ inline around advice support
+ if (Ajc5MemberMaker.isAnnotationStyleAspect(inAspect)) {
+ inAspect.crosscuttingMembers.addTypeMunger(new BcelAccessForInlineMunger(inAspect));
+ }
+
return ret;
}
diff --git a/weaver/src/org/aspectj/weaver/patterns/PerSingleton.java b/weaver/src/org/aspectj/weaver/patterns/PerSingleton.java
index f98d07980..7c053e98d 100644
--- a/weaver/src/org/aspectj/weaver/patterns/PerSingleton.java
+++ b/weaver/src/org/aspectj/weaver/patterns/PerSingleton.java
@@ -23,6 +23,7 @@ import org.aspectj.weaver.ISourceContext;
import org.aspectj.weaver.ResolvedTypeX;
import org.aspectj.weaver.Shadow;
import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.bcel.BcelAccessForInlineMunger;
import org.aspectj.weaver.ast.Expr;
import org.aspectj.weaver.ast.Literal;
import org.aspectj.weaver.ast.Test;
@@ -104,6 +105,11 @@ public class PerSingleton extends PerClause {
);
}
+ //ATAJ inline around advice support
+ if (Ajc5MemberMaker.isAnnotationStyleAspect(inAspect)) {
+ inAspect.crosscuttingMembers.addTypeMunger(new BcelAccessForInlineMunger(inAspect));
+ }
+
return ret;
}
diff --git a/weaver/src/org/aspectj/weaver/patterns/PerTypeWithin.java b/weaver/src/org/aspectj/weaver/patterns/PerTypeWithin.java
index df2db0cbb..157f10223 100644
--- a/weaver/src/org/aspectj/weaver/patterns/PerTypeWithin.java
+++ b/weaver/src/org/aspectj/weaver/patterns/PerTypeWithin.java
@@ -32,6 +32,8 @@ import org.aspectj.weaver.ResolvedTypeX;
import org.aspectj.weaver.Shadow;
import org.aspectj.weaver.VersionedDataInputStream;
import org.aspectj.weaver.World;
+import org.aspectj.weaver.bcel.BcelAccessForInlineMunger;
+import org.aspectj.weaver.ataspectj.Ajc5MemberMaker;
import org.aspectj.weaver.ast.Expr;
import org.aspectj.weaver.ast.Literal;
import org.aspectj.weaver.ast.Test;
@@ -153,6 +155,11 @@ public class PerTypeWithin extends PerClause {
);
}
+ //ATAJ inline around advice support
+ if (Ajc5MemberMaker.isAnnotationStyleAspect(inAspect)) {
+ inAspect.crosscuttingMembers.addTypeMunger(new BcelAccessForInlineMunger(inAspect));
+ }
+
return ret;
}