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 FieldGetJoinPointCompiler extends AbstractJoinPointCompiler {
    26
    27      /***
    28       * Creates a new join point compiler instance.
    29       *
    30       * @param model
    31       */
    32      FieldGetJoinPointCompiler(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 field argument field
    42          Type fieldType = Type.getType(m_calleeMemberDesc);
    43          fieldNames = new String[1];
    44          String fieldName = ARGUMENT_FIELD + 0;
    45          fieldNames[0] = fieldName;
    46          m_cw.visitField(ACC_PRIVATE, fieldName, fieldType.getDescriptor(), null, null);
    47          m_fieldNames = fieldNames;
    48
    49          m_cw.visitField(
    50                  ACC_PRIVATE + ACC_STATIC,
    51                  SIGNATURE_FIELD_NAME,
    52                  FIELD_SIGNATURE_IMPL_CLASS_SIGNATURE,
    53                  null,
    54                  null
    55          );
    56      }
    57
    58      /***
    59       * Creates the signature for the join point.
    60       * <p/>
    61       * FIXME signature field should NOT be of type Signature but of the specific type (update all refs as well)
    62       *
    63       * @param cv
    64       */
    65      protected void createSignature(final CodeVisitor cv) {
    66          cv.visitFieldInsn(GETSTATIC, m_joinPointClassName, TARGET_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
    67          cv.visitLdcInsn(new Integer(m_joinPointHash));
    68
    69          cv.visitMethodInsn(
    70                  INVOKESTATIC,
    71                  SIGNATURE_FACTORY_CLASS,
    72                  NEW_FIELD_SIGNATURE_METHOD_NAME,
    73                  NEW_FIELD_SIGNATURE_METHOD_SIGNATURE
    74          );
    75          cv.visitFieldInsn(PUTSTATIC, m_joinPointClassName, SIGNATURE_FIELD_NAME, FIELD_SIGNATURE_IMPL_CLASS_SIGNATURE);
    76      }
    77
    78      /***
    79       * Optimized implementation that does not retrieve the parameters from the join point instance but is passed
    80       * directly to the method from the input parameters in the 'invoke' method. Can only be used if no around advice
    81       * exists.
    82       *
    83       * @param cv
    84       * @param argStartIndex index on stack of first target method arg (0 or 1, depends of static target or not)
    85       */
    86      protected void createInlinedJoinPointInvocation(final CodeVisitor cv, final boolean isOptimizedJoinPoint,
    87                                                      final int argStartIndex, final int joinPointIndex) {
    88
    89          // load the target instance (arg0 else not available for static target)
    90          if (!Modifier.isStatic(m_calleeMemberModifiers)) {
    91              cv.visitVarInsn(ALOAD, 0);
    92          }
    93
    94          // do we have a public field ? If so don't use the wrappers
    95          if (Modifier.isPublic(m_calleeMemberModifiers)) {
    96              if (Modifier.isStatic(m_calleeMemberModifiers)) {
    97                  cv.visitFieldInsn(GETSTATIC, m_calleeClassName, m_calleeMemberName, m_calleeMemberDesc);
    98              } else {
    99                  cv.visitFieldInsn(GETFIELD, m_calleeClassName, m_calleeMemberName, m_calleeMemberDesc);
    100             }
    101         } else {
    102             // use the wrapper
    103             String joinPointName = TransformationUtil.getWrapperMethodName(
    104                     m_calleeMemberName,
    105                     m_calleeMemberDesc,
    106                     m_calleeClassName,
    107                     GETFIELD_WRAPPER_METHOD_PREFIX
    108             );
    109             StringBuffer getFieldWrapperDesc = new StringBuffer();
    110             getFieldWrapperDesc.append('(');
    111             getFieldWrapperDesc.append(')');
    112             getFieldWrapperDesc.append(m_calleeMemberDesc);
    113             if (Modifier.isStatic(m_calleeMemberModifiers)) {
    114                 cv.visitMethodInsn(INVOKESTATIC, m_calleeClassName, joinPointName, getFieldWrapperDesc.toString());
    115             } else {
    116                 cv.visitMethodInsn(INVOKEVIRTUAL, m_calleeClassName, joinPointName, getFieldWrapperDesc.toString());
    117             }
    118         }
    119     }
    120
    121     /***
    122      * Creates a call to the target join point, the parameter(s) to the join point are retrieved from the invocation
    123      * local join point instance.
    124      *
    125      * @param cv
    126      */
    127     protected void createJoinPointInvocation(final CodeVisitor cv) {
    128
    129         // load the target instance member field unless calleeMember is static
    130         if (!Modifier.isStatic(m_calleeMemberModifiers)) {
    131             cv.visitVarInsn(ALOAD, 0);
    132             cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
    133         }
    134
    135         // do we have a public field ? If so don't use the wrappers
    136         if (Modifier.isPublic(m_calleeMemberModifiers)) {
    137             if (Modifier.isStatic(m_calleeMemberModifiers)) {
    138                 cv.visitFieldInsn(GETSTATIC, m_calleeClassName, m_calleeMemberName, m_calleeMemberDesc);
    139             } else {
    140                 cv.visitFieldInsn(GETFIELD, m_calleeClassName, m_calleeMemberName, m_calleeMemberDesc);
    141             }
    142         } else {
    143             String joinPointName = TransformationUtil.getWrapperMethodName(
    144                     m_calleeMemberName,
    145                     m_calleeMemberDesc,
    146                     m_calleeClassName,
    147                     GETFIELD_WRAPPER_METHOD_PREFIX
    148             );
    149             StringBuffer getFieldWrapperDesc = new StringBuffer();
    150             getFieldWrapperDesc.append('(');
    151             getFieldWrapperDesc.append(')');
    152             getFieldWrapperDesc.append(m_calleeMemberDesc);
    153             if (Modifier.isStatic(m_calleeMemberModifiers)) {
    154                 cv.visitMethodInsn(INVOKESTATIC, m_calleeClassName, joinPointName, getFieldWrapperDesc.toString());
    155             } else {
    156                 cv.visitMethodInsn(INVOKEVIRTUAL, m_calleeClassName, joinPointName, getFieldWrapperDesc.toString());
    157             }
    158         }
    159     }
    160
    161     /***
    162      * Returns the join points return type.
    163      *
    164      * @return
    165      */
    166     protected Type getJoinPointReturnType() {
    167         return Type.getType(m_calleeMemberDesc);
    168     }
    169
    170     /***
    171      * Returns the join points argument type(s).
    172      *
    173      * @return
    174      */
    175     protected Type[] getJoinPointArgumentTypes() {
    176         return new Type[]{Type.getType(m_calleeMemberDesc)};
    177     }
    178
    179     /***
    180      * Creates the getRtti method
    181      */
    182     protected void createGetRttiMethod() {
    183         CodeVisitor cv = m_cw.visitMethod(ACC_PUBLIC, GET_RTTI_METHOD_NAME, GET_RTTI_METHOD_SIGNATURE, null, null);
    184
    185         // new FieldRttiImpl( .. )
    186         cv.visitTypeInsn(NEW, FIELD_RTTI_IMPL_CLASS_NAME);
    187         cv.visitInsn(DUP);
    188         cv.visitFieldInsn(GETSTATIC, m_joinPointClassName, SIGNATURE_FIELD_NAME, FIELD_SIGNATURE_IMPL_CLASS_SIGNATURE);
    189         cv.visitVarInsn(ALOAD, 0);
    190         cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
    191         cv.visitVarInsn(ALOAD, 0);
    192         cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
    193         cv.visitMethodInsn(
    194                 INVOKESPECIAL, FIELD_RTTI_IMPL_CLASS_NAME, INIT_METHOD_NAME, FIELD_RTTI_IMPL_INIT_SIGNATURE
    195         );
    196
    197         // set the value
    198         cv.visitInsn(DUP);
    199         if (AsmHelper.isPrimitive(m_returnType)) {
    200             AsmHelper.prepareWrappingOfPrimitiveType(cv, m_returnType);
    201             cv.visitVarInsn(ALOAD, 0);
    202             cv.visitFieldInsn(GETFIELD, m_joinPointClassName, RETURN_VALUE_FIELD_NAME, m_returnType.getDescriptor());
    203             AsmHelper.wrapPrimitiveType(cv, m_returnType);
    204         } else {
    205             cv.visitVarInsn(ALOAD, 0);
    206             cv.visitFieldInsn(GETFIELD, m_joinPointClassName, RETURN_VALUE_FIELD_NAME, m_returnType.getDescriptor());
    207         }
    208         cv.visitMethodInsn(
    209                 INVOKEVIRTUAL,
    210                 FIELD_RTTI_IMPL_CLASS_NAME,
    211                 SET_FIELD_VALUE_METHOD_NAME,
    212                 SET_FIELD_VALUE_METHOD_SIGNATURE
    213         );
    214
    215         cv.visitInsn(ARETURN);
    216         cv.visitMaxs(0, 0);
    217     }
    218
    219     /***
    220      * Creates the getSignature method.
    221      */
    222     protected void createGetSignatureMethod() {
    223         CodeVisitor cv = m_cw.visitMethod(
    224                 ACC_PUBLIC,
    225                 GET_SIGNATURE_METHOD_NAME,
    226                 GET_SIGNATURE_METHOD_SIGNATURE,
    227                 null,
    228                 null
    229         );
    230         cv.visitFieldInsn(
    231                 GETSTATIC, m_joinPointClassName,
    232                 SIGNATURE_FIELD_NAME, FIELD_SIGNATURE_IMPL_CLASS_SIGNATURE
    233         );
    234         cv.visitInsn(ARETURN);
    235         cv.visitMaxs(0, 0);
    236     }
    237 }