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