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.CodeVisitor;
    11  import org.objectweb.asm.Type;
    12
    13  import org.codehaus.aspectwerkz.transform.TransformationUtil;
    14  import org.codehaus.aspectwerkz.transform.inlining.AsmHelper;
    15
    16  import java.lang.reflect.Modifier;
    17
    18  /***
    19   * A compiler that compiles/generates a class that represents a specific join point, a class which invokes the advices
    20   * and the target join point statically.
    21   *
    22   * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
    23   * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur </a>
    24   */
    25  public class MethodExecutionJoinPointCompiler extends AbstractJoinPointCompiler {
    26
    27      /***
    28       * Creates a new join point compiler instance.
    29       *
    30       * @param model
    31       */
    32      MethodExecutionJoinPointCompiler(final CompilationInfo.Model model) {
    33          super(model);
    34      }
    35
    36      /***
    37       * Creates join point specific fields.
    38       */
    39      protected void createJoinPointSpecificFields() {
    40          String[] fieldNames = null;
    41          // create the method argument fields
    42          Type[] argumentTypes = Type.getArgumentTypes(m_calleeMemberDesc);
    43          fieldNames = new String[argumentTypes.length];
    44          for (int i = 0; i < argumentTypes.length; i++) {
    45              Type argumentType = argumentTypes[i];
    46              String fieldName = ARGUMENT_FIELD + i;
    47              fieldNames[i] = fieldName;
    48              m_cw.visitField(ACC_PRIVATE, fieldName, argumentType.getDescriptor(), null, null);
    49          }
    50
    51          m_fieldNames = fieldNames;
    52
    53          m_cw.visitField(
    54                  ACC_PRIVATE + ACC_STATIC,
    55                  SIGNATURE_FIELD_NAME,
    56                  METHOD_SIGNATURE_IMPL_CLASS_SIGNATURE,
    57                  null,
    58                  null
    59          );
    60      }
    61
    62      /***
    63       * Creates the signature for the join point.
    64       * <p/>
    65       * FIXME signature field should NOT be of type Signature but of the specific type (update all refs as well)
    66       *
    67       * @param cv
    68       */
    69      protected void createSignature(final CodeVisitor cv) {
    70          cv.visitFieldInsn(GETSTATIC, m_joinPointClassName, TARGET_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
    71          cv.visitLdcInsn(new Integer(m_joinPointHash));
    72
    73          cv.visitMethodInsn(
    74                  INVOKESTATIC,
    75                  SIGNATURE_FACTORY_CLASS,
    76                  NEW_METHOD_SIGNATURE_METHOD_NAME,
    77                  NEW_METHOD_SIGNATURE_METHOD_SIGNATURE
    78          );
    79          cv.visitFieldInsn(
    80                  PUTSTATIC, m_joinPointClassName, SIGNATURE_FIELD_NAME, METHOD_SIGNATURE_IMPL_CLASS_SIGNATURE
    81          );
    82
    83      }
    84
    85      /***
    86       * Optimized implementation that does not retrieve the parameters from the join point instance but is passed
    87       * directly to the method from the input parameters in the 'invoke' method. Can only be used if no around advice
    88       * exists.
    89       *
    90       * @param cv
    91       * @param argStartIndex index on stack of first target method arg (0 or 1, depends of static target or not)
    92       */
    93      protected void createInlinedJoinPointInvocation(final CodeVisitor cv, final boolean isOptimizedJoinPoint,
    94                                                      final int argStartIndex, final int joinPointIndex) {
    95
    96          // load the target instance (arg0 else not available for static target)
    97          if (!Modifier.isStatic(m_calleeMemberModifiers)) {
    98              cv.visitVarInsn(ALOAD, 0);
    99          }
    100
    101         String joinPointName = null; // can be prefixed
    102
    103         loadArgumentMemberFields(cv, argStartIndex);
    104         joinPointName = TransformationUtil.getPrefixedOriginalMethodName(
    105                 m_calleeMemberName,
    106                 m_calleeClassName
    107         );
    108         if (Modifier.isStatic(m_calleeMemberModifiers)) {
    109             cv.visitMethodInsn(INVOKESTATIC, m_calleeClassName, joinPointName, m_calleeMemberDesc);
    110         } else {
    111             cv.visitMethodInsn(INVOKEVIRTUAL, m_calleeClassName, joinPointName, m_calleeMemberDesc);
    112         }
    113
    114     }
    115
    116     /***
    117      * Creates a call to the target join point, the parameter(s) to the join point are retrieved from the invocation
    118      * local join point instance.
    119      *
    120      * @param cv
    121      */
    122     protected void createJoinPointInvocation(final CodeVisitor cv) {
    123
    124         // load the target instance member field unless calleeMember is static
    125         if (!Modifier.isStatic(m_calleeMemberModifiers)) {
    126             cv.visitVarInsn(ALOAD, 0);
    127             cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
    128         }
    129
    130         String joinPointName;
    131         loadArguments(cv);
    132         joinPointName = TransformationUtil.getPrefixedOriginalMethodName(
    133                 m_calleeMemberName,
    134                 m_calleeClassName
    135         );
    136         if (Modifier.isStatic(m_calleeMemberModifiers)) {
    137             cv.visitMethodInsn(INVOKESTATIC, m_calleeClassName, joinPointName, m_calleeMemberDesc);
    138         } else {
    139             cv.visitMethodInsn(INVOKEVIRTUAL, m_calleeClassName, joinPointName, m_calleeMemberDesc);
    140         }
    141     }
    142
    143     /***
    144      * Returns the join points return type.
    145      *
    146      * @return
    147      */
    148     protected Type getJoinPointReturnType() {
    149         return Type.getReturnType(m_calleeMemberDesc);
    150     }
    151
    152     /***
    153      * Returns the join points argument type(s).
    154      *
    155      * @return
    156      */
    157     protected Type[] getJoinPointArgumentTypes() {
    158         return Type.getArgumentTypes(m_calleeMemberDesc);
    159     }
    160
    161     /***
    162      * Creates the getRtti method
    163      */
    164     protected void createGetRttiMethod() {
    165         CodeVisitor cv = m_cw.visitMethod(ACC_PUBLIC, GET_RTTI_METHOD_NAME, GET_RTTI_METHOD_SIGNATURE, null, null);
    166
    167         // new MethodRttiImpl( .. )
    168         cv.visitTypeInsn(NEW, METHOD_RTTI_IMPL_CLASS_NAME);
    169         cv.visitInsn(DUP);
    170         cv.visitFieldInsn(
    171                 GETSTATIC, m_joinPointClassName, SIGNATURE_FIELD_NAME, METHOD_SIGNATURE_IMPL_CLASS_SIGNATURE
    172         );
    173         cv.visitVarInsn(ALOAD, 0);
    174         cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
    175         cv.visitVarInsn(ALOAD, 0);
    176         cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
    177         cv.visitMethodInsn(
    178                 INVOKESPECIAL, METHOD_RTTI_IMPL_CLASS_NAME, INIT_METHOD_NAME, METHOD_RTTI_IMPL_INIT_SIGNATURE
    179         );
    180
    181         // set the arguments
    182         cv.visitInsn(DUP);
    183         createArgumentArrayAt(cv, 1);
    184         cv.visitVarInsn(ALOAD, 1);
    185         cv.visitMethodInsn(
    186                 INVOKEVIRTUAL, METHOD_RTTI_IMPL_CLASS_NAME, SET_PARAMETER_VALUES_METHOD_NAME,
    187                 SET_PARAMETER_VALUES_METHOD_SIGNATURE
    188         );
    189
    190         // set the Returned instance
    191         if (m_returnType.getSort() != Type.VOID) {
    192             cv.visitInsn(DUP);
    193             if (AsmHelper.isPrimitive(m_returnType)) {
    194                 AsmHelper.prepareWrappingOfPrimitiveType(cv, m_returnType);
    195                 cv.visitVarInsn(ALOAD, 0);
    196                 cv.visitFieldInsn(
    197                         GETFIELD, m_joinPointClassName, RETURN_VALUE_FIELD_NAME, m_returnType.getDescriptor()
    198                 );
    199                 AsmHelper.wrapPrimitiveType(cv, m_returnType);
    200             } else {
    201                 cv.visitVarInsn(ALOAD, 0);
    202                 cv.visitFieldInsn(
    203                         GETFIELD, m_joinPointClassName, RETURN_VALUE_FIELD_NAME, m_returnType.getDescriptor()
    204                 );
    205             }
    206             cv.visitMethodInsn(
    207                     INVOKEVIRTUAL, METHOD_RTTI_IMPL_CLASS_NAME, SET_RETURN_VALUE_METHOD_NAME,
    208                     SET_RETURN_VALUE_METHOD_SIGNATURE
    209             );
    210         }
    211
    212         cv.visitInsn(ARETURN);
    213         cv.visitMaxs(0, 0);
    214     }
    215
    216     /***
    217      * Creates the getSignature method.
    218      */
    219     protected void createGetSignatureMethod() {
    220         CodeVisitor cv = m_cw.visitMethod(
    221                 ACC_PUBLIC,
    222                 GET_SIGNATURE_METHOD_NAME,
    223                 GET_SIGNATURE_METHOD_SIGNATURE,
    224                 null,
    225                 null
    226         );
    227
    228         cv.visitFieldInsn(
    229                 GETSTATIC, m_joinPointClassName,
    230                 SIGNATURE_FIELD_NAME, METHOD_SIGNATURE_IMPL_CLASS_SIGNATURE
    231         );
    232         cv.visitInsn(ARETURN);
    233         cv.visitMaxs(0, 0);
    234     }
    235 }