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 }