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 /***
14 * A compiler that compiles/generates a class that represents a specific join point, a class which invokes the advices
15 * and the target join point statically.
16 *
17 * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
18 * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur </a>
19 */
20 public class ConstructorCallJoinPointCompiler extends AbstractJoinPointCompiler {
21 /***
22 * Creates a new join point compiler instance.
23 *
24 * @param model
25 */
26 ConstructorCallJoinPointCompiler(final CompilationInfo.Model model) {
27 super(model);
28 }
29
30 /***
31 * Creates join point specific fields.
32 */
33 protected void createJoinPointSpecificFields() {
34 String[] fieldNames = null;
35
36 Type[] argumentTypes = Type.getArgumentTypes(m_calleeMemberDesc);
37 fieldNames = new String[argumentTypes.length];
38 for (int i = 0; i < argumentTypes.length; i++) {
39 Type argumentType = argumentTypes[i];
40 String fieldName = ARGUMENT_FIELD + i;
41 fieldNames[i] = fieldName;
42 m_cw.visitField(ACC_PRIVATE, fieldName, argumentType.getDescriptor(), null, null);
43 }
44 m_fieldNames = fieldNames;
45
46 m_cw.visitField(
47 ACC_PRIVATE + ACC_STATIC,
48 SIGNATURE_FIELD_NAME,
49 CONSTRUCTOR_SIGNATURE_IMPL_CLASS_SIGNATURE,
50 null,
51 null
52 );
53 }
54
55 /***
56 * Creates the signature for the join point.
57 * <p/>
58 * FIXME signature field should NOT be of type Signature but of the specific type (update all refs as well)
59 *
60 * @param cv
61 */
62 protected void createSignature(final CodeVisitor cv) {
63 cv.visitFieldInsn(GETSTATIC, m_joinPointClassName, TARGET_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
64 cv.visitLdcInsn(new Integer(m_joinPointHash));
65
66 cv.visitMethodInsn(
67 INVOKESTATIC,
68 SIGNATURE_FACTORY_CLASS,
69 NEW_CONSTRUCTOR_SIGNATURE_METHOD_NAME,
70 NEW_CONSTRUCTOR_SIGNATURE_METHOD_SIGNATURE
71 );
72 cv.visitFieldInsn(
73 PUTSTATIC, m_joinPointClassName, SIGNATURE_FIELD_NAME,
74 CONSTRUCTOR_SIGNATURE_IMPL_CLASS_SIGNATURE
75 );
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 cv.visitTypeInsn(NEW, m_calleeClassName);
89 cv.visitInsn(DUP);
90 loadArgumentMemberFields(cv, argStartIndex);
91 cv.visitMethodInsn(
92 INVOKESPECIAL, m_calleeClassName, INIT_METHOD_NAME
93 m_calleeMemberDesc
94 );
95
96
97
98 cv.visitInsn(DUP);
99 loadJoinPointInstance(cv, isOptimizedJoinPoint, joinPointIndex);
100 cv.visitInsn(SWAP);
101 cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
102 }
103
104 /***
105 * Creates a call to the target join point, the parameter(s) to the join point are retrieved from the invocation
106 * local join point instance.
107 *
108 * @param cv
109 */
110 protected void createJoinPointInvocation(final CodeVisitor cv) {
111 cv.visitTypeInsn(NEW, m_calleeClassName);
112 cv.visitInsn(DUP);
113 loadArguments(cv);
114 cv.visitMethodInsn(
115 INVOKESPECIAL, m_calleeClassName, INIT_METHOD_NAME
116 m_calleeMemberDesc
117 );
118
119
120 cv.visitInsn(DUP);
121 cv.visitVarInsn(ALOAD, 0);
122 cv.visitInsn(SWAP);
123 cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
124 }
125
126 /***
127 * Returns the join points return type.
128 *
129 * @return
130 */
131 protected Type getJoinPointReturnType() {
132 return Type.getReturnType(m_calleeClassSignature);
133 }
134
135 /***
136 * Returns the join points argument type(s).
137 *
138 * @return
139 */
140 protected Type[] getJoinPointArgumentTypes() {
141 return Type.getArgumentTypes(m_calleeMemberDesc);
142 }
143
144 /***
145 * Creates the getRtti method
146 */
147 protected void createGetRttiMethod() {
148 CodeVisitor cv = m_cw.visitMethod(ACC_PUBLIC, GET_RTTI_METHOD_NAME, GET_RTTI_METHOD_SIGNATURE, null, null);
149
150
151 cv.visitTypeInsn(NEW, CONSTRUCTOR_RTTI_IMPL_CLASS_NAME);
152 cv.visitInsn(DUP);
153 cv.visitFieldInsn(
154 GETSTATIC, m_joinPointClassName, SIGNATURE_FIELD_NAME, CONSTRUCTOR_SIGNATURE_IMPL_CLASS_SIGNATURE
155 );
156 cv.visitVarInsn(ALOAD, 0);
157 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
158 cv.visitVarInsn(ALOAD, 0);
159
160 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, RETURN_VALUE_FIELD_NAME, m_calleeClassSignature);
161 cv.visitMethodInsn(
162 INVOKESPECIAL, CONSTRUCTOR_RTTI_IMPL_CLASS_NAME, INIT_METHOD_NAME,
163 CONSTRUCTOR_RTTI_IMPL_INIT_SIGNATURE
164 );
165
166
167 cv.visitInsn(DUP);
168 createArgumentArrayAt(cv, 1);
169 cv.visitVarInsn(ALOAD, 1);
170 cv.visitMethodInsn(
171 INVOKEVIRTUAL, CONSTRUCTOR_RTTI_IMPL_CLASS_NAME, SET_PARAMETER_VALUES_METHOD_NAME,
172 SET_PARAMETER_VALUES_METHOD_SIGNATURE
173 );
174
175 cv.visitInsn(ARETURN);
176 cv.visitMaxs(0, 0);
177 }
178
179 /***
180 * Creates the getSignature method.
181 */
182 protected void createGetSignatureMethod() {
183 CodeVisitor cv = m_cw.visitMethod(
184 ACC_PUBLIC,
185 GET_SIGNATURE_METHOD_NAME,
186 GET_SIGNATURE_METHOD_SIGNATURE,
187 null,
188 null
189 );
190 cv.visitFieldInsn(
191 GETSTATIC, m_joinPointClassName,
192 SIGNATURE_FIELD_NAME, CONSTRUCTOR_SIGNATURE_IMPL_CLASS_SIGNATURE
193 );
194 cv.visitInsn(ARETURN);
195 cv.visitMaxs(0, 0);
196 }
197 }