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.compiler.AbstractJoinPointCompiler;
15 import org.codehaus.aspectwerkz.transform.inlining.AsmHelper;
16
17 import java.lang.reflect.Modifier;
18
19 /***
20 * A compiler that compiles/generates a class that represents a specific join point, a class which invokes the advices
21 * and the target join point statically.
22 *
23 * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
24 * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur </a>
25 */
26 public class FieldSetJoinPointCompiler extends AbstractJoinPointCompiler {
27
28 /***
29 * Creates a new join point compiler instance.
30 *
31 * @param model
32 */
33 FieldSetJoinPointCompiler(final CompilationInfo.Model model) {
34 super(model);
35 }
36
37 /***
38 * Creates join point specific fields.
39 */
40 protected void createJoinPointSpecificFields() {
41 String[] fieldNames = null;
42
43 Type fieldType = Type.getType(m_calleeMemberDesc);
44 fieldNames = new String[1];
45 String fieldName = ARGUMENT_FIELD + 0;
46 fieldNames[0] = fieldName;
47 m_cw.visitField(ACC_PRIVATE, fieldName, fieldType.getDescriptor(), null, null);
48 m_fieldNames = fieldNames;
49
50 m_cw.visitField(
51 ACC_PRIVATE + ACC_STATIC,
52 SIGNATURE_FIELD_NAME,
53 FIELD_SIGNATURE_IMPL_CLASS_SIGNATURE,
54 null,
55 null
56 );
57 }
58
59 /***
60 * Creates the signature for the join point.
61 * <p/>
62 * FIXME signature field should NOT be of type Signature but of the specific type (update all refs as well)
63 *
64 * @param cv
65 */
66 protected void createSignature(final CodeVisitor cv) {
67 cv.visitFieldInsn(GETSTATIC, m_joinPointClassName, TARGET_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
68 cv.visitLdcInsn(new Integer(m_joinPointHash));
69
70 cv.visitMethodInsn(
71 INVOKESTATIC,
72 SIGNATURE_FACTORY_CLASS,
73 NEW_FIELD_SIGNATURE_METHOD_NAME,
74 NEW_FIELD_SIGNATURE_METHOD_SIGNATURE
75 );
76 cv.visitFieldInsn(PUTSTATIC, m_joinPointClassName, SIGNATURE_FIELD_NAME, FIELD_SIGNATURE_IMPL_CLASS_SIGNATURE);
77 }
78
79 /***
80 * Optimized implementation that does not retrieve the parameters from the join point instance but is passed
81 * directly to the method from the input parameters in the 'invoke' method. Can only be used if no around advice
82 * exists.
83 *
84 * @param cv
85 * @param argStartIndex index on stack of first target method arg (0 or 1, depends of static target or not)
86 */
87 protected void createInlinedJoinPointInvocation(final CodeVisitor cv, final boolean isOptimizedJoinPoint,
88 final int argStartIndex, final int joinPointIndex) {
89
90
91 if (!Modifier.isStatic(m_calleeMemberModifiers)) {
92 cv.visitVarInsn(ALOAD, 0);
93 }
94
95 loadArgumentMemberFields(cv, argStartIndex);
96
97
98 if (Modifier.isPublic(m_calleeMemberModifiers)) {
99 if (Modifier.isStatic(m_calleeMemberModifiers)) {
100 cv.visitFieldInsn(PUTSTATIC, m_calleeClassName, m_calleeMemberName, m_calleeMemberDesc);
101 } else {
102 cv.visitFieldInsn(PUTFIELD, m_calleeClassName, m_calleeMemberName, m_calleeMemberDesc);
103 }
104 } else {
105 String joinPointName = null;
106 joinPointName = m_calleeMemberName;
107 joinPointName = TransformationUtil.getWrapperMethodName(
108 joinPointName,
109 m_calleeMemberDesc,
110 m_calleeClassName,
111 PUTFIELD_WRAPPER_METHOD_PREFIX
112 );
113 StringBuffer sig = new StringBuffer();
114 sig.append('(');
115 sig.append(m_calleeMemberDesc);
116 sig.append(')');
117 sig.append('V');
118 if (Modifier.isStatic(m_calleeMemberModifiers)) {
119 cv.visitMethodInsn(INVOKESTATIC, m_calleeClassName, joinPointName, sig.toString());
120 } else {
121 cv.visitMethodInsn(INVOKEVIRTUAL, m_calleeClassName, joinPointName, sig.toString());
122 }
123 }
124
125 AsmHelper.addDefaultValue(cv, m_argumentTypes[0]);
126 }
127
128 /***
129 * Creates a call to the target join point, the parameter(s) to the join point are retrieved from the invocation
130 * local join point instance.
131 *
132 * @param cv
133 */
134 protected void createJoinPointInvocation(final CodeVisitor cv) {
135
136
137 if (!Modifier.isStatic(m_calleeMemberModifiers)) {
138 cv.visitVarInsn(ALOAD, 0);
139 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
140 }
141
142 loadArguments(cv);
143
144
145 if (Modifier.isPublic(m_calleeMemberModifiers)) {
146 if (Modifier.isStatic(m_calleeMemberModifiers)) {
147 cv.visitFieldInsn(PUTSTATIC, m_calleeClassName, m_calleeMemberName, m_calleeMemberDesc);
148 } else {
149 cv.visitFieldInsn(PUTFIELD, m_calleeClassName, m_calleeMemberName, m_calleeMemberDesc);
150 }
151 } else {
152 String joinPointName = TransformationUtil.getWrapperMethodName(
153 m_calleeMemberName,
154 m_calleeMemberDesc,
155 m_calleeClassName,
156 PUTFIELD_WRAPPER_METHOD_PREFIX
157 );
158 StringBuffer putFieldWrapperDesc = new StringBuffer();
159 putFieldWrapperDesc.append('(');
160 putFieldWrapperDesc.append(m_calleeMemberDesc);
161 putFieldWrapperDesc.append(')');
162 putFieldWrapperDesc.append('V');
163 if (Modifier.isStatic(m_calleeMemberModifiers)) {
164 cv.visitMethodInsn(INVOKESTATIC, m_calleeClassName, joinPointName, putFieldWrapperDesc.toString());
165 } else {
166 cv.visitMethodInsn(INVOKEVIRTUAL, m_calleeClassName, joinPointName, putFieldWrapperDesc.toString());
167 }
168 }
169
170 AsmHelper.addDefaultValue(cv, m_argumentTypes[0]);
171 }
172
173 /***
174 * Returns the join points return type.
175 *
176 * @return
177 */
178 protected Type getJoinPointReturnType() {
179 return Type.getType(m_calleeMemberDesc);
180 }
181
182 /***
183 * Returns the join points argument type(s).
184 *
185 * @return
186 */
187 protected Type[] getJoinPointArgumentTypes() {
188 return new Type[]{Type.getType(m_calleeMemberDesc)};
189 }
190
191 /***
192 * Creates the getRtti method
193 */
194 protected void createGetRttiMethod() {
195 CodeVisitor cv = m_cw.visitMethod(ACC_PUBLIC, GET_RTTI_METHOD_NAME, GET_RTTI_METHOD_SIGNATURE, null, null);
196
197
198 cv.visitTypeInsn(NEW, FIELD_RTTI_IMPL_CLASS_NAME);
199 cv.visitInsn(DUP);
200 cv.visitFieldInsn(GETSTATIC, m_joinPointClassName, SIGNATURE_FIELD_NAME, FIELD_SIGNATURE_IMPL_CLASS_SIGNATURE);
201 cv.visitVarInsn(ALOAD, 0);
202 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
203 cv.visitVarInsn(ALOAD, 0);
204 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
205 cv.visitMethodInsn(
206 INVOKESPECIAL, FIELD_RTTI_IMPL_CLASS_NAME, INIT_METHOD_NAME, FIELD_RTTI_IMPL_INIT_SIGNATURE
207 );
208
209
210 cv.visitInsn(DUP);
211 if (AsmHelper.isPrimitive(m_returnType)) {
212 AsmHelper.prepareWrappingOfPrimitiveType(cv, m_returnType);
213 cv.visitVarInsn(ALOAD, 0);
214 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, RETURN_VALUE_FIELD_NAME, m_returnType.getDescriptor());
215 AsmHelper.wrapPrimitiveType(cv, m_returnType);
216 } else {
217 cv.visitVarInsn(ALOAD, 0);
218 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, RETURN_VALUE_FIELD_NAME, m_returnType.getDescriptor());
219 }
220 cv.visitMethodInsn(
221 INVOKEVIRTUAL,
222 FIELD_RTTI_IMPL_CLASS_NAME,
223 SET_FIELD_VALUE_METHOD_NAME,
224 SET_FIELD_VALUE_METHOD_SIGNATURE
225 );
226
227 cv.visitInsn(ARETURN);
228 cv.visitMaxs(0, 0);
229 }
230
231 /***
232 * Creates the getSignature method.
233 */
234 protected void createGetSignatureMethod() {
235 CodeVisitor cv = m_cw.visitMethod(
236 ACC_PUBLIC,
237 GET_SIGNATURE_METHOD_NAME,
238 GET_SIGNATURE_METHOD_SIGNATURE,
239 null,
240 null
241 );
242 cv.visitFieldInsn(
243 GETSTATIC, m_joinPointClassName,
244 SIGNATURE_FIELD_NAME, FIELD_SIGNATURE_IMPL_CLASS_SIGNATURE
245 );
246 cv.visitInsn(ARETURN);
247 cv.visitMaxs(0, 0);
248 }
249 }