Browse Source

from branch: loads of @AJ changes for inlining strategies, using the right JP, wiring up the closure, etc.

tags/PRE_ANDY
aclement 19 years ago
parent
commit
385356c6c1
1 changed files with 234 additions and 50 deletions
  1. 234
    50
      weaver/src/org/aspectj/weaver/bcel/BcelShadow.java

+ 234
- 50
weaver/src/org/aspectj/weaver/bcel/BcelShadow.java View File

@@ -1,13 +1,14 @@
/* *******************************************************************
* Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* PARC initial implementation
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* PARC initial implementation
* Alexandre Vasseur support for @AJ aspects
* ******************************************************************/


@@ -23,6 +24,7 @@ import java.util.Map;
import org.aspectj.apache.bcel.Constants;
import org.aspectj.apache.bcel.classfile.Field;
import org.aspectj.apache.bcel.generic.ACONST_NULL;
import org.aspectj.apache.bcel.generic.ALOAD;
import org.aspectj.apache.bcel.generic.ANEWARRAY;
import org.aspectj.apache.bcel.generic.ArrayType;
import org.aspectj.apache.bcel.generic.BranchInstruction;
@@ -30,6 +32,7 @@ import org.aspectj.apache.bcel.generic.ConstantPoolGen;
import org.aspectj.apache.bcel.generic.DUP;
import org.aspectj.apache.bcel.generic.DUP_X1;
import org.aspectj.apache.bcel.generic.FieldInstruction;
import org.aspectj.apache.bcel.generic.INVOKEINTERFACE;
import org.aspectj.apache.bcel.generic.INVOKESPECIAL;
import org.aspectj.apache.bcel.generic.INVOKESTATIC;
import org.aspectj.apache.bcel.generic.Instruction;
@@ -43,6 +46,7 @@ import org.aspectj.apache.bcel.generic.LoadInstruction;
import org.aspectj.apache.bcel.generic.MULTIANEWARRAY;
import org.aspectj.apache.bcel.generic.NEW;
import org.aspectj.apache.bcel.generic.ObjectType;
import org.aspectj.apache.bcel.generic.POP;
import org.aspectj.apache.bcel.generic.PUSH;
import org.aspectj.apache.bcel.generic.ReturnInstruction;
import org.aspectj.apache.bcel.generic.SWAP;
@@ -70,6 +74,7 @@ import org.aspectj.weaver.TypeX;
import org.aspectj.weaver.WeaverMessages;
import org.aspectj.weaver.World;
import org.aspectj.weaver.ast.Var;
import org.aspectj.weaver.ataspectj.Ajc5MemberMaker;


/*
@@ -1093,26 +1098,45 @@ public class BcelShadow extends Shadow {
return il;
}

/**
* Get the Var for the jpStaticPart
* @return
*/
public BcelVar getThisJoinPointStaticPartBcelVar() {
return getThisJoinPointStaticPartBcelVar(false);
}

/**
* Get the Var for the xxxxJpStaticPart, xxx = this or enclosing
* @param isEnclosingJp true to have the enclosingJpStaticPart
* @return
*/
public BcelVar getThisJoinPointStaticPartBcelVar(final boolean isEnclosingJp) {
if (thisJoinPointStaticPartVar == null) {
Field field = getEnclosingClass().getTjpField(this);
Field field = getEnclosingClass().getTjpField(this, isEnclosingJp);
thisJoinPointStaticPartVar =
new BcelFieldRef(
world.getCoreType(TypeX.forName("org.aspectj.lang.JoinPoint$StaticPart")),
isEnclosingJp?
world.getCoreType(TypeX.forName("org.aspectj.lang.JoinPoint$EnclosingStaticPart")):
world.getCoreType(TypeX.forName("org.aspectj.lang.JoinPoint$StaticPart")),
getEnclosingClass().getClassName(),
field.getName());
// getEnclosingClass().warnOnAddedStaticInitializer(this,munger.getSourceLocation());
}
return thisJoinPointStaticPartVar;
}

/**
* Get the Var for the enclosingJpStaticPart
* @return
*/
public BcelVar getThisEnclosingJoinPointStaticPartBcelVar() {
if (enclosingShadow == null) {
// the enclosing of an execution is itself
return getThisJoinPointStaticPartBcelVar();
return getThisJoinPointStaticPartBcelVar(true);
} else {
return ((BcelShadow)enclosingShadow).getThisJoinPointStaticPartBcelVar();
return ((BcelShadow)enclosingShadow).getThisJoinPointStaticPartBcelVar(true);
}
}
@@ -1286,7 +1310,6 @@ public class BcelShadow extends Shadow {
thisAnnotationVars = new HashMap();
// populate..
}
public void initializeTargetAnnotationVars() {
if (targetAnnotationVars != null) return;
if (getKind().isTargetSameAsThis()) {
@@ -2024,9 +2047,9 @@ public class BcelShadow extends Shadow {
for (int i=extraParamOffset; i < nVars; i++) {
varMap.put(i-extraParamOffset, i);
}
localAdviceMethod.getBody().insert(
BcelClassWeaver.genInlineInstructions(adviceMethod,
BcelClassWeaver.genInlineInstructions(adviceMethod,
localAdviceMethod, varMap, fact, true));


@@ -2054,7 +2077,9 @@ public class BcelShadow extends Shadow {
munger.getAdviceArgSetup(
this,
null,
new InstructionList(InstructionConstants.ACONST_NULL)));
(munger.getConcreteAspect().isAnnotationStyleAspect())?
this.loadThisJoinPoint():
new InstructionList(InstructionConstants.ACONST_NULL)));
// adviceMethodInvocation =
advice.append(
Utility.createInvoke(fact, localAdviceMethod)); //(fact, getWorld(), munger.getSignature()));
@@ -2100,31 +2125,62 @@ public class BcelShadow extends Shadow {
// now search through the advice, looking for a call to PROCEED.
// Then we replace the call to proceed with some argument setup, and a
// call to the extracted method.
String proceedName =
NameMangler.proceedMethodName(munger.getSignature().getName());

InstructionHandle curr = localAdviceMethod.getBody().getStart();
InstructionHandle end = localAdviceMethod.getBody().getEnd();
ConstantPoolGen cpg = localAdviceMethod.getEnclosingClass().getConstantPoolGen();
while (curr != end) {
InstructionHandle next = curr.getNext();
Instruction inst = curr.getInstruction();
if ((inst instanceof INVOKESTATIC)
&& proceedName.equals(((INVOKESTATIC) inst).getMethodName(cpg))) {

localAdviceMethod.getBody().append(
curr,
getRedoneProceedCall(
fact,
extractedMethod,
munger,
localAdviceMethod,
proceedVarList));
Utility.deleteInstruction(curr, localAdviceMethod);
}
curr = next;

// inlining support for code style aspects
if (!munger.getConcreteAspect().isAnnotationStyleAspect()) {
String proceedName =
NameMangler.proceedMethodName(munger.getSignature().getName());

InstructionHandle curr = localAdviceMethod.getBody().getStart();
InstructionHandle end = localAdviceMethod.getBody().getEnd();
ConstantPoolGen cpg = localAdviceMethod.getEnclosingClass().getConstantPoolGen();
while (curr != end) {
InstructionHandle next = curr.getNext();
Instruction inst = curr.getInstruction();
if ((inst instanceof INVOKESTATIC)
&& proceedName.equals(((INVOKESTATIC) inst).getMethodName(cpg))) {

localAdviceMethod.getBody().append(
curr,
getRedoneProceedCall(
fact,
extractedMethod,
munger,
localAdviceMethod,
proceedVarList));
Utility.deleteInstruction(curr, localAdviceMethod);
}
curr = next;
}
// and that's it.
} else {
//ATAJ inlining support for @AJ aspects
// [TODO document @AJ code rule: don't manipulate 2 jps proceed at the same time.. in an advice body]
InstructionHandle curr = localAdviceMethod.getBody().getStart();
InstructionHandle end = localAdviceMethod.getBody().getEnd();
ConstantPoolGen cpg = localAdviceMethod.getEnclosingClass().getConstantPoolGen();
while (curr != end) {
InstructionHandle next = curr.getNext();
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(
fact,
extractedMethod,
munger,
localAdviceMethod,
proceedVarList);
//TODO optimize, a POP is added somewhere, what for non void ?
localAdviceMethod.getBody().append(
curr, insteadProceedIl);

Utility.deleteInstruction(curr, localAdviceMethod);
}
curr = next;
}
}
// and that's it.
}

private InstructionList getRedoneProceedCall(
@@ -2153,11 +2209,10 @@ public class BcelShadow extends Shadow {
System.arraycopy(proceedParamTypes, 0, newTypes, 0, len);
proceedParamTypes = newTypes;
}
//System.out.println("stateTypes: " + Arrays.asList(stateTypes));
BcelVar[] proceedVars =
BcelVar[] proceedVars =
Utility.pushAndReturnArrayOfVars(proceedParamTypes, ret, fact, localAdviceMethod);

Type[] stateTypes = callbackMethod.getArgumentTypes();
// System.out.println("stateTypes: " + Arrays.asList(stateTypes));
@@ -2177,8 +2232,117 @@ public class BcelShadow extends Shadow {
ret.append(Utility.createConversion(fact, callbackMethod.getReturnType(),
BcelWorld.makeBcelType(munger.getSignature().getReturnType())));
return ret;
}
}

/**
* ATAJ Handle the inlining for @AJ aspects
*
* @param fact
* @param callbackMethod
* @param munger
* @param localAdviceMethod
* @param argVarList
* @return
*/
private InstructionList getRedoneProceedCallForAnnotationStyle(
InstructionFactory fact,
LazyMethodGen callbackMethod,
BcelAdvice munger,
LazyMethodGen localAdviceMethod,
List argVarList)
{
//if (true) return new InstructionList();

//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 ?

// 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);

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

ResolvedTypeX[] proceedParamTypes =
world.resolve(munger.getSignature().getParameterTypes());
//System.out.println(proceedParamTypes);

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));
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 //FIXME Alex: if so clean up
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.
//
// BcelVar[] adviceVars = munger.getExposedStateAsBcelVars();
// IntMap proceedMap = makeProceedArgumentMap(adviceVars);
//
// System.out.println(proceedMap + " for " + this);
// System.out.println(argVarList);
//
// 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;
}

public void weaveAroundClosure(
BcelAdvice munger,
boolean hasDynamicTest)
@@ -2269,12 +2433,32 @@ public class BcelShadow extends Shadow {
InstructionFactory.createReturn(callbackMethod.getReturnType()));
}
}

// ATAJ for @AJ aspect we need to link the closure with the joinpoint instance
if (Ajc5MemberMaker.isAnnotationStyleAspect(munger.getConcreteAspect())) {
//advice.append(new POP());
closureInstantiation.append(Utility.createInvoke(
getFactory(),
getWorld(),
new Member(
Member.METHOD,
TypeX.forName("org.aspectj.runtime.internal.AroundClosure"),
Modifier.PUBLIC,
"linkClosureAndJoinPoint",
"()Lorg/aspectj/lang/ProceedingJoinPoint;"
)
));
}
//System.err.println(closureInstantiation);


InstructionList advice = new InstructionList();
advice.append(munger.getAdviceArgSetup(this, null, closureInstantiation));
// advice.append(closureInstantiation);

// invoke the advice
advice.append(munger.getNonTestAdviceInstructions(this));
advice.append(returnConversionCode);
advice.append(returnConversionCode);
if (!hasDynamicTest) {
range.append(advice);
@@ -2398,7 +2582,7 @@ public class BcelShadow extends Shadow {
private LazyMethodGen makeClosureClassAndReturnConstructor(
String closureClassName,
LazyMethodGen callbackMethod,
IntMap proceedMap)
IntMap proceedMap)
{
String superClassName = "org.aspectj.runtime.internal.AroundClosure";
Type objectArrayType = new ArrayType(Type.OBJECT, 1);

Loading…
Cancel
Save