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 }