]> source.dussan.org Git - aspectj.git/commitdiff
from branch: loads of @AJ changes for inlining strategies, using the right JP, wiring...
authoraclement <aclement>
Tue, 19 Apr 2005 12:41:22 +0000 (12:41 +0000)
committeraclement <aclement>
Tue, 19 Apr 2005 12:41:22 +0000 (12:41 +0000)
weaver/src/org/aspectj/weaver/bcel/BcelShadow.java

index 675286b160518d62d3eb1a502498972ecc88f56e..17f766f2895e5f0243e61a50dfff8d6e4b6823ef 100644 (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);