KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > codehaus > aspectwerkz > transform > inlining > compiler > MethodCallJoinPointCompiler


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 JavaDoc;
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 MethodCallJoinPointCompiler extends AbstractJoinPointCompiler {
26
27     /**
28      * Creates a new join point compiler instance.
29      *
30      * @param model
31      */

32     MethodCallJoinPointCompiler(final CompilationInfo.Model model) {
33         super(model);
34     }
35
36     /**
37      * Creates join point specific fields.
38      */

39     protected void createJoinPointSpecificFields() {
40         String JavaDoc[] fieldNames = null;
41         // create the method argument fields
42
Type[] argumentTypes = Type.getArgumentTypes(m_calleeMemberDesc);
43         fieldNames = new String JavaDoc[argumentTypes.length];
44         for (int i = 0; i < argumentTypes.length; i++) {
45             Type argumentType = argumentTypes[i];
46             String JavaDoc fieldName = ARGUMENT_FIELD + i;
47             fieldNames[i] = fieldName;
48             m_cw.visitField(ACC_PRIVATE, fieldName, argumentType.getDescriptor(), null, null);
49         }
50         m_fieldNames = fieldNames;
51
52         m_cw.visitField(
53                 ACC_PRIVATE + ACC_STATIC,
54                 SIGNATURE_FIELD_NAME,
55                 METHOD_SIGNATURE_IMPL_CLASS_SIGNATURE,
56                 null,
57                 null
58         );
59     }
60
61     /**
62      * Creates the signature for the join point.
63      * <p/>
64      * FIXME signature field should NOT be of type Signature but of the specific type (update all refs as well)
65      *
66      * @param cv
67      */

68     protected void createSignature(final CodeVisitor cv) {
69         cv.visitFieldInsn(GETSTATIC, m_joinPointClassName, TARGET_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
70         cv.visitLdcInsn(new Integer JavaDoc(m_joinPointHash));
71
72
73         cv.visitMethodInsn(
74                 INVOKESTATIC,
75                 SIGNATURE_FACTORY_CLASS,
76                 NEW_METHOD_SIGNATURE_METHOD_NAME,
77                 NEW_METHOD_SIGNATURE_METHOD_SIGNATURE
78         );
79         cv.visitFieldInsn(
80                 PUTSTATIC, m_joinPointClassName, SIGNATURE_FIELD_NAME, METHOD_SIGNATURE_IMPL_CLASS_SIGNATURE
81         );
82
83     }
84
85     /**
86      * Optimized implementation that does not retrieve the parameters from the join point instance but is passed
87      * directly to the method from the input parameters in the 'invoke' method. Can only be used if no around advice
88      * exists.
89      *
90      * @param cv
91      * @param argStartIndex index on stack of first target method arg (0 or 1, depends of static target or not)
92      */

93     protected void createInlinedJoinPointInvocation(final CodeVisitor cv, final boolean isOptimizedJoinPoint,
94                                                     final int argStartIndex, final int joinPointIndex) {
95
96         // load the target instance (arg0 else not available for static target)
97
if (!Modifier.isStatic(m_calleeMemberModifiers)) {
98             cv.visitVarInsn(ALOAD, 0);
99         }
100
101         String JavaDoc joinPointName = null; // can be prefixed
102

103         loadArgumentMemberFields(cv, argStartIndex);
104
105         // call the package protected wrapper method if target method is not public
106
if (!Modifier.isPublic(m_calleeMemberModifiers)) {
107             joinPointName = TransformationUtil.getWrapperMethodName(
108                     m_calleeMemberName,
109                     m_calleeMemberDesc,
110                     m_calleeClassName,
111                     INVOKE_WRAPPER_METHOD_PREFIX
112             );
113         } else {
114             joinPointName = m_calleeMemberName;
115         }
116         // FIXME - pbly broken if we are using a wrapper method - refactor this if / else
117
if (Modifier.isStatic(m_calleeMemberModifiers)) {
118             cv.visitMethodInsn(INVOKESTATIC, m_calleeClassName, joinPointName, m_calleeMemberDesc);
119         } else if (isInvokeInterface(m_calleeMemberModifiers)) {
120             // AW-253
121
cv.visitMethodInsn(INVOKEINTERFACE, m_calleeClassName, joinPointName, m_calleeMemberDesc);
122         } else {
123             cv.visitMethodInsn(INVOKEVIRTUAL, m_calleeClassName, joinPointName, m_calleeMemberDesc);
124         }
125     }
126
127     /**
128      * Creates a call to the target join point, the parameter(s) to the join point are retrieved from the invocation
129      * local join point instance.
130      *
131      * @param cv
132      */

133     protected void createJoinPointInvocation(final CodeVisitor cv) {
134
135         // load the target instance member field unless calleeMember is static
136
if (!Modifier.isStatic(m_calleeMemberModifiers)) {
137             cv.visitVarInsn(ALOAD, 0);
138             cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
139         }
140
141         String JavaDoc joinPointName;
142         loadArguments(cv);
143         if (!Modifier.isPublic(m_calleeMemberModifiers)) {
144             joinPointName = TransformationUtil.getWrapperMethodName(
145                     m_calleeMemberName,
146                     m_calleeMemberDesc,
147                     m_calleeClassName,
148                     INVOKE_WRAPPER_METHOD_PREFIX
149             );
150         } else {
151             joinPointName = m_calleeMemberName;
152         }
153         // FIXME - pbly broken if we are using a wrapper method - refactor this if / else
154
if (Modifier.isStatic(m_calleeMemberModifiers)) {
155             cv.visitMethodInsn(INVOKESTATIC, m_calleeClassName, joinPointName, m_calleeMemberDesc);
156         } else if (isInvokeInterface(m_calleeMemberModifiers)) {
157             // AW-253
158
cv.visitMethodInsn(INVOKEINTERFACE, m_calleeClassName, joinPointName, m_calleeMemberDesc);
159         } else {
160             cv.visitMethodInsn(INVOKEVIRTUAL, m_calleeClassName, joinPointName, m_calleeMemberDesc);
161         }
162     }
163
164     /**
165      * Returns the join points return type.
166      *
167      * @return
168      */

169     protected Type getJoinPointReturnType() {
170         return Type.getReturnType(m_calleeMemberDesc);
171     }
172
173     /**
174      * Returns the join points argument type(s).
175      *
176      * @return
177      */

178     protected Type[] getJoinPointArgumentTypes() {
179         return Type.getArgumentTypes(m_calleeMemberDesc);
180     }
181
182     /**
183      * Creates the getRtti method
184      */

185     protected void createGetRttiMethod() {
186         CodeVisitor cv = m_cw.visitMethod(ACC_PUBLIC, GET_RTTI_METHOD_NAME, GET_RTTI_METHOD_SIGNATURE, null, null);
187
188         // new MethodRttiImpl( .. )
189
cv.visitTypeInsn(NEW, METHOD_RTTI_IMPL_CLASS_NAME);
190         cv.visitInsn(DUP);
191         cv.visitFieldInsn(
192                 GETSTATIC, m_joinPointClassName, SIGNATURE_FIELD_NAME, METHOD_SIGNATURE_IMPL_CLASS_SIGNATURE
193         );
194         cv.visitVarInsn(ALOAD, 0);
195         cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
196         cv.visitVarInsn(ALOAD, 0);
197         cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
198         cv.visitMethodInsn(
199                 INVOKESPECIAL, METHOD_RTTI_IMPL_CLASS_NAME, INIT_METHOD_NAME, METHOD_RTTI_IMPL_INIT_SIGNATURE
200         );
201
202         // set the arguments
203
cv.visitInsn(DUP);
204         createArgumentArrayAt(cv, 1);
205         cv.visitVarInsn(ALOAD, 1);
206         cv.visitMethodInsn(
207                 INVOKEVIRTUAL, METHOD_RTTI_IMPL_CLASS_NAME, SET_PARAMETER_VALUES_METHOD_NAME,
208                 SET_PARAMETER_VALUES_METHOD_SIGNATURE
209         );
210
211         // set the Returned instance
212
if (m_returnType.getSort() != Type.VOID) {
213             cv.visitInsn(DUP);
214             if (AsmHelper.isPrimitive(m_returnType)) {
215                 AsmHelper.prepareWrappingOfPrimitiveType(cv, m_returnType);
216                 cv.visitVarInsn(ALOAD, 0);
217                 cv.visitFieldInsn(
218                         GETFIELD, m_joinPointClassName, RETURN_VALUE_FIELD_NAME, m_returnType.getDescriptor()
219                 );
220                 AsmHelper.wrapPrimitiveType(cv, m_returnType);
221             } else {
222                 cv.visitVarInsn(ALOAD, 0);
223                 cv.visitFieldInsn(
224                         GETFIELD, m_joinPointClassName, RETURN_VALUE_FIELD_NAME, m_returnType.getDescriptor()
225                 );
226             }
227             cv.visitMethodInsn(
228                     INVOKEVIRTUAL, METHOD_RTTI_IMPL_CLASS_NAME, SET_RETURN_VALUE_METHOD_NAME,
229                     SET_RETURN_VALUE_METHOD_SIGNATURE
230             );
231         }
232
233         cv.visitInsn(ARETURN);
234         cv.visitMaxs(0, 0);
235     }
236
237     /**
238      * Creates the getSignature method.
239      */

240     protected void createGetSignatureMethod() {
241         CodeVisitor cv = m_cw.visitMethod(
242                 ACC_PUBLIC,
243                 GET_SIGNATURE_METHOD_NAME,
244                 GET_SIGNATURE_METHOD_SIGNATURE,
245                 null,
246                 null
247         );
248
249         cv.visitFieldInsn(
250                 GETSTATIC, m_joinPointClassName,
251                 SIGNATURE_FIELD_NAME, METHOD_SIGNATURE_IMPL_CLASS_SIGNATURE
252         );
253         cv.visitInsn(ARETURN);
254         cv.visitMaxs(0, 0);
255     }
256
257     /**
258      * See AW-253
259      * For INVOKE INTERFACE, we are using a custom modifier to track it down in order to avoid to do the
260      * hierarchy resolution ourself here
261      */

262     private boolean isInvokeInterface(int modifier) {
263         return (modifier & MODIFIER_INVOKEINTERFACE) != 0;
264     }
265 }
Popular Tags