001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
003: */
004: package com.tc.aspectwerkz.transform.inlining.compiler;
005:
006: import com.tc.asm.MethodVisitor;
007: import com.tc.asm.Type;
008:
009: import com.tc.aspectwerkz.transform.TransformationUtil;
010:
011: import java.lang.reflect.Modifier;
012:
013: /**
014: * A compiler that compiles/generates a class that represents a specific join point, a class which invokes the advices
015: * and the target join point statically.
016: *
017: * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
018: * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur </a>
019: */
020: public class ConstructorCallJoinPointCompiler extends
021: AbstractJoinPointCompiler {
022: /**
023: * Creates a new join point compiler instance.
024: *
025: * @param model
026: */
027: ConstructorCallJoinPointCompiler(final CompilationInfo.Model model) {
028: super (model);
029: }
030:
031: /**
032: * Creates join point specific fields.
033: */
034: protected void createJoinPointSpecificFields() {
035: String[] fieldNames = null;
036: // create the method argument fields
037: Type[] argumentTypes = Type
038: .getArgumentTypes(m_calleeMemberDesc);
039: fieldNames = new String[argumentTypes.length];
040: for (int i = 0; i < argumentTypes.length; i++) {
041: Type argumentType = argumentTypes[i];
042: String fieldName = ARGUMENT_FIELD + i;
043: fieldNames[i] = fieldName;
044: m_cw.visitField(ACC_PRIVATE, fieldName, argumentType
045: .getDescriptor(), null, null);
046: }
047: m_fieldNames = fieldNames;
048:
049: m_cw.visitField(ACC_PRIVATE + ACC_STATIC, SIGNATURE_FIELD_NAME,
050: CONSTRUCTOR_SIGNATURE_IMPL_CLASS_SIGNATURE, null, null);
051: }
052:
053: /**
054: * Creates the signature for the join point.
055: * <p/>
056: * FIXME signature field should NOT be of type Signature but of the specific type (update all refs as well)
057: *
058: * @param cv
059: */
060: protected void createSignature(final MethodVisitor cv) {
061: cv.visitFieldInsn(GETSTATIC, m_joinPointClassName,
062: TARGET_CLASS_FIELD_NAME_IN_JP, CLASS_CLASS_SIGNATURE);
063: cv.visitLdcInsn(new Integer(m_joinPointHash));
064:
065: cv.visitMethodInsn(INVOKESTATIC, SIGNATURE_FACTORY_CLASS,
066: NEW_CONSTRUCTOR_SIGNATURE_METHOD_NAME,
067: NEW_CONSTRUCTOR_SIGNATURE_METHOD_SIGNATURE);
068: cv.visitFieldInsn(PUTSTATIC, m_joinPointClassName,
069: SIGNATURE_FIELD_NAME,
070: CONSTRUCTOR_SIGNATURE_IMPL_CLASS_SIGNATURE);
071: }
072:
073: /**
074: * Optimized implementation that does not retrieve the parameters from the join point instance but is passed
075: * directly to the method from the input parameters in the 'invoke' method. Can only be used if no around advice
076: * exists.
077: *
078: * @param cv
079: * @param input
080: */
081: protected void createInlinedJoinPointInvocation(
082: final MethodVisitor cv, final CompilerInput input) {
083: if (!Modifier.isPublic(m_calleeMemberModifiers)) {
084: loadArgumentMemberFields(cv, input.argStartIndex);
085: cv.visitMethodInsn(INVOKESTATIC, m_calleeClassName,
086: TransformationUtil.getWrapperMethodName(
087: m_calleeMemberName, m_calleeMemberDesc,
088: m_calleeClassName,
089: INVOKE_WRAPPER_METHOD_PREFIX), Type
090: .getMethodDescriptor(Type
091: .getType(m_calleeClassSignature),
092: m_argumentTypes));
093: } else {
094: cv.visitTypeInsn(NEW, m_calleeClassName);
095: cv.visitInsn(DUP);
096: loadArgumentMemberFields(cv, input.argStartIndex);
097: cv.visitMethodInsn(INVOKESPECIAL, m_calleeClassName,
098: INIT_METHOD_NAME, m_calleeMemberDesc);
099: }
100: // assign to CALLEE
101: //TODO - might not be needed / feasible for optimized jp - we should ensure that it is affected to target for
102: // after advice that comes after (but should we support target on ctor call)
103: cv.visitInsn(DUP);
104: loadJoinPointInstance(cv, input);
105: cv.visitInsn(SWAP);
106: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
107: CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
108: }
109:
110: /**
111: * Creates a call to the target join point, the parameter(s) to the join point are retrieved from the invocation
112: * local join point instance.
113: *
114: * @param cv
115: */
116: protected void createJoinPointInvocation(final MethodVisitor cv) {
117: if (!Modifier.isPublic(m_calleeMemberModifiers)) {
118: loadArguments(cv);
119: cv.visitMethodInsn(INVOKESTATIC, m_calleeClassName,
120: TransformationUtil.getWrapperMethodName(
121: m_calleeMemberName, m_calleeMemberDesc,
122: m_calleeClassName,
123: INVOKE_WRAPPER_METHOD_PREFIX), Type
124: .getMethodDescriptor(Type
125: .getType(m_calleeClassSignature),
126: m_argumentTypes));
127: } else {
128: cv.visitTypeInsn(NEW, m_calleeClassName);
129: cv.visitInsn(DUP);
130: loadArguments(cv);
131: cv.visitMethodInsn(INVOKESPECIAL, m_calleeClassName,
132: INIT_METHOD_NAME, m_calleeMemberDesc);
133: }
134:
135: // put it in CALLEE field
136: cv.visitInsn(DUP);
137: cv.visitVarInsn(ALOAD, 0);
138: cv.visitInsn(SWAP);
139: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
140: CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
141: }
142:
143: /**
144: * Returns the join points return type.
145: *
146: * @return
147: */
148: protected Type getJoinPointReturnType() {
149: return Type.getReturnType(m_calleeClassSignature);
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: MethodVisitor cv = m_cw.visitMethod(ACC_PUBLIC,
166: GET_RTTI_METHOD_NAME, GET_RTTI_METHOD_SIGNATURE, null,
167: null);
168:
169: // new CtorRttiImpl( .. )
170: cv.visitTypeInsn(NEW, CONSTRUCTOR_RTTI_IMPL_CLASS_NAME);
171: cv.visitInsn(DUP);
172: cv.visitFieldInsn(GETSTATIC, m_joinPointClassName,
173: SIGNATURE_FIELD_NAME,
174: CONSTRUCTOR_SIGNATURE_IMPL_CLASS_SIGNATURE);
175: cv.visitVarInsn(ALOAD, 0);
176: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
177: CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
178: cv.visitVarInsn(ALOAD, 0);
179: // use RETURNED field instead
180: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
181: RETURN_VALUE_FIELD_NAME, m_calleeClassSignature);
182: cv.visitMethodInsn(INVOKESPECIAL,
183: CONSTRUCTOR_RTTI_IMPL_CLASS_NAME, INIT_METHOD_NAME,
184: CONSTRUCTOR_RTTI_IMPL_INIT_SIGNATURE);
185:
186: // set the arguments
187: cv.visitInsn(DUP);
188: createArgumentArrayAt(cv, 1);
189: cv.visitVarInsn(ALOAD, 1);
190: cv.visitMethodInsn(INVOKEVIRTUAL,
191: CONSTRUCTOR_RTTI_IMPL_CLASS_NAME,
192: SET_PARAMETER_VALUES_METHOD_NAME,
193: SET_PARAMETER_VALUES_METHOD_SIGNATURE);
194:
195: cv.visitInsn(ARETURN);
196: cv.visitMaxs(0, 0);
197: }
198:
199: /**
200: * Creates the getSignature method.
201: */
202: protected void createGetSignatureMethod() {
203: MethodVisitor cv = m_cw.visitMethod(ACC_PUBLIC,
204: GET_SIGNATURE_METHOD_NAME,
205: GET_SIGNATURE_METHOD_SIGNATURE, null, null);
206: cv.visitFieldInsn(GETSTATIC, m_joinPointClassName,
207: SIGNATURE_FIELD_NAME,
208: CONSTRUCTOR_SIGNATURE_IMPL_CLASS_SIGNATURE);
209: cv.visitInsn(ARETURN);
210: cv.visitMaxs(0, 0);
211: }
212: }
|