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
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
90 if (!Modifier.isStatic(m_calleeMemberModifiers)) {
91 cv.visitVarInsn(ALOAD, 0);
92 }
93
94
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
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
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
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
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
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 }