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