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 MethodExecutionJoinPointCompiler extends AbstractJoinPointCompiler {
26
27 /***
28 * Creates a new join point compiler instance.
29 *
30 * @param model
31 */
32 MethodExecutionJoinPointCompiler(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
42 Type[] argumentTypes = Type.getArgumentTypes(m_calleeMemberDesc);
43 fieldNames = new String[argumentTypes.length];
44 for (int i = 0; i < argumentTypes.length; i++) {
45 Type argumentType = argumentTypes[i];
46 String fieldName = ARGUMENT_FIELD + i;
47 fieldNames[i] = fieldName;
48 m_cw.visitField(ACC_PRIVATE, fieldName, argumentType.getDescriptor(), null, null);
49 }
50
51 m_fieldNames = fieldNames;
52
53 m_cw.visitField(
54 ACC_PRIVATE + ACC_STATIC,
55 SIGNATURE_FIELD_NAME,
56 METHOD_SIGNATURE_IMPL_CLASS_SIGNATURE,
57 null,
58 null
59 );
60 }
61
62 /***
63 * Creates the signature for the join point.
64 * <p/>
65 * FIXME signature field should NOT be of type Signature but of the specific type (update all refs as well)
66 *
67 * @param cv
68 */
69 protected void createSignature(final CodeVisitor cv) {
70 cv.visitFieldInsn(GETSTATIC, m_joinPointClassName, TARGET_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
71 cv.visitLdcInsn(new Integer(m_joinPointHash));
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
97 if (!Modifier.isStatic(m_calleeMemberModifiers)) {
98 cv.visitVarInsn(ALOAD, 0);
99 }
100
101 String joinPointName = null;
102
103 loadArgumentMemberFields(cv, argStartIndex);
104 joinPointName = TransformationUtil.getPrefixedOriginalMethodName(
105 m_calleeMemberName,
106 m_calleeClassName
107 );
108 if (Modifier.isStatic(m_calleeMemberModifiers)) {
109 cv.visitMethodInsn(INVOKESTATIC, m_calleeClassName, joinPointName, m_calleeMemberDesc);
110 } else {
111 cv.visitMethodInsn(INVOKEVIRTUAL, m_calleeClassName, joinPointName, m_calleeMemberDesc);
112 }
113
114 }
115
116 /***
117 * Creates a call to the target join point, the parameter(s) to the join point are retrieved from the invocation
118 * local join point instance.
119 *
120 * @param cv
121 */
122 protected void createJoinPointInvocation(final CodeVisitor cv) {
123
124
125 if (!Modifier.isStatic(m_calleeMemberModifiers)) {
126 cv.visitVarInsn(ALOAD, 0);
127 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
128 }
129
130 String joinPointName;
131 loadArguments(cv);
132 joinPointName = TransformationUtil.getPrefixedOriginalMethodName(
133 m_calleeMemberName,
134 m_calleeClassName
135 );
136 if (Modifier.isStatic(m_calleeMemberModifiers)) {
137 cv.visitMethodInsn(INVOKESTATIC, m_calleeClassName, joinPointName, m_calleeMemberDesc);
138 } else {
139 cv.visitMethodInsn(INVOKEVIRTUAL, m_calleeClassName, joinPointName, m_calleeMemberDesc);
140 }
141 }
142
143 /***
144 * Returns the join points return type.
145 *
146 * @return
147 */
148 protected Type getJoinPointReturnType() {
149 return Type.getReturnType(m_calleeMemberDesc);
150 }
151
152 /***
153 * Returns the join points argument type(s).
154 *
155 * @return
156 */
157 protected Type[] getJoinPointArgumentTypes() {
158 return Type.getArgumentTypes(m_calleeMemberDesc);
159 }
160
161 /***
162 * Creates the getRtti method
163 */
164 protected void createGetRttiMethod() {
165 CodeVisitor cv = m_cw.visitMethod(ACC_PUBLIC, GET_RTTI_METHOD_NAME, GET_RTTI_METHOD_SIGNATURE, null, null);
166
167
168 cv.visitTypeInsn(NEW, METHOD_RTTI_IMPL_CLASS_NAME);
169 cv.visitInsn(DUP);
170 cv.visitFieldInsn(
171 GETSTATIC, m_joinPointClassName, SIGNATURE_FIELD_NAME, METHOD_SIGNATURE_IMPL_CLASS_SIGNATURE
172 );
173 cv.visitVarInsn(ALOAD, 0);
174 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
175 cv.visitVarInsn(ALOAD, 0);
176 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
177 cv.visitMethodInsn(
178 INVOKESPECIAL, METHOD_RTTI_IMPL_CLASS_NAME, INIT_METHOD_NAME, METHOD_RTTI_IMPL_INIT_SIGNATURE
179 );
180
181
182 cv.visitInsn(DUP);
183 createArgumentArrayAt(cv, 1);
184 cv.visitVarInsn(ALOAD, 1);
185 cv.visitMethodInsn(
186 INVOKEVIRTUAL, METHOD_RTTI_IMPL_CLASS_NAME, SET_PARAMETER_VALUES_METHOD_NAME,
187 SET_PARAMETER_VALUES_METHOD_SIGNATURE
188 );
189
190
191 if (m_returnType.getSort() != Type.VOID) {
192 cv.visitInsn(DUP);
193 if (AsmHelper.isPrimitive(m_returnType)) {
194 AsmHelper.prepareWrappingOfPrimitiveType(cv, m_returnType);
195 cv.visitVarInsn(ALOAD, 0);
196 cv.visitFieldInsn(
197 GETFIELD, m_joinPointClassName, RETURN_VALUE_FIELD_NAME, m_returnType.getDescriptor()
198 );
199 AsmHelper.wrapPrimitiveType(cv, m_returnType);
200 } else {
201 cv.visitVarInsn(ALOAD, 0);
202 cv.visitFieldInsn(
203 GETFIELD, m_joinPointClassName, RETURN_VALUE_FIELD_NAME, m_returnType.getDescriptor()
204 );
205 }
206 cv.visitMethodInsn(
207 INVOKEVIRTUAL, METHOD_RTTI_IMPL_CLASS_NAME, SET_RETURN_VALUE_METHOD_NAME,
208 SET_RETURN_VALUE_METHOD_SIGNATURE
209 );
210 }
211
212 cv.visitInsn(ARETURN);
213 cv.visitMaxs(0, 0);
214 }
215
216 /***
217 * Creates the getSignature method.
218 */
219 protected void createGetSignatureMethod() {
220 CodeVisitor cv = m_cw.visitMethod(
221 ACC_PUBLIC,
222 GET_SIGNATURE_METHOD_NAME,
223 GET_SIGNATURE_METHOD_SIGNATURE,
224 null,
225 null
226 );
227
228 cv.visitFieldInsn(
229 GETSTATIC, m_joinPointClassName,
230 SIGNATURE_FIELD_NAME, METHOD_SIGNATURE_IMPL_CLASS_SIGNATURE
231 );
232 cv.visitInsn(ARETURN);
233 cv.visitMaxs(0, 0);
234 }
235 }