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 }