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