From 385356c6c19ff2e3f2899a6e4e80ceab5130cc03 Mon Sep 17 00:00:00 2001 From: aclement Date: Tue, 19 Apr 2005 12:41:22 +0000 Subject: [PATCH] from branch: loads of @AJ changes for inlining strategies, using the right JP, wiring up the closure, etc. --- .../org/aspectj/weaver/bcel/BcelShadow.java | 284 +++++++++++++++--- 1 file changed, 234 insertions(+), 50 deletions(-) diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java b/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java index 675286b16..17f766f28 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java @@ -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); -- 2.39.5