View Javadoc

1   /***************************************************************************************
2    * Copyright (c) Jonas BonŽr, Alexandre Vasseur. All rights reserved.                 *
3    * http://aspectwerkz.codehaus.org                                                    *
4    * ---------------------------------------------------------------------------------- *
5    * The software in this package is published under the terms of the LGPL license      *
6    * a copy of which has been included with this distribution in the license.txt file.  *
7    **************************************************************************************/
8   package org.codehaus.aspectwerkz.transform.inlining.compiler;
9   
10  import org.objectweb.asm.ClassWriter;
11  import org.objectweb.asm.CodeVisitor;
12  import org.objectweb.asm.Constants;
13  import org.objectweb.asm.Label;
14  import org.objectweb.asm.Type;
15  
16  import org.codehaus.aspectwerkz.DeploymentModel;
17  import org.codehaus.aspectwerkz.cflow.CflowCompiler;
18  import org.codehaus.aspectwerkz.reflect.ClassInfo;
19  import org.codehaus.aspectwerkz.reflect.ClassInfoHelper;
20  import org.codehaus.aspectwerkz.reflect.MethodInfo;
21  import org.codehaus.aspectwerkz.reflect.ReflectionInfo;
22  import org.codehaus.aspectwerkz.reflect.impl.asm.AsmClassInfo;
23  import org.codehaus.aspectwerkz.aspect.AdviceInfo;
24  import org.codehaus.aspectwerkz.exception.DefinitionException;
25  import org.codehaus.aspectwerkz.aspect.AdviceType;
26  import org.codehaus.aspectwerkz.definition.AspectDefinition;
27  import org.codehaus.aspectwerkz.transform.Compiler;
28  import org.codehaus.aspectwerkz.transform.TransformationConstants;
29  import org.codehaus.aspectwerkz.transform.inlining.EmittedJoinPoint;
30  import org.codehaus.aspectwerkz.transform.inlining.AsmHelper;
31  import org.codehaus.aspectwerkz.transform.inlining.AdviceMethodInfo;
32  import org.codehaus.aspectwerkz.transform.inlining.AspectInfo;
33  import org.codehaus.aspectwerkz.transform.inlining.AspectModelManager;
34  import org.codehaus.aspectwerkz.transform.inlining.spi.AspectModel;
35  import org.codehaus.aspectwerkz.joinpoint.management.JoinPointType;
36  import org.codehaus.aspectwerkz.joinpoint.management.AdviceInfoContainer;
37  
38  import java.lang.reflect.InvocationTargetException;
39  import java.lang.reflect.Modifier;
40  import java.util.Iterator;
41  import java.util.ArrayList;
42  import java.util.List;
43  import java.util.Set;
44  import java.util.HashSet;
45  import java.util.HashMap;
46  import java.util.Map;
47  
48  /***
49   * Abstract base class for the different join point compiler implementations.
50   * <p/>
51   * Compiles/generates a class that represents a specific join point, a class which invokes the advices
52   * and the target join point statically.
53   * <p/>
54   * FIXME: depending on hotswap needs, remove the implements StaticJP or JP decision
55   * FIXME: remove isOptimizedJP and put it global
56   *
57   * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
58   * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur </a>
59   * @author <a href="mailto:the_mindstorm@evolva.ro">Alex Popescu</a>
60   */
61  public abstract class AbstractJoinPointCompiler implements Compiler, TransformationConstants {
62  
63      protected static final String TARGET_CLASS_FIELD_NAME = "TARGET_CLASS";
64      protected static final String THIS_CLASS_FIELD_NAME	  = "THIS_CLASS";
65  
66      // FIXME define these two using VM option - if dump dir specified then dump
67      public static final boolean DUMP_JIT_CLASSES = false;
68      protected static final String DUMP_DIR = "_dump";
69  
70      protected final String m_callerClassName;
71      protected final String m_calleeClassName;
72      protected final String m_callerClassSignature;
73      protected final String m_calleeClassSignature;
74      protected final String m_joinPointClassName;
75      protected final int m_joinPointType;
76      protected final int m_joinPointHash;
77      protected final String m_callerMethodName;
78      protected final String m_callerMethodDesc;
79      protected final int m_callerMethodModifiers;
80      protected final String m_calleeMemberName;
81      protected final String m_calleeMemberDesc;
82      protected final int m_calleeMemberModifiers;
83  
84      protected ClassWriter m_cw;
85      protected AspectInfo[] m_aspectInfos;
86      protected AspectModel[] m_aspectModels;
87      protected AdviceMethodInfo[] m_aroundAdviceMethodInfos;
88      protected AdviceMethodInfo[] m_beforeAdviceMethodInfos;
89      protected AdviceMethodInfo[] m_afterFinallyAdviceMethodInfos;
90      protected AdviceMethodInfo[] m_afterReturningAdviceMethodInfos;
91      protected AdviceMethodInfo[] m_afterThrowingAdviceMethodInfos;
92      protected final List m_customProceedMethodStructs = new ArrayList();
93  
94      protected boolean m_hasAroundAdvices = false;
95      protected boolean m_requiresThisOrTarget = false;
96      protected boolean m_requiresJoinPoint = false;
97  
98      protected String[] m_fieldNames;
99      protected Type[] m_argumentTypes;
100     protected Type m_returnType;
101     protected boolean m_isThisAdvisable = false;
102 
103     /***
104      * Creates a new join point compiler instance.
105      *
106      * @param model the compilation model
107      */
108     public AbstractJoinPointCompiler(final CompilationInfo.Model model) {
109         m_joinPointClassName = model.getJoinPointClassName();
110 
111         final EmittedJoinPoint emittedJoinPoint = model.getEmittedJoinPoint();
112 
113         m_joinPointHash = emittedJoinPoint.getJoinPointHash();
114         m_joinPointType = emittedJoinPoint.getJoinPointType();
115 
116         m_callerMethodName = emittedJoinPoint.getCallerMethodName();
117         m_callerMethodDesc = emittedJoinPoint.getCallerMethodDesc();
118         m_callerMethodModifiers = emittedJoinPoint.getCallerMethodModifiers();
119 
120         m_calleeMemberName = emittedJoinPoint.getCalleeMemberName();
121         m_calleeMemberDesc = emittedJoinPoint.getCalleeMemberDesc();
122         m_calleeMemberModifiers = emittedJoinPoint.getCalleeMemberModifiers();
123 
124         // NOTE: internal compiler class name format is ALWAYS using '/'
125         m_callerClassName = emittedJoinPoint.getCallerClassName().replace('.', '/');
126         m_calleeClassName = emittedJoinPoint.getCalleeClassName().replace('.', '/');
127         m_callerClassSignature = L + emittedJoinPoint.getCallerClassName().replace('.', '/') + SEMICOLON;
128         m_calleeClassSignature = L + emittedJoinPoint.getCalleeClassName().replace('.', '/') + SEMICOLON;
129 
130         m_argumentTypes = getJoinPointArgumentTypes();
131         m_returnType = getJoinPointReturnType();
132 
133         initialize(model);
134     }
135 
136     /***
137      * Initializes the the join point compiler.
138      *
139      * @param model the compilation model
140      */
141     private synchronized void initialize(final CompilationInfo.Model model) {
142         // check if 'target' is Advisable, e.g. can handle runtime per instance deployment
143         checkIfThisIsAdvisable(model);
144 
145         // create the aspect fields
146         final AdviceInfoContainer advices = model.getAdviceInfoContainer();
147 
148         collectAdviceInfo(advices);
149         collectCustomProceedMethods(model, advices);
150 
151         // compute the optimization we can use
152         m_hasAroundAdvices = m_aroundAdviceMethodInfos.length > 0;
153         m_requiresThisOrTarget = requiresThisOrTarget();
154         m_requiresJoinPoint = requiresJoinPoint();
155 
156         // setup models at the end so that they can override m_requiresJoinPoint
157         setupReferencedAspectModels();
158 
159         m_cw = AsmHelper.newClassWriter(true);
160     }
161 
162     /***
163      * Collects the advice info.
164      *
165      * @param advices
166      */
167     private void collectAdviceInfo(final AdviceInfoContainer advices) {
168         final List aspectQualifiedNames = new ArrayList();// in fact a Set but we need indexOf
169         final Set aspectInfos = new HashSet();
170         m_beforeAdviceMethodInfos = getAdviceMethodInfos(
171                 aspectQualifiedNames, aspectInfos, advices.getBeforeAdviceInfos()
172         );
173         m_aroundAdviceMethodInfos = getAdviceMethodInfos(
174                 aspectQualifiedNames, aspectInfos, advices.getAroundAdviceInfos()
175         );
176         m_afterReturningAdviceMethodInfos = getAdviceMethodInfos(
177                 aspectQualifiedNames, aspectInfos, advices.getAfterReturningAdviceInfos()
178         );
179         m_afterFinallyAdviceMethodInfos = getAdviceMethodInfos(
180                 aspectQualifiedNames, aspectInfos, advices.getAfterFinallyAdviceInfos()
181         );
182         m_afterThrowingAdviceMethodInfos = getAdviceMethodInfos(
183                 aspectQualifiedNames, aspectInfos, advices.getAfterThrowingAdviceInfos()
184         );
185 
186         m_aspectInfos = (AspectInfo[]) aspectInfos.toArray(new AspectInfo[aspectInfos.size()]);
187     }
188 
189     /***
190      * Collects the custom proceed methods used in the advice specified.
191      *
192      * @param model
193      * @param advices
194      */
195     private void collectCustomProceedMethods(final CompilationInfo.Model model,
196                                              final AdviceInfoContainer advices) {
197         ClassLoader loader = model.getThisClassInfo().getClassLoader();
198         final AdviceInfo[] beforeAdviceInfos = advices.getBeforeAdviceInfos();
199         for (int i = 0; i < beforeAdviceInfos.length; i++) {
200             collectCustomProceedMethods(beforeAdviceInfos[i], loader);
201         }
202         final AdviceInfo[] aroundAdviceInfos = advices.getAroundAdviceInfos();
203         for (int i = 0; i < aroundAdviceInfos.length; i++) {
204             collectCustomProceedMethods(aroundAdviceInfos[i], loader);
205         }
206         final AdviceInfo[] afterFinallyAdviceInfos = advices.getAfterFinallyAdviceInfos();
207         for (int i = 0; i < afterFinallyAdviceInfos.length; i++) {
208             collectCustomProceedMethods(afterFinallyAdviceInfos[i], loader);
209         }
210         final AdviceInfo[] afterReturningAdviceInfos = advices.getAfterReturningAdviceInfos();
211         for (int i = 0; i < afterReturningAdviceInfos.length; i++) {
212             collectCustomProceedMethods(afterReturningAdviceInfos[i], loader);
213         }
214         final AdviceInfo[] afterThrowingAdviceInfos = advices.getAfterThrowingAdviceInfos();
215         for (int i = 0; i < afterThrowingAdviceInfos.length; i++) {
216             collectCustomProceedMethods(afterThrowingAdviceInfos[i], loader);
217         }
218     }
219 
220     /***
221      * Collects the custom proceed methods used in the advice specified.
222      *
223      * @param adviceInfo
224      * @param loader
225      */
226     private void collectCustomProceedMethods(final AdviceInfo adviceInfo, final ClassLoader loader) {
227         final Type[] paramTypes = adviceInfo.getMethodParameterTypes();
228         if (paramTypes.length != 0) {
229             Type firstParam = paramTypes[0];
230             //TODO should we support JP at other positions or lock the other advice models then so that JP..
231             // ..is not there or first only ?
232             // check if first param is an object but not a JP or SJP
233             if (firstParam.getSort() == Type.OBJECT &&
234                 !firstParam.getClassName().equals(JOIN_POINT_JAVA_CLASS_NAME) &&
235                 !firstParam.getClassName().equals(STATIC_JOIN_POINT_JAVA_CLASS_NAME)) {
236                 ClassInfo classInfo = AsmClassInfo.getClassInfo(firstParam.getClassName(), loader);
237                 if (ClassInfoHelper.implementsInterface(classInfo, JOIN_POINT_JAVA_CLASS_NAME) ||
238                     ClassInfoHelper.implementsInterface(classInfo, STATIC_JOIN_POINT_JAVA_CLASS_NAME)) {
239                     // we have ourselves a custom joinpoint
240                     MethodInfo[] methods = classInfo.getMethods();
241                     for (int j = 0; j < methods.length; j++) {
242                         MethodInfo method = methods[j];
243                         if (method.getName().equals(PROCEED_METHOD_NAME)) {
244                             // we inherit the binding from the advice that actually use us
245                             // for now the first advice sets the rule
246                             // it is up to the user to ensure consistency if the custom proceed
247                             // is used more than once in different advices.
248                             m_customProceedMethodStructs.add(new CustomProceedMethodStruct(
249                                     method,
250                                     adviceInfo.getMethodToArgIndexes()
251                             ));
252                         }
253                     }
254                 }
255             }
256         }
257     }
258 
259     /***
260      * Checks if the this class implements the Advisable interface.
261      *
262      * @param model
263      */
264     private void checkIfThisIsAdvisable(final CompilationInfo.Model model) {
265         if (!Modifier.isStatic(m_callerMethodModifiers)) {
266             ClassInfo[] interfaces = model.getThisClassInfo().getInterfaces();
267             for (int i = 0; i < interfaces.length; i++) {
268                 if (interfaces[i].getName().equals(ADVISABLE_CLASS_JAVA_NAME)) {
269                     m_isThisAdvisable = true;
270                     break;
271                 }
272             }
273         }
274     }
275 
276     /***
277      * Retrives and sets the aspect models that are referenced in this compilation phase.
278      */
279     private void setupReferencedAspectModels() {
280         Map aspectModelMap = new HashMap();
281         for (int i = 0; i < m_aspectInfos.length; i++) {
282             AspectDefinition aspectDef = m_aspectInfos[i].getAspectDefinition();
283             if (aspectDef.isAspectWerkzAspect()) {
284                 continue; // AW Aspect Model not managed by AspectModelManager
285             }
286             String type = aspectDef.getAspectModel();
287             AspectModel aspectModel = AspectModelManager.getModelFor(type);
288             aspectModelMap.put(type, aspectModel);
289             if (aspectModel.requiresReflectiveInfo()) {
290                 m_requiresJoinPoint = true; // if at least one model requries RTTI then build it
291             }
292         }
293         m_aspectModels = (AspectModel[]) aspectModelMap.values().toArray(new AspectModel[aspectModelMap.size()]);
294     }
295 
296     /***
297      * Returns the join point interface class name.
298      *
299      * @return
300      */
301     private String getJoinPointInterface() {
302         String joinPointInterface;
303         if (requiresProceedMethod() || m_requiresJoinPoint) {
304             joinPointInterface = JOIN_POINT_CLASS_NAME;
305         } else {
306             joinPointInterface = STATIC_JOIN_POINT_CLASS_NAME;
307         }
308         return joinPointInterface;
309     }
310 
311     /***
312      * Retrieves the advice method infos.
313      *
314      * @param aspectQualifiedNames
315      * @param aspectInfos
316      * @param adviceInfos
317      * @return
318      */
319     protected AdviceMethodInfo[] getAdviceMethodInfos(final List aspectQualifiedNames,
320                                                       final Set aspectInfos,
321                                                       final AdviceInfo[] adviceInfos) {
322         List adviceMethodInfosSet = new ArrayList();
323         for (int i = 0; i < adviceInfos.length; i++) {
324             AdviceInfo adviceInfo = adviceInfos[i];
325 
326             // if we have a perinstance deployed aspect and a static member CALLER -> skip and go on
327             DeploymentModel deploymentModel = adviceInfo.getAdviceDefinition().getAspectDefinition()
328                     .getDeploymentModel();
329             if (deploymentModel.equals(DeploymentModel.PER_INSTANCE) &&
330                 Modifier.isStatic(m_callerMethodModifiers)) {
331                 continue;
332             }
333 
334             final String aspectClassName = adviceInfo.getAspectClassName().replace('.', '/');
335 
336             if (!aspectQualifiedNames.contains(adviceInfo.getAspectQualifiedName())) {
337                 aspectQualifiedNames.add(adviceInfo.getAspectQualifiedName());
338             }
339             int aspectIndex = aspectQualifiedNames.indexOf(adviceInfo.getAspectQualifiedName());
340             AdviceMethodInfo adviceMethodInfo = new AdviceMethodInfo(
341                     adviceInfo,
342                     ASPECT_FIELD_PREFIX + aspectIndex,
343                     aspectClassName,
344                     L + aspectClassName + SEMICOLON,
345                     m_callerClassSignature,
346                     m_calleeClassSignature,
347                     m_joinPointClassName,
348                     m_calleeMemberDesc
349             );
350             adviceMethodInfosSet.add(adviceMethodInfo);
351             aspectInfos.add(adviceMethodInfo.getAspectInfo());
352         }
353         return (AdviceMethodInfo[]) adviceMethodInfosSet.toArray(new AdviceMethodInfo[adviceMethodInfosSet.size()]);
354     }
355 
356     /***
357      * Creates join point specific fields.
358      */
359     protected abstract void createJoinPointSpecificFields();
360 
361     /***
362      * Creates the signature for the join point.
363      *
364      * @param cv
365      */
366     protected abstract void createSignature(final CodeVisitor cv);
367 
368     /***
369      * Optimized implementation that does not retrieve the parameters from the join point instance but is passed
370      * directly to the method from the input parameters in the 'invoke' method. Can only be used if no around advice
371      * exists.
372      *
373      * @param cv
374      * @param argStartIndex index on stack of first target method arg (0 or 1, depends of static target or not)
375      */
376     protected abstract void createInlinedJoinPointInvocation(final CodeVisitor cv,
377                                                              final boolean isOptimizedJoinPoint,
378                                                              final int argStartIndex,
379                                                              final int joinPointIndex);
380 
381     /***
382      * Creates a call to the target join point, the parameter(s) to the join point are retrieved from the invocation
383      * local join point instance.
384      *
385      * @param cv
386      */
387     protected abstract void createJoinPointInvocation(final CodeVisitor cv);
388 
389     /***
390      * Returns the join points return type.
391      *
392      * @return
393      */
394     protected abstract Type getJoinPointReturnType();
395 
396     /***
397      * Returns the join points argument type(s).
398      *
399      * @return
400      */
401     protected abstract Type[] getJoinPointArgumentTypes();
402 
403     /***
404      * Creates the getRtti method
405      */
406     protected abstract void createGetRttiMethod();
407 
408     /***
409      * Creates the getSignature method
410      */
411     protected abstract void createGetSignatureMethod();
412 
413     /***
414      * Compiles a join point class, one specific class for each distinct join point. The compiled join point class
415      * inherits the base join point class.
416      *
417      * @return the generated, compiled and loaded join point class
418      */
419     public byte[] compile() {
420         try {
421             // TODO: INNER CLASS OR NOT?
422             // flag it as a public static inner class
423             // Note: if <init> changes, we will need to pass the containing instance as arg0 and add a syntetic field
424 //            int innerIndex = m_joinPointClassName.lastIndexOf('$');
425 //            m_cw.visitInnerClass(m_joinPointClassName,
426 //                    m_joinPointClassName.substring(0, innerIndex),
427 //                    m_joinPointClassName.substring(innerIndex + 1, m_joinPointClassName.length()),
428 //                    ACC_PUBLIC + ACC_STATIC);
429 
430             createClassHeader();
431             createMandatoryMethodInAspectModels();
432             createFieldsCommonToAllJoinPoints();
433             createJoinPointSpecificFields();
434             createStaticInitializer();
435             createClinit();
436             createInit();
437             createUtilityMethods();
438             createCopyMethod();
439             createGetSignatureMethod();
440             createInvokeMethod();
441             if (requiresProceedMethod()) {
442                 createProceedMethod();
443             }
444             if (m_requiresJoinPoint) {
445                 createGetRttiMethod();
446             }
447             createCustomProceedMethods();
448             m_cw.visitEnd();
449 
450             if (DUMP_JIT_CLASSES) {
451                 AsmHelper.dumpClass(DUMP_DIR, m_joinPointClassName, m_cw);
452             }
453             return m_cw.toByteArray();
454 
455         } catch (Exception e) {
456             e.printStackTrace();
457             StringBuffer buf = new StringBuffer();
458             buf.append("could not compile join point instance for join point with hash [");
459             buf.append(m_joinPointHash);
460             buf.append("] and declaring class [");
461             buf.append(m_callerClassName);
462             buf.append("] due to: ");
463             if (e instanceof InvocationTargetException) {
464                 buf.append(((InvocationTargetException) e).getTargetException().toString());
465             } else {
466                 buf.append(e.toString());
467             }
468             throw new RuntimeException(buf.toString());
469         }
470     }
471 
472     /***
473      * Creates join point specific fields.
474      */
475     protected void createFieldsCommonToAllJoinPoints() {
476         if (m_returnType.getSort() != Type.VOID) {
477             m_cw.visitField(ACC_PRIVATE, RETURN_VALUE_FIELD_NAME, m_returnType.getDescriptor(), null, null);
478         }
479         m_cw.visitField(
480                 ACC_PRIVATE + ACC_STATIC,
481                 TARGET_CLASS_FIELD_NAME,
482                 CLASS_CLASS_SIGNATURE,
483                 null,
484                 null
485         );
486         
487         m_cw.visitField(
488         		ACC_PRIVATE + ACC_STATIC + ACC_FINAL,
489         		THIS_CLASS_FIELD_NAME,
490         		CLASS_CLASS_SIGNATURE,
491         		null,
492         		null
493         );
494         
495         m_cw.visitField(
496         		ACC_PRIVATE + ACC_STATIC + ACC_FINAL, 
497 				ENCLOSING_SJP_FIELD_NAME, 
498 				ENCLOSING_SJP_FIELD_CLASS_SIGNATURE,
499 				null,
500 				null
501 		);
502         
503         m_cw.visitField(ACC_PRIVATE + ACC_STATIC, META_DATA_FIELD_NAME, MAP_CLASS_SIGNATURE, null, null);
504         m_cw.visitField(
505                 ACC_PRIVATE + ACC_STATIC,
506                 OPTIMIZED_JOIN_POINT_INSTANCE_FIELD_NAME,
507                 L + m_joinPointClassName + SEMICOLON,
508                 null, null
509         );
510         m_cw.visitField(ACC_PRIVATE, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature, null, null);
511         m_cw.visitField(ACC_PRIVATE, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature, null, null);
512         m_cw.visitField(ACC_PRIVATE, STACK_FRAME_COUNTER_FIELD_NAME, I, null, null);
513 
514         if (m_isThisAdvisable) {
515             m_cw.visitField(ACC_PRIVATE, INTERCEPTOR_INDEX_FIELD_NAME, I, null, null);
516 
517             m_cw.visitField(
518                     ACC_PRIVATE, AROUND_INTERCEPTORS_FIELD_NAME,
519                     AROUND_ADVICE_ARRAY_CLASS_SIGNATURE, null, null
520             );
521             m_cw.visitField(ACC_PRIVATE, NR_OF_AROUND_INTERCEPTORS_FIELD_NAME, I, null, null);
522 
523             m_cw.visitField(
524                     ACC_PRIVATE, BEFORE_INTERCEPTORS_FIELD_NAME,
525                     BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE, null, null
526             );
527             m_cw.visitField(ACC_PRIVATE, NR_OF_BEFORE_INTERCEPTORS_FIELD_NAME, I, null, null);
528 
529             m_cw.visitField(
530                     ACC_PRIVATE, AFTER_INTERCEPTORS_FIELD_NAME,
531                     AFTER_ADVICE_ARRAY_CLASS_SIGNATURE, null, null
532             );
533             m_cw.visitField(ACC_PRIVATE, NR_OF_AFTER_INTERCEPTORS_FIELD_NAME, I, null, null);
534 
535             m_cw.visitField(
536                     ACC_PRIVATE, AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
537                     AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE, null, null
538             );
539             m_cw.visitField(ACC_PRIVATE, NR_OF_AFTER_RETURNING_INTERCEPTORS_FIELD_NAME, I, null, null);
540 
541             m_cw.visitField(
542                     ACC_PRIVATE, AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
543                     AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE, null, null
544             );
545             m_cw.visitField(ACC_PRIVATE, NR_OF_AFTER_THROWING_INTERCEPTORS_FIELD_NAME, I, null, null);
546         }
547     }
548 
549     /***
550      * Creates the clinit method for the join point.
551      */
552     protected void createClinit() {
553         CodeVisitor cv = m_cw.visitMethod(ACC_STATIC, CLINIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE, null, null);
554         cv.visitMethodInsn(
555                 INVOKESTATIC, m_joinPointClassName,
556                 STATIC_INITIALIZATION_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE
557         );
558         cv.visitInsn(RETURN);
559         cv.visitMaxs(0, 0);
560     }
561 
562     /***
563      * Creates the init method for the join point.
564      */
565     protected void createInit() {
566         CodeVisitor cv = m_cw.visitMethod(ACC_PRIVATE, INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE, null, null);
567         cv.visitVarInsn(ALOAD, 0);
568 
569         boolean hasAroundClosureBaseClass = false;
570         AspectModel aspectModel = null;
571 
572         for (int i = 0; i < m_aspectModels.length; i++) {
573             aspectModel = m_aspectModels[i];
574             if (aspectModel.getAroundClosureClassInfo().getSuperClassName() != null) {
575                 hasAroundClosureBaseClass = true;
576                 break;
577             }
578         }
579 
580         if (hasAroundClosureBaseClass) {
581             // invoke the super class constructor
582             aspectModel.createInvocationOfAroundClosureSuperClass(cv);
583         } else {
584             // invoke the constructor of java.lang.Object
585             cv.visitMethodInsn(INVOKESPECIAL, OBJECT_CLASS_NAME, INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE);
586         }
587 
588         resetStackFrameCounter(cv);
589 
590         cv.visitInsn(RETURN);
591         cv.visitMaxs(0, 0);
592     }
593 
594     /***
595      * Creates the class header for the join point.
596      */
597     private void createClassHeader() {
598 
599         Set interfaces = new HashSet();
600         String baseClass = OBJECT_CLASS_NAME;
601 
602         // get the different aspect models required interfaces
603         for (int i = 0; i < m_aspectModels.length; i++) {
604             AspectModel aspectModel = m_aspectModels[i];
605             AspectModel.AroundClosureClassInfo closureClassInfo = aspectModel.getAroundClosureClassInfo();
606             final String superClassName = closureClassInfo.getSuperClassName();
607             final String[] interfaceNames = closureClassInfo.getInterfaceNames();
608             if (superClassName != null) {
609                 if (!baseClass.equals(OBJECT_CLASS_NAME)) {
610                     throw new RuntimeException(
611                             "compiled join point can only subclass one around closure base class but more than registered aspect model requires a closure base class"
612                     );
613                 }
614                 baseClass = superClassName;
615             }
616             if (interfaceNames.length != 0) {
617                 for (int j = 0; j < interfaceNames.length; j++) {
618                     interfaces.add(interfaceNames[j]);
619                 }
620             }
621         }
622 
623         // get the custom join point interfaces
624         for (Iterator it = m_customProceedMethodStructs.iterator(); it.hasNext();) {
625             MethodInfo methodInfo = ((CustomProceedMethodStruct) it.next()).customProceed;
626             interfaces.add(methodInfo.getDeclaringType().getName().replace('.', '/'));
627         }
628 
629         int i = 1;
630         String[] interfaceArr = new String[interfaces.size() + 1];
631         interfaceArr[0] = getJoinPointInterface();
632         for (Iterator it = interfaces.iterator(); it.hasNext(); i++) {
633             interfaceArr[i] = (String) it.next();
634         }
635 
636         m_cw.visit(
637                 AsmHelper.JAVA_VERSION,
638                 ACC_PUBLIC + ACC_SUPER,
639                 m_joinPointClassName,
640                 baseClass,
641                 interfaceArr,
642                 null
643         );
644     }
645 
646     /***
647      * Creates the methods that are mandatory methods in the around closure in the different aspect models.
648      */
649     private void createMandatoryMethodInAspectModels() {
650         for (int i = 0; i < m_aspectModels.length; i++) {
651             m_aspectModels[i].createMandatoryMethods(m_cw, m_joinPointClassName);
652         }
653     }
654 
655     /***
656      * Creates the custom proceed methods.
657      */
658     private void createCustomProceedMethods() {
659         Set addedMethodSignatures = new HashSet();
660         for (Iterator it = m_customProceedMethodStructs.iterator(); it.hasNext();) {
661             CustomProceedMethodStruct customProceedStruct = (CustomProceedMethodStruct) it.next();
662             MethodInfo methodInfo = customProceedStruct.customProceed;
663             final String desc = methodInfo.getSignature();
664 
665             if (addedMethodSignatures.contains(desc)) {
666                 continue;
667             }
668             addedMethodSignatures.add(desc);
669 
670             CodeVisitor cv = m_cw.visitMethod(
671                     ACC_PUBLIC | ACC_FINAL,
672                     PROCEED_METHOD_NAME,
673                     desc,
674                     new String[]{
675                         THROWABLE_CLASS_NAME
676                     },
677                     null
678             );
679 
680             // update the joinpoint instance with the given values
681             // starts at 1 since first arg is the custom join point by convention
682             //TODO see JoinPointManage for this custom jp is first convention
683             int argStackIndex = 1;
684             for (int i = 1; i < customProceedStruct.adviceToTargetArgs.length; i++) {
685                 int targetArg = customProceedStruct.adviceToTargetArgs[i];
686                 if (targetArg >= 0) {
687                     // regular arg
688                     String fieldName = m_fieldNames[targetArg];
689                     cv.visitVarInsn(ALOAD, 0);
690                     Type type = m_argumentTypes[targetArg];
691                     argStackIndex = AsmHelper.loadType(cv, argStackIndex, type);
692                     cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, fieldName, type.getDescriptor());
693                 } else if (targetArg == AdviceInfo.TARGET_ARG) {
694                     cv.visitVarInsn(ALOAD, 0);
695                     argStackIndex = AsmHelper.loadType(cv, argStackIndex, Type.getType(m_calleeClassSignature));
696                     cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
697                 } else if (targetArg == AdviceInfo.THIS_ARG) {
698                     cv.visitVarInsn(ALOAD, 0);
699                     argStackIndex = AsmHelper.loadType(cv, argStackIndex, Type.getType(m_callerClassSignature));
700                     cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
701                 } else {
702                     ;//skip it
703                 }
704             }
705 
706             // call proceed()
707             // and handles unwrapping for returning primitive
708             Type returnType = Type.getType(customProceedStruct.customProceed.getReturnType().getSignature());
709             if (AsmHelper.isPrimitive(returnType)) {
710                 cv.visitVarInsn(ALOAD, 0);
711                 cv.visitMethodInsn(
712                         INVOKESPECIAL,
713                         m_joinPointClassName,
714                         PROCEED_METHOD_NAME,
715                         PROCEED_METHOD_SIGNATURE
716                 );
717                 AsmHelper.unwrapType(cv, returnType);
718             } else {
719                 cv.visitVarInsn(ALOAD, 0);
720                 cv.visitMethodInsn(
721                         INVOKESPECIAL,
722                         m_joinPointClassName,
723                         PROCEED_METHOD_NAME,
724                         PROCEED_METHOD_SIGNATURE
725                 );
726                 if (!returnType.getClassName().equals(OBJECT_CLASS_SIGNATURE)) {
727                     cv.visitTypeInsn(CHECKCAST, returnType.getInternalName());
728                 }
729             }
730             AsmHelper.addReturnStatement(cv, returnType);
731             cv.visitMaxs(0, 0);
732         }
733     }
734 
735     /***
736      * Creates the static initialization method (not clinit) for the join point.
737      */
738     protected void createStaticInitializer() {
739         CodeVisitor cv = m_cw.visitMethod(
740                 ACC_STATIC | ACC_PUBLIC,
741                 STATIC_INITIALIZATION_METHOD_NAME,
742                 NO_PARAM_RETURN_VOID_SIGNATURE,
743                 null, null
744         );
745 
746         Label tryLabel = new Label();
747         cv.visitLabel(tryLabel);
748         cv.visitLdcInsn(m_calleeClassName.replace('/', '.'));
749         cv.visitMethodInsn(INVOKESTATIC, CLASS_CLASS, FOR_NAME_METHOD_NAME, FOR_NAME_METHOD_SIGNATURE);
750         cv.visitFieldInsn(PUTSTATIC, m_joinPointClassName, TARGET_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
751 
752         cv.visitLdcInsn(m_callerClassName.replace('/', '.'));
753         cv.visitMethodInsn(INVOKESTATIC, CLASS_CLASS, FOR_NAME_METHOD_NAME, FOR_NAME_METHOD_SIGNATURE);
754         cv.visitFieldInsn(PUTSTATIC, m_joinPointClassName, THIS_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
755         
756         Label finallyLabel = new Label();
757         cv.visitLabel(finallyLabel);
758 
759         Label gotoFinallyLabel = new Label();
760         cv.visitJumpInsn(GOTO, gotoFinallyLabel);
761 
762         Label catchLabel = new Label();
763         cv.visitLabel(catchLabel);
764         cv.visitVarInsn(ASTORE, 0);
765 
766         cv.visitVarInsn(ALOAD, 0);
767         cv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Throwable", "printStackTrace", "()V");
768 
769         cv.visitTypeInsn(NEW, RUNTIME_EXCEPTION_CLASS_NAME);
770         cv.visitInsn(DUP);
771         cv.visitLdcInsn("could not load target class using Class.forName() in generated join point base class "
772                         + m_joinPointClassName);
773 
774         cv.visitMethodInsn(
775                 INVOKESPECIAL,
776                 RUNTIME_EXCEPTION_CLASS_NAME,
777                 INIT_METHOD_NAME,
778                 RUNTIME_EXCEPTION_INIT_METHOD_SIGNATURE
779         );
780 
781         cv.visitInsn(ATHROW);
782         cv.visitLabel(gotoFinallyLabel);
783 
784         // create the enclosing static joinpoint
785         createEnclosingStaticJoinPoint(cv);
786         
787         // create the metadata map
788         cv.visitTypeInsn(NEW, HASH_MAP_CLASS_NAME);
789         cv.visitInsn(DUP);
790         cv.visitMethodInsn(INVOKESPECIAL, HASH_MAP_CLASS_NAME, INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE);
791         cv.visitFieldInsn(PUTSTATIC, m_joinPointClassName, META_DATA_FIELD_NAME, MAP_CLASS_SIGNATURE);
792 
793         // create the Signature instance
794         createSignature(cv);
795 
796         // create the static JoinPoint instance
797         cv.visitTypeInsn(NEW, m_joinPointClassName);
798         cv.visitInsn(DUP);
799         cv.visitMethodInsn(INVOKESPECIAL, m_joinPointClassName, INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE);
800         cv.visitFieldInsn(
801                 PUTSTATIC,
802                 m_joinPointClassName,
803                 OPTIMIZED_JOIN_POINT_INSTANCE_FIELD_NAME,
804                 L + m_joinPointClassName + SEMICOLON
805         );
806 
807         // create and initialize the aspect fields
808         for (int i = 0; i < m_aspectInfos.length; i++) {
809             createAndInitializeAspectField(m_aspectInfos[i], cv);
810         }
811 
812         cv.visitInsn(RETURN);
813         cv.visitTryCatchBlock(tryLabel, finallyLabel, catchLabel, CLASS_NOT_FOUND_EXCEPTION_CLASS_NAME);
814         cv.visitMaxs(0, 0);
815     }
816 
817     /***
818      * Add and initialize the static field for enclosing joint point static part
819      *
820      * @param cv
821      */
822     protected void createEnclosingStaticJoinPoint(CodeVisitor cv) {
823     	cv.visitFieldInsn(GETSTATIC, 
824     			m_joinPointClassName,
825     			THIS_CLASS_FIELD_NAME, 
826     			CLASS_CLASS_SIGNATURE);
827         cv.visitLdcInsn(m_callerMethodName);
828         cv.visitLdcInsn(m_callerMethodDesc);
829 
830         cv.visitMethodInsn(INVOKESTATIC,
831         		SIGNATURE_FACTORY_CLASS,
832         		NEW_ENCLOSING_SJP_METHOD_NAME,
833         		NEW_ENCLOSING_SJP_METHOD_SIGNATURE);
834     	cv.visitFieldInsn(
835     			PUTSTATIC, 
836 				m_joinPointClassName,
837 				ENCLOSING_SJP_FIELD_NAME, 
838 				ENCLOSING_SJP_FIELD_CLASS_SIGNATURE);
839     }
840     
841     /***
842      * Create and initialize the aspect field for a specific aspect (qualified since it depends
843      * on the param, deployment model, container etc).
844      *
845      * @param aspectInfo
846      * @param cv
847      */
848     protected boolean createAndInitializeAspectField(final AspectInfo aspectInfo, final CodeVisitor cv) {
849         if (aspectInfo.getAspectDefinition().isAspectWerkzAspect()) {
850             // AW aspect
851             // create the field to host the aspect and retrieve the aspect to set it to the field
852             createAspectReferenceField(m_cw, aspectInfo);
853             createAspectInstantiation(cv, aspectInfo, m_joinPointClassName);
854         } else {
855             // non-AW aspect
856             final String type = aspectInfo.getAspectDefinition().getAspectModel();
857             final AspectModel aspectModel = AspectModelManager.getModelFor(type);
858             aspectModel.createAspectReferenceField(m_cw, aspectInfo, m_joinPointClassName);
859             aspectModel.createAspectInstantiation(cv, aspectInfo, m_joinPointClassName);
860         }
861 
862         return false;
863     }
864 
865     /***
866      * Creates aspect reference field (static or non static field).
867      *
868      * @param cw
869      * @param aspectInfo
870      */
871     public static void createAspectReferenceField(final ClassWriter cw,
872                                                   final AspectInfo aspectInfo) {
873         String aspectClassSignature = aspectInfo.getAspectClassSignature();
874 
875         // create a field depending on the aspect deployment model
876         DeploymentModel deploymentModel = aspectInfo.getDeploymentModel();
877         if (deploymentModel.equals(DeploymentModel.PER_JVM) ||
878             deploymentModel.equals(DeploymentModel.PER_CLASS)) {
879             // add the aspect static field
880             cw.visitField(ACC_PRIVATE + ACC_STATIC, aspectInfo.getAspectFieldName(), aspectClassSignature, null, null);
881         } else if (deploymentModel.equals(DeploymentModel.PER_INSTANCE)) {
882             // add the aspect field as a non static field
883             //TODO - may bee skip the aspect and all its advice is target is static, or ctor call
884             //that is no instance available
885             cw.visitField(ACC_PRIVATE, aspectInfo.getAspectFieldName(), aspectClassSignature, null, null);
886         } else {
887             throw new UnsupportedOperationException(
888                     "unsupported deployment model - " +
889                     aspectInfo.getAspectClassName() + " " +
890                     deploymentModel
891             );
892         }
893     }
894 
895     /***
896      * Creates instantiation of aspects using the Aspects.aspectOf() methods which uses the AspectContainer impls.
897      * We are using the THIS_CLASS classloader since the aspect can be visible from that one only f.e. for get/set/call
898      *
899      * @param cv
900      * @param aspectInfo
901      * @param joinPointClassName
902      */
903     public static void createAspectInstantiation(final CodeVisitor cv,
904                                                  final AspectInfo aspectInfo,
905                                                  final String joinPointClassName) {
906         String aspectClassSignature = aspectInfo.getAspectClassSignature();
907         String aspectClassName = aspectInfo.getAspectClassName();
908         // retrieve the aspect set it to the field
909         DeploymentModel deploymentModel = aspectInfo.getDeploymentModel();
910         if (CflowCompiler.isCflowClass(aspectClassName)) {
911             // handle Cflow native aspectOf
912             cv.visitMethodInsn(
913                     INVOKESTATIC,
914                     aspectClassName,
915                     CflowCompiler.CFLOW_ASPECTOF_METHOD_NAME,
916                     "()"+aspectClassSignature
917             );
918             cv.visitFieldInsn(PUTSTATIC, joinPointClassName, aspectInfo.getAspectFieldName(), aspectClassSignature);
919         } else if (deploymentModel.equals(DeploymentModel.PER_JVM)) {
920             // AW-355, AW-415 we need a ClassLoader here
921             cv.visitFieldInsn(GETSTATIC, joinPointClassName, THIS_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
922             cv.visitMethodInsn(
923                     INVOKEVIRTUAL, CLASS_CLASS, GETCLASSLOADER_METHOD_NAME,
924                     CLASS_CLASS_GETCLASSLOADER_METHOD_SIGNATURE
925             );
926             cv.visitLdcInsn(aspectInfo.getAspectQualifiedName());
927             cv.visitLdcInsn(aspectInfo.getAspectDefinition().getContainerClassName());
928             cv.visitMethodInsn(
929                     INVOKESTATIC,
930                     ASPECTS_CLASS_NAME,
931                     ASPECT_OF_METHOD_NAME,
932                     ASPECT_OF_PER_JVM_METHOD_SIGNATURE
933             );
934             cv.visitTypeInsn(CHECKCAST, aspectClassName);
935             cv.visitFieldInsn(PUTSTATIC, joinPointClassName, aspectInfo.getAspectFieldName(), aspectClassSignature);
936         } else if (deploymentModel.equals(DeploymentModel.PER_CLASS)) {
937             cv.visitLdcInsn(aspectInfo.getAspectQualifiedName());
938             cv.visitLdcInsn(aspectInfo.getAspectDefinition().getContainerClassName());
939             cv.visitFieldInsn(GETSTATIC, joinPointClassName, THIS_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
940             cv.visitMethodInsn(
941                     INVOKESTATIC,
942                     ASPECTS_CLASS_NAME,
943                     ASPECT_OF_METHOD_NAME,
944                     ASPECT_OF_PER_CLASS_METHOD_SIGNATURE
945             );
946             cv.visitTypeInsn(CHECKCAST, aspectClassName);
947             cv.visitFieldInsn(PUTSTATIC, joinPointClassName, aspectInfo.getAspectFieldName(), aspectClassSignature);
948         } else if (deploymentModel.equals(DeploymentModel.PER_INSTANCE)) {
949         } else {
950             throw new UnsupportedOperationException(
951                     "unsupported deployment model - " +
952                     aspectInfo.getAspectClassName() + " " +
953                     deploymentModel
954             );
955         }
956     }
957 
958     /***
959      * Creates the 'invoke' method. If possible delegates to the target join point directly, e.g. does not invoke the
960      * 'proceed' method (Used when a join point has zero around advice).
961      */
962     protected void createInvokeMethod() {
963 
964         final String invokeDesc = buildInvokeMethodSignature();
965 
966         // create the method
967         CodeVisitor cv = m_cw.visitMethod(
968                 ACC_PUBLIC + ACC_FINAL + ACC_STATIC,
969                 INVOKE_METHOD_NAME,
970                 invokeDesc,
971                 new String[]{
972                     THROWABLE_CLASS_NAME
973                 },
974                 null
975         );
976 
977         // compute the callee and caller index from the invoke(..) signature
978         int calleeIndex = INDEX_NOTAVAILABLE;
979         int argStartIndex = 0;
980         if (!Modifier.isStatic(m_calleeMemberModifiers) &&
981             m_joinPointType != JoinPointType.CONSTRUCTOR_CALL_INT &&
982             m_joinPointType != JoinPointType.HANDLER_INT) {
983             calleeIndex = 0;
984             argStartIndex++;
985         } else {
986             calleeIndex = INDEX_NOTAVAILABLE;// no callee in the invoke(..) parameters
987         }
988         int callerIndex = argStartIndex + AsmHelper.getRegisterDepth(m_argumentTypes);
989 
990         // custom logic overrides for handler jp
991         if (m_joinPointType == JoinPointType.HANDLER_INT) {
992             calleeIndex = 0;
993             callerIndex = 2;
994             argStartIndex = 1;
995         }
996 
997         // do we need to keep track of CALLEE, ARGS etc, if not then completely skip it
998         // and make use of the optimized join point instance
999         // while not using its fields (does not support reentrancy and thread safety)
1000         final boolean isOptimizedJoinPoint = !m_requiresJoinPoint && !requiresProceedMethod();
1001         int joinPointIndex = INDEX_NOTAVAILABLE;
1002 
1003         if (!isOptimizedJoinPoint) {
1004             // create a new JP and makes use of it
1005             joinPointIndex = callerIndex + 1;
1006             createInvocationLocalJoinPointInstance(cv, argStartIndex, joinPointIndex, callerIndex, calleeIndex);
1007         }
1008 
1009         // initialize the instance level aspects (perInstance)
1010         initializeInstanceLevelAspects(cv, isOptimizedJoinPoint, joinPointIndex, callerIndex, calleeIndex);
1011 
1012         // before advices
1013         createBeforeAdviceInvocations(
1014                 cv, isOptimizedJoinPoint, argStartIndex, joinPointIndex, callerIndex, calleeIndex
1015         );
1016 
1017         // handle different combinations of after advice (finally/throwing/returning)
1018         if (m_afterFinallyAdviceMethodInfos.length == 0 &&
1019             m_afterThrowingAdviceMethodInfos.length == 0 &&
1020             !m_isThisAdvisable) {
1021             createPartOfInvokeMethodWithoutAfterFinallyAndAfterThrowingAdviceTypes(
1022                     cv, isOptimizedJoinPoint, joinPointIndex, argStartIndex, callerIndex, calleeIndex
1023             );
1024         } else if (m_afterThrowingAdviceMethodInfos.length == 0 &&
1025                    !m_isThisAdvisable) {
1026             createPartOfInvokeMethodWithoutAfterThrowingAdviceTypes(
1027                     cv, isOptimizedJoinPoint, joinPointIndex, argStartIndex, callerIndex, calleeIndex
1028             );
1029         } else {
1030             createPartOfInvokeMethodWithAllAdviceTypes(
1031                     cv, OPTIMIZED_JOIN_POINT, joinPointIndex, argStartIndex, callerIndex, calleeIndex
1032             );
1033         }
1034 
1035         cv.visitMaxs(0, 0);
1036     }
1037 
1038     /***
1039      * Initializes instance level aspects, retrieves them from the target instance through the
1040      * <code>HasInstanceLevelAspect</code> interfaces.
1041      * <p/>
1042      * Use by 'perInstance', 'perThis' and 'perTarget' deployment models.
1043      *
1044      * @param cv
1045      * @param isOptimizedJoinPoint
1046      * @param joinPointIndex
1047      * @param callerIndex
1048      * @param calleeIndex
1049      */
1050     protected void initializeInstanceLevelAspects(final CodeVisitor cv,
1051                                                   final boolean isOptimizedJoinPoint,
1052                                                   final int joinPointIndex,
1053                                                   final int callerIndex,
1054                                                   final int calleeIndex) {
1055         for (int i = 0; i < m_aspectInfos.length; i++) {
1056             AspectInfo aspectInfo = m_aspectInfos[i];
1057             if (aspectInfo.getDeploymentModel() == DeploymentModel.PER_INSTANCE) {
1058                 // gen code: aspectField = (<TYPE>)((HasInstanceLocalAspect)CALLER).aw$getAspect(className, qualifiedName, containerClassName)
1059                 loadJoinPointInstance(cv, isOptimizedJoinPoint, joinPointIndex);
1060                 if (callerIndex >= 0) {
1061                     cv.visitVarInsn(ALOAD, callerIndex);
1062                 } else {
1063                     // caller instance not available - skipping
1064                     //TODO clean up should not occur
1065                 }
1066                 cv.visitLdcInsn(aspectInfo.getAspectClassName().replace('/', '.'));
1067                 cv.visitLdcInsn(aspectInfo.getAspectQualifiedName());
1068                 cv.visitLdcInsn(aspectInfo.getAspectDefinition().getContainerClassName());
1069                 cv.visitMethodInsn(
1070                         INVOKEINTERFACE,
1071                         HAS_INSTANCE_LEVEL_ASPECT_INTERFACE_NAME,
1072                         GET_INSTANCE_LEVEL_ASPECT_METHOD_NAME,
1073                         GET_INSTANCE_LEVEL_ASPECT_METHOD_SIGNATURE
1074                 );
1075                 cv.visitTypeInsn(CHECKCAST, aspectInfo.getAspectClassName());
1076                 cv.visitFieldInsn(
1077                         PUTFIELD,
1078                         m_joinPointClassName,
1079                         aspectInfo.getAspectFieldName(),
1080                         aspectInfo.getAspectClassSignature()
1081                 );
1082             }
1083         }
1084     }
1085 
1086     /***
1087      * @param cv
1088      * @param isOptimizedJoinPoint
1089      * @param joinPointInstanceIndex
1090      * @param argStartIndex
1091      * @param callerIndex
1092      * @param calleeIndex
1093      */
1094     protected void createPartOfInvokeMethodWithAllAdviceTypes(final CodeVisitor cv,
1095                                                               final boolean isOptimizedJoinPoint,
1096                                                               final int joinPointInstanceIndex,
1097                                                               final int argStartIndex,
1098                                                               final int callerIndex,
1099                                                               final int calleeIndex) {
1100         final int returnValueIndex = (joinPointInstanceIndex != INDEX_NOTAVAILABLE) ?
1101                                      (joinPointInstanceIndex + 1) : callerIndex + 1;
1102         final int exceptionIndex1 = returnValueIndex + 1;
1103         final int exceptionIndex2 = returnValueIndex + 2;
1104 
1105         cv.visitInsn(ACONST_NULL);
1106         cv.visitVarInsn(ASTORE, returnValueIndex);
1107 
1108         Label tryLabel = new Label();
1109         cv.visitLabel(tryLabel);
1110         if (!requiresProceedMethod()) {
1111             // if no around advice then optimize by invoking the target JP directly and no call to proceed()
1112             createInlinedJoinPointInvocation(cv, isOptimizedJoinPoint, argStartIndex, joinPointInstanceIndex);
1113             int stackIndex = returnValueIndex;//use another int since storeType will update it
1114             AsmHelper.storeType(cv, stackIndex, m_returnType);
1115             addReturnedValueToJoinPoint(cv, returnValueIndex, joinPointInstanceIndex, false);
1116         } else {
1117             createInvocationToProceedMethod(cv, joinPointInstanceIndex, returnValueIndex);
1118         }
1119 
1120         createAfterReturningAdviceInvocations(
1121                 cv, isOptimizedJoinPoint, argStartIndex, joinPointInstanceIndex,
1122                 callerIndex, calleeIndex
1123         );
1124 
1125         Label finallyLabel1 = new Label();
1126         cv.visitLabel(finallyLabel1);
1127 
1128         if (m_isThisAdvisable) {
1129             final int registerDepth = callerIndex + 2; // caller is using last register + possible return value
1130             createAfterInterceptorInvocations(cv, joinPointInstanceIndex, registerDepth);
1131         }
1132         createAfterFinallyAdviceInvocations(
1133                 cv, isOptimizedJoinPoint, argStartIndex, joinPointInstanceIndex,
1134                 callerIndex, calleeIndex
1135         );
1136 
1137         Label gotoFinallyLabel = new Label();
1138         cv.visitJumpInsn(GOTO, gotoFinallyLabel);
1139 
1140         Label catchLabel = new Label();
1141         cv.visitLabel(catchLabel);
1142 
1143         // store the exception
1144         cv.visitVarInsn(ASTORE, exceptionIndex1);
1145 
1146         if (m_isThisAdvisable) {
1147             createAfterThrowingInterceptorInvocations(cv, joinPointInstanceIndex, exceptionIndex1);
1148         }
1149 
1150         // loop over the after throwing advices
1151         for (int i = m_afterThrowingAdviceMethodInfos.length - 1; i >= 0; i--) {
1152             AdviceMethodInfo advice = m_afterThrowingAdviceMethodInfos[i];
1153 
1154             // set the exception argument index
1155             advice.setSpecialArgumentIndex(exceptionIndex1);
1156 
1157             // if (e instanceof TYPE) {...}
1158             cv.visitVarInsn(ALOAD, exceptionIndex1);
1159 
1160             final String specialArgTypeName = advice.getSpecialArgumentTypeName();
1161             if (specialArgTypeName != null) {
1162                 // after throwing <TYPE>
1163                 cv.visitTypeInsn(INSTANCEOF, specialArgTypeName);
1164 
1165                 Label ifInstanceOfLabel = new Label();
1166                 cv.visitJumpInsn(IFEQ, ifInstanceOfLabel);
1167 
1168                 // after throwing advice invocation
1169                 createAfterAdviceInvocation(
1170                         cv, isOptimizedJoinPoint, advice, joinPointInstanceIndex,
1171                         argStartIndex, callerIndex, calleeIndex, exceptionIndex1
1172                 );
1173 
1174                 cv.visitLabel(ifInstanceOfLabel);
1175             } else {
1176                 // after throwing
1177                 createAfterAdviceInvocation(
1178                         cv, isOptimizedJoinPoint, advice, joinPointInstanceIndex,
1179                         argStartIndex, callerIndex, calleeIndex, INDEX_NOTAVAILABLE
1180                 );
1181             }
1182         }
1183 
1184         // rethrow exception
1185         cv.visitVarInsn(ALOAD, exceptionIndex1);
1186         cv.visitInsn(ATHROW);
1187 
1188         // store exception
1189         Label exceptionLabel = new Label();
1190         cv.visitLabel(exceptionLabel);
1191         cv.visitVarInsn(ASTORE, exceptionIndex2);
1192 
1193         // after finally advice invocation
1194         Label finallyLabel2 = new Label();
1195         cv.visitLabel(finallyLabel2);
1196 
1197         if (m_isThisAdvisable) {
1198             final int registerDepth = callerIndex + 2; // caller is using last register + possible return value
1199             createAfterInterceptorInvocations(cv, joinPointInstanceIndex, registerDepth);
1200         }
1201         createAfterFinallyAdviceInvocations(
1202                 cv, isOptimizedJoinPoint, argStartIndex, joinPointInstanceIndex,
1203                 callerIndex, calleeIndex
1204         );
1205 
1206         // rethrow exception
1207         cv.visitVarInsn(ALOAD, exceptionIndex2);
1208         cv.visitInsn(ATHROW);
1209         cv.visitLabel(gotoFinallyLabel);
1210 
1211         // unwrap if around advice and return in all cases
1212         if (m_returnType.getSort() != Type.VOID) {
1213             if (requiresProceedMethod()) {
1214                 cv.visitVarInsn(ALOAD, returnValueIndex);
1215                 AsmHelper.unwrapType(cv, m_returnType);
1216             } else {
1217                 AsmHelper.loadType(cv, returnValueIndex, m_returnType);
1218             }
1219         }
1220 
1221         AsmHelper.addReturnStatement(cv, m_returnType);
1222 
1223         // build up the exception table
1224         cv.visitTryCatchBlock(tryLabel, finallyLabel1, catchLabel, THROWABLE_CLASS_NAME);
1225         cv.visitTryCatchBlock(tryLabel, finallyLabel1, exceptionLabel, null);
1226         cv.visitTryCatchBlock(catchLabel, finallyLabel2, exceptionLabel, null);
1227     }
1228 
1229     /***
1230      * @param cv
1231      * @param isOptimizedJoinPoint
1232      * @param joinPointInstanceIndex
1233      * @param argStartIndex
1234      * @param callerIndex
1235      * @param calleeIndex
1236      */
1237     protected void createPartOfInvokeMethodWithoutAfterThrowingAdviceTypes(final CodeVisitor cv,
1238                                                                            final boolean isOptimizedJoinPoint,
1239                                                                            final int joinPointInstanceIndex,
1240                                                                            final int argStartIndex,
1241                                                                            final int callerIndex,
1242                                                                            final int calleeIndex) {
1243         final int returnValueIndex = (joinPointInstanceIndex != INDEX_NOTAVAILABLE) ?
1244                                      (joinPointInstanceIndex + 1) : callerIndex + 1;
1245         final int exceptionIndex = returnValueIndex + 1;
1246 
1247         cv.visitInsn(ACONST_NULL);
1248         cv.visitVarInsn(ASTORE, returnValueIndex);
1249 
1250         Label tryLabel = new Label();
1251         cv.visitLabel(tryLabel);
1252         if (!requiresProceedMethod()) {
1253             // if no around advice then optimize by invoking the target JP directly and no call to proceed()
1254             createInlinedJoinPointInvocation(cv, isOptimizedJoinPoint, argStartIndex, joinPointInstanceIndex);
1255             int stackIndex = returnValueIndex;//use another int since storeType will update it
1256             AsmHelper.storeType(cv, stackIndex, m_returnType);
1257             addReturnedValueToJoinPoint(cv, returnValueIndex, joinPointInstanceIndex, false);
1258         } else {
1259             createInvocationToProceedMethod(cv, joinPointInstanceIndex, returnValueIndex);
1260         }
1261 
1262         createAfterReturningAdviceInvocations(
1263                 cv, isOptimizedJoinPoint, argStartIndex, joinPointInstanceIndex,
1264                 callerIndex, calleeIndex
1265         );
1266 
1267         Label finallyLabel1 = new Label();
1268         cv.visitLabel(finallyLabel1);
1269 
1270         createAfterFinallyAdviceInvocations(
1271                 cv, isOptimizedJoinPoint, argStartIndex, joinPointInstanceIndex,
1272                 callerIndex, calleeIndex
1273         );
1274 
1275         Label gotoFinallyLabel = new Label();
1276         cv.visitJumpInsn(GOTO, gotoFinallyLabel);
1277 
1278         Label exceptionLabel = new Label();
1279         cv.visitLabel(exceptionLabel);
1280         cv.visitVarInsn(ASTORE, exceptionIndex);
1281 
1282         Label finallyLabel2 = new Label();
1283         cv.visitLabel(finallyLabel2);
1284 
1285         createAfterFinallyAdviceInvocations(
1286                 cv, isOptimizedJoinPoint, argStartIndex, joinPointInstanceIndex,
1287                 callerIndex, calleeIndex
1288         );
1289 
1290         cv.visitVarInsn(ALOAD, exceptionIndex);
1291         cv.visitInsn(ATHROW);
1292 
1293         cv.visitLabel(gotoFinallyLabel);
1294 
1295         // unwrap if around advice and return in all cases
1296         if (m_returnType.getSort() != Type.VOID) {
1297             if (requiresProceedMethod()) {
1298                 cv.visitVarInsn(ALOAD, returnValueIndex);
1299                 AsmHelper.unwrapType(cv, m_returnType);
1300             } else {
1301                 AsmHelper.loadType(cv, returnValueIndex, m_returnType);
1302             }
1303         }
1304 
1305         AsmHelper.addReturnStatement(cv, m_returnType);
1306 
1307         cv.visitTryCatchBlock(tryLabel, finallyLabel1, exceptionLabel, null);
1308         cv.visitTryCatchBlock(exceptionLabel, finallyLabel2, exceptionLabel, null);
1309     }
1310 
1311     /***
1312      * @param cv
1313      * @param isOptimizedJoinPoint
1314      * @param joinPointInstanceIndex
1315      * @param argStartIndex
1316      * @param callerIndex
1317      * @param calleeIndex
1318      */
1319     protected void createPartOfInvokeMethodWithoutAfterFinallyAndAfterThrowingAdviceTypes(final CodeVisitor cv,
1320                                                                                           final boolean isOptimizedJoinPoint,
1321                                                                                           final int joinPointInstanceIndex,
1322                                                                                           final int argStartIndex,
1323                                                                                           final int callerIndex,
1324                                                                                           final int calleeIndex) {
1325 
1326         final int returnValueIndex = (joinPointInstanceIndex != INDEX_NOTAVAILABLE) ?
1327                                      (joinPointInstanceIndex + 1) : callerIndex + 1;
1328         if (!requiresProceedMethod()) {
1329             // if no around advice then optimize by invoking the target JP directly and no call to proceed()
1330             createInlinedJoinPointInvocation(cv, isOptimizedJoinPoint, argStartIndex, joinPointInstanceIndex);
1331             int stackIndex = returnValueIndex;//use another int since storeType will update it
1332             AsmHelper.storeType(cv, stackIndex, m_returnType);
1333             addReturnedValueToJoinPoint(cv, returnValueIndex, joinPointInstanceIndex, false);
1334         } else {
1335             createInvocationToProceedMethod(cv, joinPointInstanceIndex, returnValueIndex);
1336         }
1337 
1338 
1339         // after returning advice invocations
1340         createAfterReturningAdviceInvocations(
1341                 cv, isOptimizedJoinPoint, argStartIndex, joinPointInstanceIndex,
1342                 callerIndex, calleeIndex
1343         );
1344 
1345         // unwrap if around advice and return in all cases
1346         if (m_returnType.getSort() != Type.VOID) {
1347             if (requiresProceedMethod()) {
1348                 cv.visitVarInsn(ALOAD, returnValueIndex);
1349                 AsmHelper.unwrapType(cv, m_returnType);
1350             } else {
1351                 AsmHelper.loadType(cv, returnValueIndex, m_returnType);
1352             }
1353         }
1354 
1355         AsmHelper.addReturnStatement(cv, m_returnType);
1356     }
1357 
1358     /***
1359      * Creates an invocation to the proceed method.
1360      *
1361      * @param cv
1362      * @param joinPointInstanceIndex
1363      * @param returnValueIndex
1364      */
1365     protected void createInvocationToProceedMethod(final CodeVisitor cv,
1366                                                    final int joinPointInstanceIndex,
1367                                                    final int returnValueIndex) {
1368         cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
1369         cv.visitMethodInsn(INVOKEVIRTUAL, m_joinPointClassName, PROCEED_METHOD_NAME, PROCEED_METHOD_SIGNATURE);
1370         cv.visitVarInsn(ASTORE, returnValueIndex);
1371     }
1372 
1373     /***
1374      * Creates an "invocation local" join point instance, e.g. one join point per invocation. Needed for thread-safety
1375      * when invoking around advice.
1376      *
1377      * @param cv
1378      * @param argStartIndex          index on stack of first target method arg (0 or 1, depends of static target or
1379      *                               not)
1380      * @param joinPointInstanceIndex
1381      * @param callerIndex
1382      * @param calleeIndex
1383      */
1384     protected void createInvocationLocalJoinPointInstance(final CodeVisitor cv,
1385                                                           final int argStartIndex,
1386                                                           final int joinPointInstanceIndex,
1387                                                           final int callerIndex,
1388                                                           final int calleeIndex) {
1389         // create the join point instance
1390         cv.visitTypeInsn(NEW, m_joinPointClassName);
1391         cv.visitInsn(DUP);
1392         cv.visitMethodInsn(INVOKESPECIAL, m_joinPointClassName, INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE);
1393 
1394         // store the jp on the stack
1395         cv.visitVarInsn(ASTORE, joinPointInstanceIndex);
1396 
1397         // set the argument fields in the join point instance (jp.m_arg<i> = <arg_i>)
1398         int argStackIndex = argStartIndex;
1399         for (int i = 0; i < m_fieldNames.length; i++) {
1400             String fieldName = m_fieldNames[i];
1401             cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
1402             Type type = m_argumentTypes[i];
1403             argStackIndex = AsmHelper.loadType(cv, argStackIndex, type);
1404             cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, fieldName, type.getDescriptor());
1405         }
1406 
1407         // caller (can be assigned to null)
1408         cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
1409         cv.visitVarInsn(ALOAD, callerIndex);
1410         cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
1411 
1412         // callee (can be not available)
1413         cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
1414         if (calleeIndex != INDEX_NOTAVAILABLE) {
1415             cv.visitVarInsn(ALOAD, 0);
1416         } else {
1417             cv.visitInsn(ACONST_NULL);
1418         }
1419         cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
1420 
1421         if (m_isThisAdvisable) {
1422             createInitializationForAdvisableManagement(cv, joinPointInstanceIndex, callerIndex);
1423         }
1424     }
1425 
1426     /***
1427      * Create the proceed() method.
1428      */
1429     protected void createProceedMethod() {
1430 
1431         CodeVisitor cv = m_cw.visitMethod(
1432                 ACC_PUBLIC | ACC_FINAL,
1433                 PROCEED_METHOD_NAME,
1434                 PROCEED_METHOD_SIGNATURE,
1435                 new String[]{
1436                     THROWABLE_CLASS_NAME
1437                 },
1438                 null
1439         );
1440 
1441         if (m_isThisAdvisable) {
1442             createAroundInterceptorInvocations(cv);
1443         }
1444 
1445         incrementStackFrameCounter(cv);
1446 
1447         // set up the labels
1448         Label tryLabel = new Label();
1449         Label defaultCaseLabel = new Label();
1450         Label gotoLabel = new Label();
1451         Label handlerLabel = new Label();
1452         Label endLabel = new Label();
1453 
1454         int nrOfCases = m_aroundAdviceMethodInfos.length;
1455         if (m_isThisAdvisable) {
1456             nrOfCases++;
1457         }
1458 
1459         Label[] caseLabels = new Label[nrOfCases];
1460         Label[] returnLabels = new Label[nrOfCases];
1461         int[] caseNumbers = new int[nrOfCases];
1462         for (int i = 0; i < caseLabels.length; i++) {
1463             caseLabels[i] = new Label();
1464             caseNumbers[i] = i;
1465         }
1466         for (int i = 0; i < returnLabels.length; i++) {
1467             returnLabels[i] = new Label();
1468         }
1469 
1470         // start try-catch block
1471         cv.visitLabel(tryLabel);
1472 
1473         // start the switch block and set the stackframe as the param to the switch
1474         cv.visitVarInsn(ALOAD, 0);
1475         cv.visitFieldInsn(GETFIELD, m_joinPointClassName, STACK_FRAME_COUNTER_FIELD_NAME, I);
1476         cv.visitLookupSwitchInsn(defaultCaseLabel, caseNumbers, caseLabels);
1477 
1478         // add one case for each around advice invocation
1479         for (int i = 0; i < m_aroundAdviceMethodInfos.length; i++) {
1480             cv.visitLabel(caseLabels[i]);
1481 
1482             // gather advice info
1483             AdviceMethodInfo adviceInfo = m_aroundAdviceMethodInfos[i];
1484 
1485             Label endInstanceOflabel = beginRuntimeCheck(cv, false, 0, adviceInfo.getAdviceInfo(), -1);
1486 
1487             // get the aspect instance
1488             loadAspect(cv, NON_OPTIMIZED_JOIN_POINT, 0, adviceInfo.getAspectInfo());
1489 
1490             // load the arguments to the advice from the join point instance plus build up the
1491             // advice method signature
1492             int[] argIndexes = adviceInfo.getAdviceMethodArgIndexes();
1493             for (int j = 0; j < argIndexes.length; j++) {
1494                 int argIndex = argIndexes[j];
1495                 if (argIndex >= 0) {
1496                     Type argumentType = m_argumentTypes[argIndex];
1497                     cv.visitVarInsn(ALOAD, 0);
1498                     cv.visitFieldInsn(
1499                             GETFIELD,
1500                             m_joinPointClassName,
1501                             ARGUMENT_FIELD + argIndex,
1502                             argumentType.getDescriptor()
1503                     );
1504                 } else if (argIndex == AdviceInfo.JOINPOINT_ARG ||
1505                            argIndex == AdviceInfo.STATIC_JOINPOINT_ARG ||
1506                            argIndex == AdviceInfo.VALID_NON_AW_AROUND_CLOSURE_TYPE ||
1507                            argIndex == AdviceInfo.CUSTOM_JOIN_POINT_ARG) {
1508                     cv.visitVarInsn(ALOAD, 0);
1509                 } else if (argIndex == AdviceInfo.TARGET_ARG) {
1510                     loadCallee(cv, NON_OPTIMIZED_JOIN_POINT, 0, INDEX_NOTAVAILABLE);
1511                     // add a cast if runtime check was used
1512                     if (adviceInfo.getAdviceInfo().hasTargetWithRuntimeCheck()) {
1513                         cv.visitTypeInsn(
1514                                 CHECKCAST, adviceInfo.getAdviceInfo().getMethodParameterTypes()[j].getInternalName()
1515                         );
1516                     }
1517                 } else if (argIndex == AdviceInfo.THIS_ARG) {
1518                     loadCaller(cv, NON_OPTIMIZED_JOIN_POINT, 0, INDEX_NOTAVAILABLE);
1519                 } else {
1520                     throw new Error("advice method argument index type is not supported: " + argIndex);
1521                 }
1522             }
1523 
1524             // invoke the advice method
1525             cv.visitMethodInsn(
1526                     INVOKEVIRTUAL,
1527                     adviceInfo.getAspectInfo().getAspectClassName(),
1528                     adviceInfo.getAdviceInfo().getMethodName(),
1529                     adviceInfo.getAdviceInfo().getMethodSignature()
1530             );
1531             cv.visitVarInsn(ASTORE, 1);
1532 
1533             // we need to handle the case when the advice was skipped due to runtime check
1534             // that is : if (runtimeCheck) { ret = advice() } else { ret = proceed() }
1535             if (endInstanceOflabel != null) {
1536                 Label elseInstanceOfLabel = new Label();
1537                 cv.visitJumpInsn(GOTO, elseInstanceOfLabel);
1538                 endRuntimeCheck(cv, adviceInfo.getAdviceInfo(), endInstanceOflabel);
1539                 cv.visitVarInsn(ALOAD, 0);
1540                 cv.visitMethodInsn(INVOKESPECIAL, m_joinPointClassName, PROCEED_METHOD_NAME, PROCEED_METHOD_SIGNATURE);
1541                 cv.visitVarInsn(ASTORE, 1);
1542                 cv.visitLabel(elseInstanceOfLabel);
1543             }
1544 
1545             cv.visitLabel(returnLabels[i]);
1546 
1547             cv.visitVarInsn(ALOAD, 1);
1548             cv.visitInsn(ARETURN);
1549         }
1550 
1551         if (m_isThisAdvisable) {
1552             int delegationCaseIndex = caseLabels.length - 1;
1553             cv.visitLabel(caseLabels[delegationCaseIndex]);
1554             cv.visitVarInsn(ALOAD, 0);
1555             cv.visitInsn(ICONST_0);
1556             cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
1557             cv.visitVarInsn(ALOAD, 0);
1558             cv.visitMethodInsn(INVOKEVIRTUAL, m_joinPointClassName, PROCEED_METHOD_NAME, PROCEED_METHOD_SIGNATURE);
1559 
1560             cv.visitLabel(returnLabels[delegationCaseIndex]);
1561 
1562             cv.visitInsn(ARETURN);
1563         }
1564 
1565         // invoke the target join point in the default case
1566         cv.visitLabel(defaultCaseLabel);
1567 
1568         AsmHelper.prepareWrappingOfPrimitiveType(cv, Type.getReturnType(m_calleeMemberDesc));
1569 
1570         createJoinPointInvocation(cv);
1571 
1572         Type m_returnType = null;
1573         if (m_joinPointType != JoinPointType.CONSTRUCTOR_CALL_INT) {
1574             m_returnType = Type.getReturnType(m_calleeMemberDesc);
1575         } else {
1576             m_returnType = Type.getType(m_calleeClassSignature);
1577         }
1578         AsmHelper.wrapPrimitiveType(cv, m_returnType);
1579         cv.visitVarInsn(ASTORE, 1);
1580 
1581         // store it in Rtti return value
1582         addReturnedValueToJoinPoint(cv, 1, 0, true);
1583 
1584         // set it as the CALLEE instance for ctor call - TODO refactor somewhere else
1585         if (m_joinPointType == JoinPointType.CONSTRUCTOR_CALL_INT) {
1586             cv.visitVarInsn(ALOAD, 0);
1587             cv.visitVarInsn(ALOAD, 1);
1588             cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
1589         }
1590 
1591         cv.visitLabel(gotoLabel);
1592 
1593         cv.visitVarInsn(ALOAD, 1);
1594         cv.visitInsn(ARETURN);
1595 
1596         // finally clause
1597         cv.visitLabel(handlerLabel);
1598         cv.visitVarInsn(ASTORE, 2);
1599         cv.visitLabel(endLabel);
1600 
1601         cv.visitVarInsn(ALOAD, 2);
1602         cv.visitInsn(ATHROW);
1603 
1604         // set up the label table
1605         cv.visitTryCatchBlock(tryLabel, returnLabels[0], handlerLabel, null);
1606         for (int i = 1; i < caseLabels.length; i++) {
1607             Label caseLabel = caseLabels[i];
1608             Label returnLabel = returnLabels[i];
1609             cv.visitTryCatchBlock(caseLabel, returnLabel, handlerLabel, null);
1610         }
1611         cv.visitTryCatchBlock(defaultCaseLabel, gotoLabel, handlerLabel, null);
1612         cv.visitTryCatchBlock(handlerLabel, endLabel, handlerLabel, null);
1613         cv.visitMaxs(0, 0);
1614     }
1615 
1616     /***
1617      * Adds before advice invocations.
1618      *
1619      * @param cv
1620      * @param isOptimizedJoinPoint
1621      * @param argStartIndex          index on stack of first target method arg (0 or 1, depends of static target or
1622      *                               not)
1623      * @param joinPointInstanceIndex >= 0 if STATIC_JOIN_POINT is NOT to be used (around advice)
1624      * @param callerIndex
1625      * @param calleeIndex
1626      */
1627     protected void createBeforeAdviceInvocations(final CodeVisitor cv,
1628                                                  final boolean isOptimizedJoinPoint,
1629                                                  final int argStartIndex,
1630                                                  final int joinPointInstanceIndex, //FIXME redundant -1 with isStaticJP
1631                                                  final int callerIndex,
1632                                                  final int calleeIndex) {
1633         for (int i = 0; i < m_beforeAdviceMethodInfos.length; i++) {
1634             AdviceMethodInfo adviceMethodInfo = m_beforeAdviceMethodInfos[i];
1635 
1636             // runtime check for target() etc
1637             Label endInstanceOflabel = beginRuntimeCheck(
1638                     cv, isOptimizedJoinPoint, joinPointInstanceIndex, adviceMethodInfo.getAdviceInfo(), calleeIndex
1639             );
1640 
1641             //get the aspect instance
1642             loadAspect(cv, isOptimizedJoinPoint, joinPointInstanceIndex, adviceMethodInfo.getAspectInfo());
1643 
1644             AspectDefinition aspectDef = adviceMethodInfo.getAdviceInfo().getAdviceDefinition().getAspectDefinition();
1645             if (aspectDef.isAspectWerkzAspect()) {
1646                 // AW aspect
1647                 int[] argIndexes = adviceMethodInfo.getAdviceMethodArgIndexes();
1648                 // if empty, we consider for now that we have to push JoinPoint for old advice with JoinPoint as sole arg
1649                 for (int j = 0; j < argIndexes.length; j++) {
1650                     int argIndex = argIndexes[j];
1651                     if (argIndex >= 0) {
1652                         Type argumentType = m_argumentTypes[argIndex];
1653                         int argStackIndex = AsmHelper.getRegisterIndexOf(m_argumentTypes, argIndex) + argStartIndex;
1654                         AsmHelper.loadType(cv, argStackIndex, argumentType);
1655                     } else if (argIndex == AdviceInfo.JOINPOINT_ARG || argIndex == AdviceInfo.STATIC_JOINPOINT_ARG) {
1656                         loadJoinPointInstance(cv, isOptimizedJoinPoint, joinPointInstanceIndex);
1657                     } else if (argIndex == AdviceInfo.TARGET_ARG) {
1658                         loadCallee(cv, isOptimizedJoinPoint, joinPointInstanceIndex, calleeIndex);
1659                         // add a cast if runtime check was used
1660                         if (adviceMethodInfo.getAdviceInfo().hasTargetWithRuntimeCheck()) {
1661                             cv.visitTypeInsn(
1662                                     CHECKCAST,
1663                                     adviceMethodInfo.getAdviceInfo().getMethodParameterTypes()[j].getInternalName()
1664                             );
1665                         }
1666                     } else if (argIndex == AdviceInfo.THIS_ARG) {
1667                         loadCaller(cv, isOptimizedJoinPoint, joinPointInstanceIndex, callerIndex);
1668                     } else {
1669                         throw new Error("special argument index is not supported: " + argIndex);
1670                     }
1671                 }
1672             } else {
1673                 // non-AW aspect
1674                 adviceMethodInfo.setJoinPointIndex(joinPointInstanceIndex);
1675                 for (int j = 0; j < m_aspectModels.length; j++) {
1676                     AspectModel aspectModel = m_aspectModels[j];
1677                     if (aspectDef.getAspectModel().equals(aspectModel.getAspectModelType())) {
1678                         aspectModel.createBeforeAdviceArgumentHandling(cv, adviceMethodInfo);
1679                     }
1680                 }
1681             }
1682 
1683             cv.visitMethodInsn(
1684                     INVOKEVIRTUAL,
1685                     adviceMethodInfo.getAspectInfo().getAspectClassName(),
1686                     adviceMethodInfo.getAdviceInfo().getMethodName(),
1687                     adviceMethodInfo.getAdviceInfo().getMethodSignature()
1688             );
1689 
1690             // end label of runtime checks
1691             endRuntimeCheck(cv, adviceMethodInfo.getAdviceInfo(), endInstanceOflabel);
1692         }
1693 
1694         if (m_isThisAdvisable) {
1695             createBeforeInterceptorInvocations(cv, joinPointInstanceIndex, callerIndex + 1);
1696         }
1697     }
1698 
1699     /***
1700      * Adds after advice invocations.
1701      *
1702      * @param cv
1703      * @param isOptimizedJoinPoint
1704      * @param argStartIndex          index on stack of first target method arg (0 or 1, depends of static target or
1705      *                               not)
1706      * @param joinPointInstanceIndex >= 0 if STATIC_JOIN_POINT is NOT to be used (around advice)
1707      * @param callerIndex
1708      * @param calleeIndex
1709      */
1710     protected void createAfterFinallyAdviceInvocations(final CodeVisitor cv,
1711                                                        final boolean isOptimizedJoinPoint,
1712                                                        final int argStartIndex,
1713                                                        final int joinPointInstanceIndex,
1714                                                        final int callerIndex,
1715                                                        final int calleeIndex) {
1716         // add after advice in reverse order
1717         for (int i = m_afterFinallyAdviceMethodInfos.length - 1; i >= 0; i--) {
1718             AdviceMethodInfo advice = m_afterFinallyAdviceMethodInfos[i];
1719             createAfterAdviceInvocation(
1720                     cv, isOptimizedJoinPoint, advice, joinPointInstanceIndex, argStartIndex,
1721                     callerIndex, calleeIndex, INDEX_NOTAVAILABLE
1722             );
1723         }
1724     }
1725 
1726     /***
1727      * Adds after returning advice invocations.
1728      *
1729      * @param cv
1730      * @param isOptimizedJoinPoint
1731      * @param argStartIndex          index on stack of first target method arg (0 or 1, depends of static target or
1732      *                               not)
1733      * @param joinPointInstanceIndex >= 0 if STATIC_JOIN_POINT is NOT to be used (around advice)
1734      * @param callerIndex
1735      * @param calleeIndex
1736      */
1737     protected void createAfterReturningAdviceInvocations(final CodeVisitor cv,
1738                                                          final boolean isOptimizedJoinPoint,
1739                                                          final int argStartIndex,
1740                                                          final int joinPointInstanceIndex,
1741                                                          final int callerIndex,
1742                                                          final int calleeIndex) {
1743 
1744         final int returnValueIndex = (joinPointInstanceIndex != INDEX_NOTAVAILABLE) ?
1745                                      (joinPointInstanceIndex + 1) : callerIndex + 1;
1746 
1747         if (m_isThisAdvisable) {
1748             createAfterReturningInterceptorInvocations(cv, joinPointInstanceIndex, returnValueIndex);
1749         }
1750 
1751         boolean hasPoppedReturnValueFromStack = false;
1752         for (int i = m_afterReturningAdviceMethodInfos.length - 1; i >= 0; i--) {
1753             AdviceMethodInfo advice = m_afterReturningAdviceMethodInfos[i];
1754 
1755             // set the return value index that will be used as arg to advice
1756             advice.setSpecialArgumentIndex(returnValueIndex);
1757 
1758             String specialArgDesc = advice.getSpecialArgumentTypeDesc();
1759             if (specialArgDesc == null) {
1760                 // after returning
1761                 createAfterAdviceInvocation(
1762                         cv, isOptimizedJoinPoint, advice, joinPointInstanceIndex, argStartIndex,
1763                         callerIndex, calleeIndex, INDEX_NOTAVAILABLE
1764                 );
1765             } else {
1766                 // after returning <TYPE>
1767                 if (AsmHelper.isPrimitive(m_returnType)) {
1768                     if (m_returnType.getDescriptor().equals(specialArgDesc)) {
1769                         createAfterAdviceInvocation(
1770                                 cv, isOptimizedJoinPoint, advice, joinPointInstanceIndex, argStartIndex,
1771                                 callerIndex, calleeIndex, returnValueIndex
1772                         );
1773                     }
1774                 } else {
1775                     cv.visitVarInsn(ALOAD, returnValueIndex);
1776 
1777                     cv.visitTypeInsn(INSTANCEOF, advice.getSpecialArgumentTypeName());
1778 
1779                     Label label = new Label();
1780                     cv.visitJumpInsn(IFEQ, label);
1781 
1782                     createAfterAdviceInvocation(
1783                             cv, isOptimizedJoinPoint, advice, joinPointInstanceIndex, argStartIndex,
1784                             callerIndex, calleeIndex, returnValueIndex
1785                     );
1786 
1787                     cv.visitLabel(label);
1788                 }
1789             }
1790         }
1791 
1792         // need the return value in return operation
1793         if (!requiresProceedMethod() && hasPoppedReturnValueFromStack) {
1794             cv.visitVarInsn(ALOAD, returnValueIndex);
1795         }
1796     }
1797 
1798     /***
1799      * Adds a single generic after advice invocation.
1800      *
1801      * @param cv
1802      * @param isOptimizedJoinPoint
1803      * @param adviceMethodInfo
1804      * @param joinPointInstanceIndex
1805      * @param argStartIndex
1806      * @param callerIndex
1807      * @param calleeIndex
1808      * @param specialArgIndex        for afterReturning / Throwing when binding is used
1809      */
1810     protected void createAfterAdviceInvocation(final CodeVisitor cv,
1811                                                final boolean isOptimizedJoinPoint,
1812                                                final AdviceMethodInfo adviceMethodInfo,
1813                                                final int joinPointInstanceIndex,
1814                                                final int argStartIndex,
1815                                                final int callerIndex,
1816                                                final int calleeIndex,
1817                                                final int specialArgIndex) {
1818         // runtime check for target() etc
1819         Label endInstanceOflabel = beginRuntimeCheck(
1820                 cv, isOptimizedJoinPoint, joinPointInstanceIndex,
1821                 adviceMethodInfo.getAdviceInfo(), calleeIndex
1822         );
1823 
1824         // get the aspect instance
1825         loadAspect(cv, isOptimizedJoinPoint, joinPointInstanceIndex, adviceMethodInfo.getAspectInfo());
1826 
1827         AspectDefinition aspectDef = adviceMethodInfo.getAdviceInfo().getAdviceDefinition().getAspectDefinition();
1828         if (aspectDef.isAspectWerkzAspect()) {
1829             // AW aspect
1830             // load the arguments that should be passed to the advice
1831             int[] argIndexes = adviceMethodInfo.getAdviceMethodArgIndexes();
1832             for (int j = 0; j < argIndexes.length; j++) {
1833                 int argIndex = argIndexes[j];
1834                 if (argIndex >= 0) {
1835                     Type argumentType = m_argumentTypes[argIndex];
1836                     int argStackIndex = AsmHelper.getRegisterIndexOf(m_argumentTypes, argIndex) + argStartIndex;
1837                     AsmHelper.loadType(cv, argStackIndex, argumentType);
1838                 } else if (argIndex == AdviceInfo.JOINPOINT_ARG || argIndex == AdviceInfo.STATIC_JOINPOINT_ARG) {
1839                     loadJoinPointInstance(cv, isOptimizedJoinPoint, joinPointInstanceIndex);
1840                 } else if (argIndex == AdviceInfo.TARGET_ARG) {
1841                     loadCallee(cv, isOptimizedJoinPoint, joinPointInstanceIndex, calleeIndex);
1842                     // add a cast if runtime check was used
1843                     if (adviceMethodInfo.getAdviceInfo().hasTargetWithRuntimeCheck()) {
1844                         cv.visitTypeInsn(
1845                                 CHECKCAST,
1846                                 adviceMethodInfo.getAdviceInfo().getMethodParameterTypes()[j].getInternalName()
1847                         );
1848                     }
1849                 } else if (argIndex == AdviceInfo.THIS_ARG) {
1850                     loadCaller(cv, isOptimizedJoinPoint, joinPointInstanceIndex, callerIndex);
1851                 } else if (argIndex == AdviceInfo.SPECIAL_ARGUMENT && specialArgIndex != INDEX_NOTAVAILABLE) {
1852                     Type argumentType = adviceMethodInfo.getAdviceInfo().getMethodParameterTypes()[j];
1853                     AsmHelper.loadType(cv, specialArgIndex, argumentType);
1854                     if (adviceMethodInfo.getAdviceInfo().getAdviceDefinition().getType().equals(
1855                             AdviceType.AFTER_THROWING
1856                     )) {
1857                         cv.visitTypeInsn(CHECKCAST, argumentType.getInternalName());
1858                     }
1859                 } else {
1860                     throw new Error("magic index is not supported: " + argIndex);
1861                 }
1862             }
1863         } else {
1864             // non-AW aspect
1865             adviceMethodInfo.setJoinPointIndex(joinPointInstanceIndex);
1866             for (int i = 0; i < m_aspectModels.length; i++) {
1867                 AspectModel aspectModel = m_aspectModels[i];
1868                 if (aspectDef.getAspectModel().equals(aspectModel.getAspectModelType())) {
1869                     aspectModel.createAfterAdviceArgumentHandling(cv, adviceMethodInfo);
1870                 }
1871             }
1872         }
1873 
1874         cv.visitMethodInsn(
1875                 INVOKEVIRTUAL,
1876                 adviceMethodInfo.getAspectInfo().getAspectClassName(),
1877                 adviceMethodInfo.getAdviceInfo().getMethodName(),
1878                 adviceMethodInfo.getAdviceInfo().getMethodSignature()
1879         );
1880 
1881         // end label of runtime checks
1882         endRuntimeCheck(cv, adviceMethodInfo.getAdviceInfo(), endInstanceOflabel);
1883     }
1884 
1885     /***
1886      * Adds the return value to the RETURNED field.
1887      *
1888      * @param cv
1889      * @param returnValueIndex
1890      * @param joinPointInstanceIndex
1891      * @param unwrap                 set to true if already wrapped on the stack (within proceed() code)
1892      */
1893     protected void addReturnedValueToJoinPoint(final CodeVisitor cv,
1894                                                final int returnValueIndex,
1895                                                final int joinPointInstanceIndex,
1896                                                final boolean unwrap) {
1897         if (m_requiresJoinPoint && m_returnType.getSort() != Type.VOID) {
1898             if (m_joinPointType == JoinPointType.METHOD_EXECUTION_INT
1899                 || m_joinPointType == JoinPointType.METHOD_CALL_INT
1900                 || m_joinPointType == JoinPointType.CONSTRUCTOR_CALL_INT) {
1901                 //TODO should we do something for field get / set
1902                 loadJoinPointInstance(cv, NON_OPTIMIZED_JOIN_POINT, joinPointInstanceIndex);
1903                 if (unwrap && AsmHelper.isPrimitive(m_returnType)) {
1904                     cv.visitVarInsn(ALOAD, returnValueIndex);
1905                     AsmHelper.unwrapType(cv, m_returnType);
1906                 } else {
1907                     AsmHelper.loadType(cv, returnValueIndex, m_returnType);
1908                 }
1909                 cv.visitFieldInsn(
1910                         PUTFIELD, m_joinPointClassName,
1911                         RETURN_VALUE_FIELD_NAME, m_returnType.getDescriptor()
1912                 );
1913             }
1914         }
1915     }
1916 
1917     /***
1918      * Loads the join point instance, takes static/non-static join point access into account.
1919      *
1920      * @param cv
1921      * @param isOptimizedJoinPoint
1922      * @param joinPointInstanceIndex
1923      */
1924     protected void loadJoinPointInstance(final CodeVisitor cv,
1925                                          final boolean isOptimizedJoinPoint,
1926                                          final int joinPointInstanceIndex) {
1927         if (isOptimizedJoinPoint) {
1928             cv.visitFieldInsn(
1929                     GETSTATIC, m_joinPointClassName,
1930                     OPTIMIZED_JOIN_POINT_INSTANCE_FIELD_NAME,
1931                     L + m_joinPointClassName + SEMICOLON
1932             );
1933         } else {
1934             cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
1935         }
1936     }
1937 
1938     /***
1939      * Loads the argument member fields.
1940      *
1941      * @param cv
1942      * @param argStartIndex
1943      */
1944     protected void loadArgumentMemberFields(final CodeVisitor cv, final int argStartIndex) {
1945         int argStackIndex = argStartIndex;
1946         for (int index = 0; index < m_argumentTypes.length; index++) {
1947             Type argumentType = m_argumentTypes[index];
1948             argStackIndex = AsmHelper.loadType(cv, argStackIndex, argumentType);
1949         }
1950     }
1951 
1952     /***
1953      * Loads the arguments.
1954      *
1955      * @param cv
1956      */
1957     protected void loadArguments(final CodeVisitor cv) {
1958         for (int i = 0; i < m_fieldNames.length; i++) {
1959             String fieldName = m_fieldNames[i];
1960             Type argumentType = m_argumentTypes[i];
1961             cv.visitVarInsn(ALOAD, 0);
1962             cv.visitFieldInsn(GETFIELD, m_joinPointClassName, fieldName, argumentType.getDescriptor());
1963         }
1964     }
1965 
1966     /***
1967      * Resets the stack frame counter.
1968      *
1969      * @param cv
1970      */
1971     protected void resetStackFrameCounter(final CodeVisitor cv) {
1972         cv.visitVarInsn(ALOAD, 0);
1973         cv.visitInsn(ICONST_M1);
1974         cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, STACK_FRAME_COUNTER_FIELD_NAME, I);
1975     }
1976 
1977     /***
1978      * Handles the incrementation of the stack frame.
1979      *
1980      * @param cv
1981      */
1982     protected void incrementStackFrameCounter(final CodeVisitor cv) {
1983         cv.visitVarInsn(ALOAD, 0);
1984         cv.visitInsn(DUP);
1985         cv.visitFieldInsn(GETFIELD, m_joinPointClassName, STACK_FRAME_COUNTER_FIELD_NAME, I);
1986         cv.visitInsn(ICONST_1);
1987         cv.visitInsn(IADD);
1988         cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, STACK_FRAME_COUNTER_FIELD_NAME, I);
1989     }
1990 
1991     /***
1992      * Create and load a structure (f.e. array of Object) where args are stored, before setting the Rtti
1993      * with it (See addParametersToRttiInstance). The structure is stored at the given stackFreeIndex.
1994      * <p/>
1995      * We provide here a default implementation that is suitable for method and constructor call and execution.
1996      * See createParameterWrappedAt for field get/set and handler compiler (no array of argument needed)
1997      *
1998      * @param cv
1999      * @param stackFreeIndex
2000      */
2001     protected final void createArgumentArrayAt(final CodeVisitor cv, final int stackFreeIndex) {
2002         AsmHelper.loadIntegerConstant(cv, m_fieldNames.length);
2003         cv.visitTypeInsn(ANEWARRAY, OBJECT_CLASS_NAME);
2004         cv.visitVarInsn(ASTORE, stackFreeIndex);
2005 
2006         for (int i = 0; i < m_argumentTypes.length; i++) {
2007             cv.visitVarInsn(ALOAD, stackFreeIndex);
2008             AsmHelper.loadIntegerConstant(cv, i);
2009             AsmHelper.prepareWrappingOfPrimitiveType(cv, m_argumentTypes[i]);
2010             cv.visitVarInsn(ALOAD, 0);
2011             cv.visitFieldInsn(GETFIELD, m_joinPointClassName, ARGUMENT_FIELD + i, m_argumentTypes[i].getDescriptor());
2012             AsmHelper.wrapPrimitiveType(cv, m_argumentTypes[i]);
2013             cv.visitInsn(AASTORE);
2014         }
2015     }
2016 
2017     /***
2018      * Creates utility methods for the join point (getter, setters etc.).
2019      */
2020     protected void createUtilityMethods() {
2021         CodeVisitor cv;
2022 
2023         // addMetaData
2024         {
2025             cv = m_cw.visitMethod(ACC_PUBLIC, ADD_META_DATA_METHOD_NAME, ADD_META_DATA_METHOD_SIGNATURE, null, null);
2026             cv.visitFieldInsn(GETSTATIC, m_joinPointClassName, META_DATA_FIELD_NAME, MAP_CLASS_SIGNATURE);
2027             cv.visitVarInsn(ALOAD, 1);
2028             cv.visitVarInsn(ALOAD, 2);
2029             cv.visitMethodInsn(
2030                     INVOKEINTERFACE,
2031                     MAP_CLASS_NAME,
2032                     PUT_METHOD_NAME,
2033                     PUT_METHOD_SIGNATURE
2034             );
2035             cv.visitInsn(POP);
2036             cv.visitInsn(RETURN);
2037             cv.visitMaxs(0, 0);
2038         }
2039 
2040         // getMetaData
2041         {
2042             cv = m_cw.visitMethod(ACC_PUBLIC, GET_META_DATA_METHOD_NAME, GET_META_DATA_METHOD_SIGNATURE, null, null);
2043             cv.visitFieldInsn(GETSTATIC, m_joinPointClassName, META_DATA_FIELD_NAME, MAP_CLASS_SIGNATURE);
2044             cv.visitVarInsn(ALOAD, 1);
2045             cv.visitMethodInsn(INVOKEINTERFACE, MAP_CLASS_NAME, GET_METHOD_NAME, GET_METHOD_SIGNATURE);
2046             cv.visitInsn(ARETURN);
2047             cv.visitMaxs(0, 0);
2048         }
2049 
2050         // getCallee
2051         {
2052             cv = m_cw.visitMethod(
2053                     ACC_PUBLIC,
2054                     GET_CALLEE_METHOD_NAME,
2055                     NO_PARAMS_SIGNATURE + OBJECT_CLASS_SIGNATURE,
2056                     null, null
2057             );
2058             cv.visitVarInsn(ALOAD, 0);
2059             cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
2060             cv.visitInsn(ARETURN);
2061             cv.visitMaxs(0, 0);
2062         }
2063 
2064         // getCaller
2065         {
2066             cv = m_cw.visitMethod(
2067                     ACC_PUBLIC,
2068                     GET_CALLER_METHOD_NAME,
2069                     NO_PARAMS_SIGNATURE + OBJECT_CLASS_SIGNATURE,
2070                     null, null
2071             );
2072             cv.visitVarInsn(ALOAD, 0);
2073             cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
2074             cv.visitInsn(ARETURN);
2075             cv.visitMaxs(0, 0);
2076         }
2077 
2078         // getTarget
2079         {
2080             cv = m_cw.visitMethod(
2081                     ACC_PUBLIC,
2082                     GET_TARGET_METHOD_NAME,
2083                     NO_PARAMS_SIGNATURE + OBJECT_CLASS_SIGNATURE,
2084                     null, null
2085             );
2086             cv.visitVarInsn(ALOAD, 0);
2087             cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
2088             cv.visitInsn(ARETURN);
2089             cv.visitMaxs(0, 0);
2090         }
2091 
2092         // getThis
2093         {
2094             cv = m_cw.visitMethod(
2095                     ACC_PUBLIC,
2096                     GET_THIS_METHOD_NAME,
2097                     NO_PARAMS_SIGNATURE + OBJECT_CLASS_SIGNATURE,
2098                     null, null
2099             );
2100             cv.visitVarInsn(ALOAD, 0);
2101             cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
2102             cv.visitInsn(ARETURN);
2103             cv.visitMaxs(0, 0);
2104         }
2105 
2106         // getCallerClass
2107         {
2108             cv =
2109             m_cw.visitMethod(
2110                     ACC_PUBLIC,
2111                     GET_CALLER_CLASS_METHOD_NAME,
2112                     GET_CALLER_CLASS_METHOD_SIGNATURE,
2113                     null,
2114                     null
2115             );
2116             cv.visitFieldInsn(GETSTATIC, m_joinPointClassName, THIS_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
2117             cv.visitInsn(ARETURN);
2118             cv.visitMaxs(0, 0);
2119         }
2120 
2121         // getCalleeClass
2122         {
2123             cv =
2124             m_cw.visitMethod(
2125                     ACC_PUBLIC,
2126                     GET_CALLEE_CLASS_METHOD_NAME,
2127                     GET_CALLEE_CLASS_METHOD_SIGNATURE,
2128                     null,
2129                     null
2130             );
2131             cv.visitFieldInsn(GETSTATIC, m_joinPointClassName, TARGET_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
2132             cv.visitInsn(ARETURN);
2133             cv.visitMaxs(0, 0);
2134         }
2135 
2136         // getTargetClass, deprecated but still there
2137         {
2138             cv =
2139             m_cw.visitMethod(
2140                     ACC_PUBLIC,
2141                     GET_TARGET_CLASS_METHOD_NAME,
2142                     GET_TARGET_CLASS_METHOD_SIGNATURE,
2143                     null,
2144                     null
2145             );
2146             cv.visitFieldInsn(GETSTATIC, m_joinPointClassName, TARGET_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
2147             cv.visitInsn(ARETURN);
2148             cv.visitMaxs(0, 0);
2149         }
2150 
2151         // getType
2152         {
2153             cv = m_cw.visitMethod(ACC_PUBLIC, GET_TYPE_METHOD_NAME, GET_TYPE_METHOD_SIGNATURE, null, null);
2154             AsmHelper.loadIntegerConstant(cv, m_joinPointType);
2155             cv.visitMethodInsn(
2156                     INVOKESTATIC, Type.getType(JoinPointType.class).getInternalName(), "fromInt",
2157                     "(I)" + Type.getType(JoinPointType.class).getDescriptor()
2158             );
2159             cv.visitInsn(ARETURN);
2160             cv.visitMaxs(0, 0);
2161         }
2162         
2163         // getEnclosingStaticJoinPoint
2164         {
2165             cv = m_cw.visitMethod(
2166                     ACC_PUBLIC,
2167                     GET_ENCLOSING_SJP_METHOD_NAME,
2168                     GET_ENCLOSING_SJP_METHOD_SIGNATURE,
2169                     null, 
2170 					null
2171             );
2172             cv.visitVarInsn(ALOAD, 0);
2173             cv.visitFieldInsn(GETSTATIC, 
2174             		m_joinPointClassName, 
2175             		ENCLOSING_SJP_FIELD_NAME, 
2176 					ENCLOSING_SJP_FIELD_CLASS_SIGNATURE 
2177 			);
2178             cv.visitInsn(ARETURN);
2179             cv.visitMaxs(0, 0);
2180         }
2181 
2182     }
2183 
2184     /***
2185      * Creates the copy method.
2186      * <p/>
2187      * TODO refactor and put in subclasses
2188      */
2189     protected void createCopyMethod() {
2190 
2191         CodeVisitor cv = m_cw.visitMethod(ACC_PUBLIC, COPY_METHOD_NAME, COPY_METHOD_SIGNATURE, null, null);
2192 
2193         // create a new join point instance
2194         cv.visitTypeInsn(NEW, m_joinPointClassName);
2195         cv.visitInsn(DUP);
2196         int joinPointCloneIndex = 1;
2197         cv.visitMethodInsn(INVOKESPECIAL, m_joinPointClassName, INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE);
2198         cv.visitVarInsn(ASTORE, joinPointCloneIndex);
2199 
2200         // set stack frame index
2201         cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2202         cv.visitVarInsn(ALOAD, 0);
2203         cv.visitFieldInsn(GETFIELD, m_joinPointClassName, STACK_FRAME_COUNTER_FIELD_NAME, I);
2204         cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, STACK_FRAME_COUNTER_FIELD_NAME, I);
2205 
2206         if (m_isThisAdvisable) {
2207             // set interceptor index
2208             cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2209             cv.visitVarInsn(ALOAD, 0);
2210             cv.visitFieldInsn(GETFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
2211             cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
2212 
2213             // set array length fields
2214             cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2215             cv.visitVarInsn(ALOAD, 0);
2216             cv.visitFieldInsn(GETFIELD, m_joinPointClassName, NR_OF_BEFORE_INTERCEPTORS_FIELD_NAME, I);
2217             cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_BEFORE_INTERCEPTORS_FIELD_NAME, I);
2218             cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2219             cv.visitVarInsn(ALOAD, 0);
2220             cv.visitFieldInsn(GETFIELD, m_joinPointClassName, NR_OF_AROUND_INTERCEPTORS_FIELD_NAME, I);
2221             cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AROUND_INTERCEPTORS_FIELD_NAME, I);
2222             cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2223             cv.visitVarInsn(ALOAD, 0);
2224             cv.visitFieldInsn(GETFIELD, m_joinPointClassName, NR_OF_AFTER_INTERCEPTORS_FIELD_NAME, I);
2225             cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AFTER_INTERCEPTORS_FIELD_NAME, I);
2226             cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2227             cv.visitVarInsn(ALOAD, 0);
2228             cv.visitFieldInsn(GETFIELD, m_joinPointClassName, NR_OF_AFTER_RETURNING_INTERCEPTORS_FIELD_NAME, I);
2229             cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AFTER_RETURNING_INTERCEPTORS_FIELD_NAME, I);
2230             cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2231             cv.visitVarInsn(ALOAD, 0);
2232             cv.visitFieldInsn(GETFIELD, m_joinPointClassName, NR_OF_AFTER_THROWING_INTERCEPTORS_FIELD_NAME, I);
2233             cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AFTER_THROWING_INTERCEPTORS_FIELD_NAME, I);
2234 
2235             // set arrays
2236             cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2237             cv.visitVarInsn(ALOAD, 0);
2238             cv.visitFieldInsn(
2239                     GETFIELD, m_joinPointClassName, BEFORE_INTERCEPTORS_FIELD_NAME,
2240                     BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE
2241             );
2242             cv.visitFieldInsn(
2243                     PUTFIELD, m_joinPointClassName, BEFORE_INTERCEPTORS_FIELD_NAME,
2244                     BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE
2245             );
2246             cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2247             cv.visitVarInsn(ALOAD, 0);
2248             cv.visitFieldInsn(
2249                     GETFIELD, m_joinPointClassName, AROUND_INTERCEPTORS_FIELD_NAME,
2250                     AROUND_ADVICE_ARRAY_CLASS_SIGNATURE
2251             );
2252             cv.visitFieldInsn(
2253                     PUTFIELD, m_joinPointClassName, AROUND_INTERCEPTORS_FIELD_NAME,
2254                     AROUND_ADVICE_ARRAY_CLASS_SIGNATURE
2255             );
2256             cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2257             cv.visitVarInsn(ALOAD, 0);
2258             cv.visitFieldInsn(
2259                     GETFIELD, m_joinPointClassName, AFTER_INTERCEPTORS_FIELD_NAME, AFTER_ADVICE_ARRAY_CLASS_SIGNATURE
2260             );
2261             cv.visitFieldInsn(
2262                     PUTFIELD, m_joinPointClassName, AFTER_INTERCEPTORS_FIELD_NAME, AFTER_ADVICE_ARRAY_CLASS_SIGNATURE
2263             );
2264             cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2265             cv.visitVarInsn(ALOAD, 0);
2266             cv.visitFieldInsn(
2267                     GETFIELD, m_joinPointClassName, AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
2268                     AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE
2269             );
2270             cv.visitFieldInsn(
2271                     PUTFIELD, m_joinPointClassName, AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
2272                     AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE
2273             );
2274             cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2275             cv.visitVarInsn(ALOAD, 0);
2276             cv.visitFieldInsn(
2277                     GETFIELD, m_joinPointClassName, AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
2278                     AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE
2279             );
2280             cv.visitFieldInsn(
2281                     PUTFIELD, m_joinPointClassName, AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
2282                     AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE
2283             );
2284         }
2285 
2286         // set callee
2287         cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2288         cv.visitVarInsn(ALOAD, 0);
2289         cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
2290         cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
2291 
2292         // set caller
2293         cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2294         cv.visitVarInsn(ALOAD, 0);
2295         cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
2296         cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
2297 
2298         // set the arguments
2299         for (int i = 0; i < m_fieldNames.length; i++) {
2300             String fieldName = m_fieldNames[i];
2301             cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2302             cv.visitVarInsn(ALOAD, 0);
2303             cv.visitFieldInsn(GETFIELD, m_joinPointClassName, fieldName, m_argumentTypes[i].getDescriptor());
2304             cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, fieldName, m_argumentTypes[i].getDescriptor());
2305         }
2306 
2307         // set the returned field if any
2308         if (m_returnType.getSort() != Type.VOID) {
2309             cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2310             cv.visitVarInsn(ALOAD, 0);
2311             cv.visitFieldInsn(GETFIELD, m_joinPointClassName, RETURN_VALUE_FIELD_NAME, m_returnType.getDescriptor());
2312             cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, RETURN_VALUE_FIELD_NAME, m_returnType.getDescriptor());
2313         }
2314 
2315         cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2316         cv.visitInsn(ARETURN);
2317         cv.visitMaxs(0, 0);
2318     }
2319 
2320     /***
2321      * Build up the signature of the 'invoke' methods.
2322      *
2323      * @return
2324      */
2325     protected String buildInvokeMethodSignature() {
2326         StringBuffer invokeDescBuf = new StringBuffer();
2327         invokeDescBuf.append('(');
2328         if (m_joinPointType != JoinPointType.CONSTRUCTOR_CALL_INT) {
2329             if (!Modifier.isStatic(m_calleeMemberModifiers)) {
2330                 // callee
2331                 invokeDescBuf.append(m_calleeClassSignature);
2332             }
2333         }
2334         // args
2335         for (int i = 0; i < m_argumentTypes.length; i++) {
2336             Type type = m_argumentTypes[i];
2337             invokeDescBuf.append(type.getDescriptor());
2338         }
2339         // caller
2340         invokeDescBuf.append(m_callerClassSignature);
2341         invokeDescBuf.append(')');
2342         invokeDescBuf.append(m_returnType.getDescriptor());
2343         return invokeDescBuf.toString();
2344     }
2345 
2346     /***
2347      * Return the number of argument the joinpoint has (excludes JoinPoint, Rtti, this / target) but is only
2348      * the number of argument we will have in the rtti (advised method/ctor args or 1 for field / handler)
2349      *
2350      * @return
2351      */
2352     protected final boolean hasArguments() {
2353         return m_argumentTypes.length > 0;
2354     }
2355 
2356     /***
2357      * Checks if at least one advice is using this or target (bounded or runtime check)
2358      *
2359      * @return true if so
2360      */
2361     protected boolean requiresThisOrTarget() {
2362         return m_isThisAdvisable ||
2363                requiresThisOrTarget(m_aroundAdviceMethodInfos) ||
2364                requiresThisOrTarget(m_beforeAdviceMethodInfos) ||
2365                requiresThisOrTarget(m_afterFinallyAdviceMethodInfos) ||
2366                requiresThisOrTarget(m_afterReturningAdviceMethodInfos) ||
2367                requiresThisOrTarget(m_afterThrowingAdviceMethodInfos);
2368     }
2369 
2370     /***
2371      * Checks if at least one advice is using the non static JoinPoint explicitly
2372      *
2373      * @return true if so
2374      */
2375     protected boolean requiresJoinPoint() {
2376         return m_isThisAdvisable ||
2377                requiresJoinPoint(m_aroundAdviceMethodInfos) ||
2378                requiresJoinPoint(m_beforeAdviceMethodInfos) ||
2379                requiresJoinPoint(m_afterFinallyAdviceMethodInfos) ||
2380                requiresJoinPoint(m_afterReturningAdviceMethodInfos) ||
2381                requiresJoinPoint(m_afterThrowingAdviceMethodInfos);
2382     }
2383 
2384     /***
2385      * Checks if at least one advice is using target or this (bounded or runtime check)
2386      *
2387      * @param adviceMethodInfos
2388      * @return true if so
2389      */
2390     protected boolean requiresThisOrTarget(final AdviceMethodInfo[] adviceMethodInfos) {
2391         for (int i = 0; i < adviceMethodInfos.length; i++) {
2392             if (adviceMethodInfos[i].requiresThisOrTarget()) {
2393                 return true;
2394             }
2395         }
2396         return false;
2397     }
2398 
2399     /***
2400      * Checks if at least one advice is using non static JoinPoint explicitly
2401      *
2402      * @param adviceMethodInfos
2403      * @return true if so
2404      */
2405     protected boolean requiresJoinPoint(final AdviceMethodInfo[] adviceMethodInfos) {
2406         for (int i = 0; i < adviceMethodInfos.length; i++) {
2407             if (adviceMethodInfos[i].requiresJoinPoint()) {
2408                 return true;
2409             }
2410         }
2411         return false;
2412     }
2413 
2414     /***
2415      * Handles the if case for runtime check (target instanceof, cflow)
2416      *
2417      * @param cv
2418      * @param isOptimizedJoinPoint
2419      * @param joinPointInstanceIndex
2420      * @param adviceInfo
2421      * @return the label for endIf or null if the adviceInfo did not required runtime check
2422      */
2423     protected Label beginRuntimeCheck(final CodeVisitor cv,
2424                                       final boolean isOptimizedJoinPoint,
2425                                       final int joinPointInstanceIndex,
2426                                       final AdviceInfo adviceInfo,
2427                                       final int calleeIndex) {
2428         Label endRuntimeCheckLabel = null;
2429         if (adviceInfo.hasTargetWithRuntimeCheck() || adviceInfo.getAdviceDefinition().hasCflowOrCflowBelow()) {
2430             endRuntimeCheckLabel = new Label();
2431             // create a specific visitor everytime
2432             RuntimeCheckVisitor runtimeCheckVisitor = new RuntimeCheckVisitor(
2433                     this, cv, adviceInfo.getExpressionInfo(), isOptimizedJoinPoint, joinPointInstanceIndex,
2434                     calleeIndex
2435             );
2436             runtimeCheckVisitor.pushCheckOnStack(adviceInfo.getExpressionContext());
2437             cv.visitJumpInsn(IFEQ, endRuntimeCheckLabel);
2438         }
2439         return endRuntimeCheckLabel;
2440     }
2441 
2442     /***
2443      * Ends the ifLabel of a runtime check
2444      *
2445      * @param cv
2446      * @param adviceInfo
2447      * @param label      if null, then do nothing (means we did not had a runtime check)
2448      */
2449     protected void endRuntimeCheck(final CodeVisitor cv, final AdviceInfo adviceInfo, final Label label) {
2450         if (adviceInfo.hasTargetWithRuntimeCheck() || adviceInfo.getAdviceDefinition().hasCflowOrCflowBelow()) {
2451             cv.visitLabel(label);
2452         }
2453     }
2454 
2455     /***
2456      * Helper method to load the callee on the stack
2457      *
2458      * @param cv
2459      * @param isOptimizedJoinPoint
2460      * @param joinPointIndex
2461      * @param calleeIndex
2462      */
2463     public void loadCallee(final CodeVisitor cv,
2464                            final boolean isOptimizedJoinPoint,
2465                            final int joinPointIndex,
2466                            final int calleeIndex) {
2467         if (isOptimizedJoinPoint) {
2468             // grab the callee from the invoke parameters directly
2469             cv.visitVarInsn(ALOAD, calleeIndex);
2470         } else {
2471             loadJoinPointInstance(cv, isOptimizedJoinPoint, joinPointIndex);
2472             cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
2473         }
2474     }
2475 
2476     /***
2477      * Helper method to load the caller on the stack
2478      *
2479      * @param cv
2480      * @param isOptimizedJoinPoint
2481      * @param joinPointIndex
2482      * @param callerIndex
2483      */
2484     protected void loadCaller(final CodeVisitor cv,
2485                               final boolean isOptimizedJoinPoint,
2486                               final int joinPointIndex,
2487                               final int callerIndex) {
2488         if (isOptimizedJoinPoint) {
2489             // grab the callee from the invoke parameters directly
2490             cv.visitVarInsn(ALOAD, callerIndex);
2491         } else {
2492             loadJoinPointInstance(cv, isOptimizedJoinPoint, joinPointIndex);
2493             cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
2494         }
2495     }
2496 
2497     /***
2498      * Loads the aspect instance.
2499      *
2500      * @param cv
2501      * @param isOptimizedJoinPoint
2502      * @param joinPointIndex
2503      * @param aspectInfo
2504      */
2505     protected void loadAspect(final CodeVisitor cv,
2506                               final boolean isOptimizedJoinPoint,
2507                               final int joinPointIndex,
2508                               final AspectInfo aspectInfo) {
2509         DeploymentModel deploymentModel = aspectInfo.getDeploymentModel();
2510         if (deploymentModel.equals(DeploymentModel.PER_JVM) ||
2511             deploymentModel.equals(DeploymentModel.PER_CLASS)) {
2512             cv.visitFieldInsn(
2513                     GETSTATIC, m_joinPointClassName, aspectInfo.getAspectFieldName(),
2514                     aspectInfo.getAspectClassSignature()
2515             );
2516         } else if (deploymentModel.equals(DeploymentModel.PER_INSTANCE)) {
2517             loadJoinPointInstance(cv, isOptimizedJoinPoint, joinPointIndex);
2518             cv.visitFieldInsn(
2519                     GETFIELD, m_joinPointClassName, aspectInfo.getAspectFieldName(),
2520                     aspectInfo.getAspectClassSignature()
2521             );
2522         } else {
2523             throw new DefinitionException("deployment model [" + deploymentModel + "] is not supported");
2524         }
2525     }
2526 
2527     /***
2528      * Creates an invocation to Aspects.aspectOf(..).
2529      *
2530      * @param cv
2531      * @param isOptimizedJoinPoint
2532      * @param joinPointIndex
2533      * @param callerIndex
2534      * @param calleeIndex
2535      * @param aspectInfo
2536      */
2537     public void createInvocationToAspectOf(final CodeVisitor cv,
2538                                            final boolean isOptimizedJoinPoint,
2539                                            final int joinPointIndex,
2540                                            final int callerIndex,
2541                                            final int calleeIndex,
2542                                            final AspectInfo aspectInfo) {
2543         if (aspectInfo.getDeploymentModel() == DeploymentModel.PER_INSTANCE) {
2544 
2545             //generates code: aspectField = (cast) Aspects.aspect$Of(aspectQN, containerClassName, callee)
2546             loadJoinPointInstance(cv, isOptimizedJoinPoint, joinPointIndex);
2547             cv.visitLdcInsn(aspectInfo.getAspectQualifiedName());
2548             if (calleeIndex >= 0) {
2549                 cv.visitVarInsn(ALOAD, calleeIndex);
2550                 cv.visitLdcInsn(aspectInfo.getAspectDefinition().getContainerClassName());
2551                 cv.visitMethodInsn(
2552                         INVOKESTATIC,
2553                         ASPECTS_CLASS_NAME,
2554                         ASPECT_OF_METHOD_NAME,
2555                         ASPECT_OF_PER_INSTANCE_METHOD_SIGNATURE
2556                 );
2557             } else {
2558                 // TODO: should this really happen? we are filtering at early stage now. - REMOVE CODE BLOCK
2559                 // fallback to perClass
2560                 //aspectField = (cast) Aspects.aspectOf(aspectQN, containerClass, calleeClass)
2561                 cv.visitFieldInsn(GETSTATIC, m_joinPointClassName, TARGET_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
2562                 cv.visitLdcInsn(aspectInfo.getAspectDefinition().getContainerClassName());
2563                 cv.visitMethodInsn(
2564                         INVOKESTATIC,
2565                         ASPECTS_CLASS_NAME,
2566                         ASPECT_OF_METHOD_NAME,
2567                         ASPECT_OF_PER_CLASS_METHOD_SIGNATURE
2568                 );
2569             }
2570             cv.visitTypeInsn(CHECKCAST, aspectInfo.getAspectClassName());
2571             cv.visitFieldInsn(
2572                     PUTFIELD, m_joinPointClassName, aspectInfo.getAspectFieldName(),
2573                     aspectInfo.getAspectClassSignature()
2574             );
2575         }
2576     }
2577 
2578     /***
2579      * Generates code needed for handling Advisable management for the target class.
2580      *
2581      * @param cv
2582      * @param joinPointInstanceIndex
2583      * @param advisableIndex
2584      */
2585     private void createInitializationForAdvisableManagement(final CodeVisitor cv,
2586                                                             final int joinPointInstanceIndex,
2587                                                             final int advisableIndex) {
2588         // interceptor index
2589         cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2590         cv.visitInsn(ICONST_M1);
2591         cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
2592 
2593         initializeAroundInterceptors(cv, joinPointInstanceIndex, advisableIndex);
2594         initializeBeforeInterceptors(cv, joinPointInstanceIndex, advisableIndex);
2595         initializeAfterInterceptors(cv, joinPointInstanceIndex, advisableIndex);
2596         initializeAfterReturningInterceptors(cv, joinPointInstanceIndex, advisableIndex);
2597         initializeAfterThrowingInterceptors(cv, joinPointInstanceIndex, advisableIndex);
2598     }
2599 
2600     /***
2601      * Handle the around interceptor init.
2602      *
2603      * @param cv
2604      * @param joinPointInstanceIndex
2605      * @param advisableIndex
2606      */
2607     private void initializeAroundInterceptors(final CodeVisitor cv,
2608                                               final int joinPointInstanceIndex,
2609                                               final int advisableIndex) {
2610         cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2611         cv.visitVarInsn(ALOAD, advisableIndex);
2612         cv.visitTypeInsn(CHECKCAST, ADVISABLE_CLASS_NAME);
2613         cv.visitLdcInsn(new Integer(m_joinPointClassName.hashCode()));
2614         cv.visitMethodInsn(
2615                 INVOKEINTERFACE,
2616                 ADVISABLE_CLASS_NAME,
2617                 GET_AROUND_ADVICE_METHOD_NAME,
2618                 GET_AROUND_ADVICE_METHOD_SIGNATURE
2619         );
2620         cv.visitFieldInsn(
2621                 PUTFIELD,
2622                 m_joinPointClassName,
2623                 AROUND_INTERCEPTORS_FIELD_NAME,
2624                 AROUND_ADVICE_ARRAY_CLASS_SIGNATURE
2625         );
2626 
2627         cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2628         cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2629         cv.visitFieldInsn(
2630                 GETFIELD,
2631                 m_joinPointClassName,
2632                 AROUND_INTERCEPTORS_FIELD_NAME,
2633                 AROUND_ADVICE_ARRAY_CLASS_SIGNATURE
2634         );
2635         cv.visitInsn(ARRAYLENGTH);
2636         cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AROUND_INTERCEPTORS_FIELD_NAME, I);
2637     }
2638 
2639     /***
2640      * Handle the before interceptor init.
2641      *
2642      * @param cv
2643      * @param joinPointInstanceIndex
2644      * @param advisableIndex
2645      */
2646     private void initializeBeforeInterceptors(final CodeVisitor cv,
2647                                               final int joinPointInstanceIndex,
2648                                               final int advisableIndex) {
2649         cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2650         cv.visitVarInsn(ALOAD, advisableIndex);
2651         cv.visitTypeInsn(CHECKCAST, ADVISABLE_CLASS_NAME);
2652         cv.visitLdcInsn(new Integer(m_joinPointClassName.hashCode()));
2653         cv.visitMethodInsn(
2654                 INVOKEINTERFACE,
2655                 ADVISABLE_CLASS_NAME,
2656                 GET_BEFORE_ADVICE_METHOD_NAME,
2657                 GET_BEFORE_ADVICE_METHOD_SIGNATURE
2658         );
2659         cv.visitFieldInsn(
2660                 PUTFIELD,
2661                 m_joinPointClassName,
2662                 BEFORE_INTERCEPTORS_FIELD_NAME,
2663                 BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE
2664         );
2665 
2666         cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2667         cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2668         cv.visitFieldInsn(
2669                 GETFIELD,
2670                 m_joinPointClassName,
2671                 BEFORE_INTERCEPTORS_FIELD_NAME,
2672                 BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE
2673         );
2674         cv.visitInsn(ARRAYLENGTH);
2675         cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_BEFORE_INTERCEPTORS_FIELD_NAME, I);
2676     }
2677 
2678     /***
2679      * Handle the after finally interceptor init.
2680      *
2681      * @param cv
2682      * @param joinPointInstanceIndex
2683      * @param advisableIndex
2684      */
2685     private void initializeAfterInterceptors(final CodeVisitor cv,
2686                                              final int joinPointInstanceIndex,
2687                                              final int advisableIndex) {
2688         cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2689         cv.visitVarInsn(ALOAD, advisableIndex);
2690         cv.visitTypeInsn(CHECKCAST, ADVISABLE_CLASS_NAME);
2691         cv.visitLdcInsn(new Integer(m_joinPointClassName.hashCode()));
2692         cv.visitMethodInsn(
2693                 INVOKEINTERFACE,
2694                 ADVISABLE_CLASS_NAME,
2695                 GET_AFTER_ADVICE_METHOD_NAME,
2696                 GET_AFTER_ADVICE_METHOD_SIGNATURE
2697         );
2698         cv.visitFieldInsn(
2699                 PUTFIELD,
2700                 m_joinPointClassName,
2701                 AFTER_INTERCEPTORS_FIELD_NAME,
2702                 AFTER_ADVICE_ARRAY_CLASS_SIGNATURE
2703         );
2704 
2705         cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2706         cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2707         cv.visitFieldInsn(
2708                 GETFIELD,
2709                 m_joinPointClassName,
2710                 AFTER_INTERCEPTORS_FIELD_NAME,
2711                 AFTER_ADVICE_ARRAY_CLASS_SIGNATURE
2712         );
2713         cv.visitInsn(ARRAYLENGTH);
2714         cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AFTER_INTERCEPTORS_FIELD_NAME, I);
2715     }
2716 
2717     /***
2718      * Handle the after returning interceptor init.
2719      *
2720      * @param cv
2721      * @param joinPointInstanceIndex
2722      * @param advisableIndex
2723      */
2724     private void initializeAfterReturningInterceptors(final CodeVisitor cv,
2725                                                       final int joinPointInstanceIndex,
2726                                                       final int advisableIndex) {
2727         cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2728         cv.visitVarInsn(ALOAD, advisableIndex);
2729         cv.visitTypeInsn(CHECKCAST, ADVISABLE_CLASS_NAME);
2730         cv.visitLdcInsn(new Integer(m_joinPointClassName.hashCode()));
2731         cv.visitMethodInsn(
2732                 INVOKEINTERFACE,
2733                 ADVISABLE_CLASS_NAME,
2734                 GET_AFTER_RETURNING_ADVICE_METHOD_NAME,
2735                 GET_AFTER_RETURNING_ADVICE_METHOD_SIGNATURE
2736         );
2737         cv.visitFieldInsn(
2738                 PUTFIELD,
2739                 m_joinPointClassName,
2740                 AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
2741                 AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE
2742         );
2743 
2744         cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2745         cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2746         cv.visitFieldInsn(
2747                 GETFIELD,
2748                 m_joinPointClassName,
2749                 AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
2750                 AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE
2751         );
2752         cv.visitInsn(ARRAYLENGTH);
2753         cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AFTER_RETURNING_INTERCEPTORS_FIELD_NAME, I);
2754     }
2755 
2756     /***
2757      * Handle the after throwing interceptor init.
2758      *
2759      * @param cv
2760      * @param joinPointInstanceIndex
2761      * @param advisableIndex
2762      */
2763     private void initializeAfterThrowingInterceptors(final CodeVisitor cv,
2764                                                      final int joinPointInstanceIndex,
2765                                                      final int advisableIndex) {
2766         cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2767         cv.visitVarInsn(ALOAD, advisableIndex);
2768         cv.visitTypeInsn(CHECKCAST, ADVISABLE_CLASS_NAME);
2769         cv.visitLdcInsn(new Integer(m_joinPointClassName.hashCode()));
2770         cv.visitMethodInsn(
2771                 INVOKEINTERFACE,
2772                 ADVISABLE_CLASS_NAME,
2773                 GET_AFTER_THROWING_ADVICE_METHOD_NAME,
2774                 GET_AFTER_THROWING_ADVICE_METHOD_SIGNATURE
2775         );
2776         cv.visitFieldInsn(
2777                 PUTFIELD,
2778                 m_joinPointClassName,
2779                 AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
2780                 AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE
2781         );
2782 
2783         cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2784         cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2785         cv.visitFieldInsn(
2786                 GETFIELD,
2787                 m_joinPointClassName,
2788                 AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
2789                 AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE
2790         );
2791         cv.visitInsn(ARRAYLENGTH);
2792         cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AFTER_THROWING_INTERCEPTORS_FIELD_NAME, I);
2793     }
2794 
2795     /***
2796      * Handles the around interceptor invocations.
2797      *
2798      * @param cv
2799      */
2800     private void createAroundInterceptorInvocations(final CodeVisitor cv) {
2801         cv.visitVarInsn(ALOAD, 0);
2802         cv.visitFieldInsn(GETFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
2803         cv.visitInsn(ICONST_M1);
2804         Label ifStatementLabel = new Label();
2805         cv.visitJumpInsn(IF_ICMPEQ, ifStatementLabel);
2806         cv.visitVarInsn(ALOAD, 0);
2807         cv.visitFieldInsn(GETFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
2808         cv.visitVarInsn(ALOAD, 0);
2809         cv.visitFieldInsn(GETFIELD, m_joinPointClassName, NR_OF_AROUND_INTERCEPTORS_FIELD_NAME, I);
2810         cv.visitJumpInsn(IF_ICMPGE, ifStatementLabel);
2811         cv.visitVarInsn(ALOAD, 0);
2812         cv.visitFieldInsn(
2813                 GETFIELD,
2814                 m_joinPointClassName,
2815                 AROUND_INTERCEPTORS_FIELD_NAME,
2816                 AROUND_ADVICE_ARRAY_CLASS_SIGNATURE
2817         );
2818         cv.visitVarInsn(ALOAD, 0);
2819         cv.visitInsn(DUP);
2820         cv.visitFieldInsn(GETFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
2821         cv.visitInsn(DUP_X1);
2822         cv.visitInsn(ICONST_1);
2823         cv.visitInsn(IADD);
2824         cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
2825         cv.visitInsn(AALOAD);
2826         cv.visitVarInsn(ALOAD, 0);
2827         cv.visitMethodInsn(
2828                 INVOKEINTERFACE,
2829                 AROUND_ADVICE_CLASS_NAME,
2830                 INTERCEPT_INVOKE_METHOD_NAME,
2831                 AROUND_ADVICE_INVOKE_METHOD_SIGNATURE
2832         );
2833         cv.visitInsn(ARETURN);
2834         cv.visitLabel(ifStatementLabel);
2835     }
2836 
2837     /***
2838      * Creates invocations fo the before interceptors.
2839      *
2840      * @param cv
2841      * @param joinPointInstanceIndex
2842      * @param registerDepth
2843      */
2844     private void createBeforeInterceptorInvocations(final CodeVisitor cv,
2845                                                     final int joinPointInstanceIndex,
2846                                                     final int registerDepth) {
2847         final int loopIndex = registerDepth + 1;
2848         cv.visitInsn(ICONST_0);
2849         cv.visitVarInsn(ISTORE, loopIndex);
2850         Label loopStartLabel = new Label();
2851         cv.visitLabel(loopStartLabel);
2852         cv.visitVarInsn(ILOAD, loopIndex);
2853         cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2854         cv.visitFieldInsn(
2855                 GETFIELD,
2856                 m_joinPointClassName,
2857                 NR_OF_BEFORE_INTERCEPTORS_FIELD_NAME,
2858                 I
2859         );
2860         Label loopCheckCondLabel = new Label();
2861         cv.visitJumpInsn(IF_ICMPGE, loopCheckCondLabel);
2862         cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2863         cv.visitFieldInsn(
2864                 GETFIELD,
2865                 m_joinPointClassName,
2866                 BEFORE_INTERCEPTORS_FIELD_NAME,
2867                 BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE
2868         );
2869         cv.visitVarInsn(ILOAD, loopIndex);
2870         cv.visitInsn(AALOAD);
2871         cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2872         cv.visitMethodInsn(
2873                 INVOKEINTERFACE,
2874                 BEFORE_ADVICE_CLASS_NAME,
2875                 INTERCEPT_INVOKE_METHOD_NAME,
2876                 BEFORE_ADVICE_INVOKE_METHOD_SIGNATURE
2877         );
2878         cv.visitIincInsn(loopIndex, 1);
2879         cv.visitJumpInsn(GOTO, loopStartLabel);
2880         cv.visitLabel(loopCheckCondLabel);
2881     }
2882 
2883     /***
2884      * Creates invocations fo the after finally interceptors.
2885      *
2886      * @param cv
2887      * @param joinPointInstanceIndex
2888      * @param registerDepth
2889      */
2890     private void createAfterInterceptorInvocations(final CodeVisitor cv,
2891                                                    final int joinPointInstanceIndex,
2892                                                    final int registerDepth) {
2893         final int loopIndex = registerDepth + 1;
2894         cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2895         cv.visitFieldInsn(
2896                 GETFIELD,
2897                 m_joinPointClassName,
2898                 NR_OF_AFTER_INTERCEPTORS_FIELD_NAME,
2899                 I
2900         );
2901         cv.visitInsn(ICONST_1);
2902         cv.visitInsn(ISUB);
2903         cv.visitVarInsn(ISTORE, loopIndex);
2904         Label loopLabel1 = new Label();
2905         cv.visitLabel(loopLabel1);
2906         cv.visitVarInsn(ILOAD, loopIndex);
2907         Label loopLabel2 = new Label();
2908         cv.visitJumpInsn(IFLT, loopLabel2);
2909         cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2910         cv.visitFieldInsn(
2911                 GETFIELD,
2912                 m_joinPointClassName,
2913                 AFTER_INTERCEPTORS_FIELD_NAME,
2914                 AFTER_ADVICE_ARRAY_CLASS_SIGNATURE
2915         );
2916         cv.visitVarInsn(ILOAD, loopIndex);
2917         cv.visitInsn(AALOAD);
2918         cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2919         cv.visitMethodInsn(
2920                 INVOKEINTERFACE,
2921                 AFTER_ADVICE_CLASS_NAME,
2922                 INTERCEPT_INVOKE_METHOD_NAME,
2923                 AFTER_ADVICE_INVOKE_METHOD_SIGNATURE
2924         );
2925         cv.visitIincInsn(loopIndex, -1);
2926         cv.visitJumpInsn(GOTO, loopLabel1);
2927         cv.visitLabel(loopLabel2);
2928     }
2929 
2930     /***
2931      * Creates invocations fo the after returning interceptors.
2932      *
2933      * @param cv
2934      * @param joinPointInstanceIndex
2935      * @param returnValueInstanceIndex
2936      */
2937     private void createAfterReturningInterceptorInvocations(final CodeVisitor cv,
2938                                                             final int joinPointInstanceIndex,
2939                                                             final int returnValueInstanceIndex) {
2940         final int loopIndex = returnValueInstanceIndex + 1;
2941         cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2942         cv.visitFieldInsn(
2943                 GETFIELD,
2944                 m_joinPointClassName,
2945                 NR_OF_AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
2946                 I
2947         );
2948         cv.visitInsn(ICONST_1);
2949         cv.visitInsn(ISUB);
2950         cv.visitVarInsn(ISTORE, loopIndex);
2951         Label loopLabel1 = new Label();
2952         cv.visitLabel(loopLabel1);
2953         cv.visitVarInsn(ILOAD, loopIndex);
2954         Label loopLabel2 = new Label();
2955         cv.visitJumpInsn(IFLT, loopLabel2);
2956         cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2957         cv.visitFieldInsn(
2958                 GETFIELD,
2959                 m_joinPointClassName,
2960                 AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
2961                 AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE
2962         );
2963         cv.visitVarInsn(ILOAD, loopIndex);
2964         cv.visitInsn(AALOAD);
2965         cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2966         cv.visitVarInsn(ALOAD, returnValueInstanceIndex);
2967         cv.visitMethodInsn(
2968                 INVOKEINTERFACE,
2969                 AFTER_RETURNING_ADVICE_CLASS_NAME,
2970                 INTERCEPT_INVOKE_METHOD_NAME,
2971                 AFTER_RETURNING_ADVICE_INVOKE_METHOD_SIGNATURE
2972         );
2973         cv.visitIincInsn(loopIndex, -1);
2974         cv.visitJumpInsn(GOTO, loopLabel1);
2975         cv.visitLabel(loopLabel2);
2976     }
2977 
2978     /***
2979      * Creates invocations fo the after returning interceptors.
2980      *
2981      * @param cv
2982      * @param joinPointInstanceIndex
2983      * @param exceptionInstanceIndex
2984      */
2985     private void createAfterThrowingInterceptorInvocations(final CodeVisitor cv,
2986                                                            final int joinPointInstanceIndex,
2987                                                            final int exceptionInstanceIndex) {
2988         final int loopIndex = exceptionInstanceIndex + 1;
2989         cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2990         cv.visitFieldInsn(
2991                 GETFIELD,
2992                 m_joinPointClassName,
2993                 NR_OF_AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
2994                 I
2995         );
2996         cv.visitInsn(ICONST_1);
2997         cv.visitInsn(ISUB);
2998         cv.visitVarInsn(ISTORE, loopIndex);
2999         Label loopLabel1 = new Label();
3000         cv.visitLabel(loopLabel1);
3001         cv.visitVarInsn(ILOAD, loopIndex);
3002         Label loopLabel2 = new Label();
3003         cv.visitJumpInsn(IFLT, loopLabel2);
3004         cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
3005         cv.visitFieldInsn(
3006                 GETFIELD,
3007                 m_joinPointClassName,
3008                 AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
3009                 AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE
3010         );
3011         cv.visitVarInsn(ILOAD, loopIndex);
3012         cv.visitInsn(AALOAD);
3013         cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
3014         cv.visitVarInsn(ALOAD, exceptionInstanceIndex);
3015         cv.visitMethodInsn(
3016                 INVOKEINTERFACE,
3017                 AFTER_THROWING_ADVICE_CLASS_NAME,
3018                 INTERCEPT_INVOKE_METHOD_NAME,
3019                 AFTER_THROWING_ADVICE_INVOKE_METHOD_SIGNATURE
3020         );
3021         cv.visitIincInsn(loopIndex, -1);
3022         cv.visitJumpInsn(GOTO, loopLabel1);
3023         cv.visitLabel(loopLabel2);
3024     }
3025 
3026     /***
3027      * Checks if the join point requires a proceed() method.
3028      *
3029      * @return
3030      */
3031     protected boolean requiresProceedMethod() {
3032         return m_hasAroundAdvices || m_isThisAdvisable;
3033     }
3034 
3035     private static class CustomProceedMethodStruct {
3036         MethodInfo customProceed;
3037         int[] adviceToTargetArgs;
3038 
3039         public CustomProceedMethodStruct(MethodInfo customProceed, int[] adviceToTargetArgs) {
3040             this.customProceed = customProceed;
3041             this.adviceToTargetArgs = adviceToTargetArgs;
3042         }
3043     }
3044 }