Browse Source

@AJ around inline + test, fix a bug in BcelClassWeaver on my way

tags/PRE_ANDY
avasseur 19 years ago
parent
commit
9e2ef17dad

+ 108
- 0
tests/java5/ataspectj/ataspectj/AroundInlineMungerTest.java View File

@@ -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() {};
}
}
}

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

@@ -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>

+ 54
- 55
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"
@@ -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

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

@@ -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>

+ 464
- 0
weaver/src/org/aspectj/weaver/bcel/BcelAccessForInlineMunger.java View File

@@ -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;
}
}

+ 1
- 1
weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java View File

@@ -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 {

+ 4
- 5
weaver/src/org/aspectj/weaver/bcel/BcelPerClauseAspectAdder.java View File

@@ -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) {

+ 11
- 0
weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java View File

@@ -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;
}
}

+ 7
- 0
weaver/src/org/aspectj/weaver/patterns/PerCflow.java View File

@@ -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;
}


+ 7
- 0
weaver/src/org/aspectj/weaver/patterns/PerObject.java View File

@@ -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;
}


+ 6
- 0
weaver/src/org/aspectj/weaver/patterns/PerSingleton.java View File

@@ -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;
}


+ 7
- 0
weaver/src/org/aspectj/weaver/patterns/PerTypeWithin.java View File

@@ -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;
}

Loading…
Cancel
Save