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: import com.tc.aspectwerkz.transform.inlining.AsmHelper;
011:
012: import java.lang.reflect.Modifier;
013:
014: /**
015: * A compiler that compiles/generates a class that represents a specific join point, a class which invokes the advices
016: * and the target join point statically.
017: *
018: * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
019: * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur </a>
020: */
021: public class MethodCallJoinPointCompiler extends
022: AbstractJoinPointCompiler {
023:
024: /**
025: * Creates a new join point compiler instance.
026: *
027: * @param model
028: */
029: MethodCallJoinPointCompiler(final CompilationInfo.Model model) {
030: super (model);
031: }
032:
033: /**
034: * Creates join point specific fields.
035: */
036: protected void createJoinPointSpecificFields() {
037: String[] fieldNames = null;
038: // create the method argument fields
039: Type[] argumentTypes = Type
040: .getArgumentTypes(m_calleeMemberDesc);
041: fieldNames = new String[argumentTypes.length];
042: for (int i = 0; i < argumentTypes.length; i++) {
043: Type argumentType = argumentTypes[i];
044: String fieldName = ARGUMENT_FIELD + i;
045: fieldNames[i] = fieldName;
046: m_cw.visitField(ACC_PRIVATE, fieldName, argumentType
047: .getDescriptor(), null, null);
048: }
049: m_fieldNames = fieldNames;
050:
051: m_cw.visitField(ACC_PRIVATE + ACC_STATIC, SIGNATURE_FIELD_NAME,
052: METHOD_SIGNATURE_IMPL_CLASS_SIGNATURE, null, null);
053: }
054:
055: /**
056: * Creates the signature for the join point.
057: * <p/>
058: * FIXME signature field should NOT be of type Signature but of the specific type (update all refs as well)
059: *
060: * @param cv
061: */
062: protected void createSignature(final MethodVisitor cv) {
063: cv.visitFieldInsn(GETSTATIC, m_joinPointClassName,
064: TARGET_CLASS_FIELD_NAME_IN_JP, CLASS_CLASS_SIGNATURE);
065: cv.visitLdcInsn(new Integer(m_joinPointHash));
066:
067: cv.visitMethodInsn(INVOKESTATIC, SIGNATURE_FACTORY_CLASS,
068: NEW_METHOD_SIGNATURE_METHOD_NAME,
069: NEW_METHOD_SIGNATURE_METHOD_SIGNATURE);
070: cv.visitFieldInsn(PUTSTATIC, m_joinPointClassName,
071: SIGNATURE_FIELD_NAME,
072: METHOD_SIGNATURE_IMPL_CLASS_SIGNATURE);
073:
074: }
075:
076: /**
077: * Optimized implementation that does not retrieve the parameters from the join point instance but is passed
078: * directly to the method from the input parameters in the 'invoke' method. Can only be used if no around advice
079: * exists.
080: *
081: * @param cv
082: * @param input
083: */
084: protected void createInlinedJoinPointInvocation(
085: final MethodVisitor cv, final CompilerInput input) {
086:
087: // load the target instance (arg0 else not available for static target)
088: if (!Modifier.isStatic(m_calleeMemberModifiers)) {
089: cv.visitVarInsn(ALOAD, 0);
090: }
091:
092: String joinPointName = null; // can be prefixed
093:
094: loadArgumentMemberFields(cv, input.argStartIndex);
095:
096: // call the package protected wrapper method if target method is not public
097: if (!Modifier.isPublic(m_calleeMemberModifiers)) {
098: joinPointName = TransformationUtil.getWrapperMethodName(
099: m_calleeMemberName, m_calleeMemberDesc,
100: m_calleeClassName, INVOKE_WRAPPER_METHOD_PREFIX);
101: } else {
102: joinPointName = m_calleeMemberName;
103: }
104: // FIXME - pbly broken if we are using a wrapper method - refactor this if / else
105: if (Modifier.isStatic(m_calleeMemberModifiers)) {
106: cv.visitMethodInsn(INVOKESTATIC, m_calleeClassName,
107: joinPointName, m_calleeMemberDesc);
108: } else if (isInvokeInterface(m_calleeMemberModifiers)) {
109: // AW-253
110: cv.visitMethodInsn(INVOKEINTERFACE, m_calleeClassName,
111: joinPointName, m_calleeMemberDesc);
112: } else {
113: cv.visitMethodInsn(INVOKEVIRTUAL, m_calleeClassName,
114: joinPointName, m_calleeMemberDesc);
115: }
116: }
117:
118: /**
119: * Creates a call to the target join point, the parameter(s) to the join point are retrieved from the invocation
120: * local join point instance.
121: *
122: * @param cv
123: */
124: protected void createJoinPointInvocation(final MethodVisitor cv) {
125:
126: // load the target instance member field unless calleeMember is static
127: if (!Modifier.isStatic(m_calleeMemberModifiers)) {
128: cv.visitVarInsn(ALOAD, 0);
129: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
130: CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
131: }
132:
133: String joinPointName;
134: loadArguments(cv);
135: if (!Modifier.isPublic(m_calleeMemberModifiers)) {
136: joinPointName = TransformationUtil.getWrapperMethodName(
137: m_calleeMemberName, m_calleeMemberDesc,
138: m_calleeClassName, INVOKE_WRAPPER_METHOD_PREFIX);
139: } else {
140: joinPointName = m_calleeMemberName;
141: }
142: // FIXME - pbly broken if we are using a wrapper method - refactor this if / else
143: if (Modifier.isStatic(m_calleeMemberModifiers)) {
144: cv.visitMethodInsn(INVOKESTATIC, m_calleeClassName,
145: joinPointName, m_calleeMemberDesc);
146: } else if (isInvokeInterface(m_calleeMemberModifiers)) {
147: // AW-253
148: cv.visitMethodInsn(INVOKEINTERFACE, m_calleeClassName,
149: joinPointName, m_calleeMemberDesc);
150: } else {
151: cv.visitMethodInsn(INVOKEVIRTUAL, m_calleeClassName,
152: joinPointName, m_calleeMemberDesc);
153: }
154: }
155:
156: /**
157: * Returns the join points return type.
158: *
159: * @return
160: */
161: protected Type getJoinPointReturnType() {
162: return Type.getReturnType(m_calleeMemberDesc);
163: }
164:
165: /**
166: * Returns the join points argument type(s).
167: *
168: * @return
169: */
170: protected Type[] getJoinPointArgumentTypes() {
171: return Type.getArgumentTypes(m_calleeMemberDesc);
172: }
173:
174: /**
175: * Creates the getRtti method
176: */
177: protected void createGetRttiMethod() {
178: MethodVisitor cv = m_cw.visitMethod(ACC_PUBLIC,
179: GET_RTTI_METHOD_NAME, GET_RTTI_METHOD_SIGNATURE, null,
180: null);
181:
182: // new MethodRttiImpl( .. )
183: cv.visitTypeInsn(NEW, METHOD_RTTI_IMPL_CLASS_NAME);
184: cv.visitInsn(DUP);
185: cv.visitFieldInsn(GETSTATIC, m_joinPointClassName,
186: SIGNATURE_FIELD_NAME,
187: METHOD_SIGNATURE_IMPL_CLASS_SIGNATURE);
188: cv.visitVarInsn(ALOAD, 0);
189: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
190: CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
191: cv.visitVarInsn(ALOAD, 0);
192: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
193: CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
194: cv.visitMethodInsn(INVOKESPECIAL, METHOD_RTTI_IMPL_CLASS_NAME,
195: INIT_METHOD_NAME, METHOD_RTTI_IMPL_INIT_SIGNATURE);
196:
197: // set the arguments
198: cv.visitInsn(DUP);
199: createArgumentArrayAt(cv, 1);
200: cv.visitVarInsn(ALOAD, 1);
201: cv.visitMethodInsn(INVOKEVIRTUAL, METHOD_RTTI_IMPL_CLASS_NAME,
202: SET_PARAMETER_VALUES_METHOD_NAME,
203: SET_PARAMETER_VALUES_METHOD_SIGNATURE);
204:
205: // set the Returned instance
206: if (m_returnType.getSort() != Type.VOID) {
207: cv.visitInsn(DUP);
208: if (AsmHelper.isPrimitive(m_returnType)) {
209: AsmHelper.prepareWrappingOfPrimitiveType(cv,
210: m_returnType);
211: cv.visitVarInsn(ALOAD, 0);
212: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
213: RETURN_VALUE_FIELD_NAME, m_returnType
214: .getDescriptor());
215: AsmHelper.wrapPrimitiveType(cv, m_returnType);
216: } else {
217: cv.visitVarInsn(ALOAD, 0);
218: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
219: RETURN_VALUE_FIELD_NAME, m_returnType
220: .getDescriptor());
221: }
222: cv.visitMethodInsn(INVOKEVIRTUAL,
223: METHOD_RTTI_IMPL_CLASS_NAME,
224: SET_RETURN_VALUE_METHOD_NAME,
225: SET_RETURN_VALUE_METHOD_SIGNATURE);
226: }
227:
228: cv.visitInsn(ARETURN);
229: cv.visitMaxs(0, 0);
230: }
231:
232: /**
233: * Creates the getSignature method.
234: */
235: protected void createGetSignatureMethod() {
236: MethodVisitor cv = m_cw.visitMethod(ACC_PUBLIC,
237: GET_SIGNATURE_METHOD_NAME,
238: GET_SIGNATURE_METHOD_SIGNATURE, null, null);
239:
240: cv.visitFieldInsn(GETSTATIC, m_joinPointClassName,
241: SIGNATURE_FIELD_NAME,
242: METHOD_SIGNATURE_IMPL_CLASS_SIGNATURE);
243: cv.visitInsn(ARETURN);
244: cv.visitMaxs(0, 0);
245: }
246:
247: /**
248: * See AW-253
249: * For INVOKE INTERFACE, we are using a custom modifier to track it down in order to avoid to do the
250: * hierarchy resolution ourself here
251: */
252: private boolean isInvokeInterface(int modifier) {
253: return (modifier & MODIFIER_INVOKEINTERFACE) != 0;
254: }
255: }
|