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 MethodExecutionJoinPointCompiler extends
022: AbstractJoinPointCompiler {
023:
024: /**
025: * Creates a new join point compiler instance.
026: *
027: * @param model
028: */
029: MethodExecutionJoinPointCompiler(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:
050: m_fieldNames = fieldNames;
051:
052: m_cw.visitField(ACC_PRIVATE + ACC_STATIC, SIGNATURE_FIELD_NAME,
053: METHOD_SIGNATURE_IMPL_CLASS_SIGNATURE, null, null);
054: }
055:
056: /**
057: * Creates the signature for the join point.
058: * <p/>
059: * FIXME signature field should NOT be of type Signature but of the specific type (update all refs as well)
060: *
061: * @param cv
062: */
063: protected void createSignature(final MethodVisitor cv) {
064: cv.visitFieldInsn(GETSTATIC, m_joinPointClassName,
065: TARGET_CLASS_FIELD_NAME_IN_JP, CLASS_CLASS_SIGNATURE);
066: cv.visitLdcInsn(new Integer(m_joinPointHash));
067:
068: cv.visitMethodInsn(INVOKESTATIC, SIGNATURE_FACTORY_CLASS,
069: NEW_METHOD_SIGNATURE_METHOD_NAME,
070: NEW_METHOD_SIGNATURE_METHOD_SIGNATURE);
071: cv.visitFieldInsn(PUTSTATIC, m_joinPointClassName,
072: SIGNATURE_FIELD_NAME,
073: METHOD_SIGNATURE_IMPL_CLASS_SIGNATURE);
074:
075: }
076:
077: /**
078: * Optimized implementation that does not retrieve the parameters from the join point instance but is passed
079: * directly to the method from the input parameters in the 'invoke' method. Can only be used if no around advice
080: * exists.
081: *
082: * @param cv
083: * @param input
084: */
085: protected void createInlinedJoinPointInvocation(
086: final MethodVisitor cv, final CompilerInput input) {
087:
088: // load the target instance (arg0 else not available for static target)
089: if (!Modifier.isStatic(m_calleeMemberModifiers)) {
090: cv.visitVarInsn(ALOAD, 0);
091: }
092:
093: String joinPointName = null; // can be prefixed
094:
095: loadArgumentMemberFields(cv, input.argStartIndex);
096: joinPointName = TransformationUtil
097: .getPrefixedOriginalMethodName(m_calleeMemberName,
098: m_calleeClassName);
099: if (Modifier.isStatic(m_calleeMemberModifiers)) {
100: cv.visitMethodInsn(INVOKESTATIC, m_calleeClassName,
101: joinPointName, m_calleeMemberDesc);
102: } else {
103: cv.visitMethodInsn(INVOKEVIRTUAL, m_calleeClassName,
104: joinPointName, m_calleeMemberDesc);
105: }
106:
107: }
108:
109: /**
110: * Creates a call to the target join point, the parameter(s) to the join point are retrieved from the invocation
111: * local join point instance.
112: *
113: * @param cv
114: */
115: protected void createJoinPointInvocation(final MethodVisitor cv) {
116:
117: // load the target instance member field unless calleeMember is static
118: if (!Modifier.isStatic(m_calleeMemberModifiers)) {
119: cv.visitVarInsn(ALOAD, 0);
120: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
121: CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
122: }
123:
124: String joinPointName;
125: loadArguments(cv);
126: joinPointName = TransformationUtil
127: .getPrefixedOriginalMethodName(m_calleeMemberName,
128: m_calleeClassName);
129: if (Modifier.isStatic(m_calleeMemberModifiers)) {
130: cv.visitMethodInsn(INVOKESTATIC, m_calleeClassName,
131: joinPointName, m_calleeMemberDesc);
132: } else {
133: cv.visitMethodInsn(INVOKEVIRTUAL, m_calleeClassName,
134: joinPointName, m_calleeMemberDesc);
135: }
136: }
137:
138: /**
139: * Returns the join points return type.
140: *
141: * @return
142: */
143: protected Type getJoinPointReturnType() {
144: return Type.getReturnType(m_calleeMemberDesc);
145: }
146:
147: /**
148: * Returns the join points argument type(s).
149: *
150: * @return
151: */
152: protected Type[] getJoinPointArgumentTypes() {
153: return Type.getArgumentTypes(m_calleeMemberDesc);
154: }
155:
156: /**
157: * Creates the getRtti method
158: */
159: protected void createGetRttiMethod() {
160: MethodVisitor cv = m_cw.visitMethod(ACC_PUBLIC,
161: GET_RTTI_METHOD_NAME, GET_RTTI_METHOD_SIGNATURE, null,
162: null);
163:
164: // new MethodRttiImpl( .. )
165: cv.visitTypeInsn(NEW, METHOD_RTTI_IMPL_CLASS_NAME);
166: cv.visitInsn(DUP);
167: cv.visitFieldInsn(GETSTATIC, m_joinPointClassName,
168: SIGNATURE_FIELD_NAME,
169: METHOD_SIGNATURE_IMPL_CLASS_SIGNATURE);
170: cv.visitVarInsn(ALOAD, 0);
171: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
172: CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
173: cv.visitVarInsn(ALOAD, 0);
174: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
175: CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
176: cv.visitMethodInsn(INVOKESPECIAL, METHOD_RTTI_IMPL_CLASS_NAME,
177: INIT_METHOD_NAME, METHOD_RTTI_IMPL_INIT_SIGNATURE);
178:
179: // set the arguments
180: cv.visitInsn(DUP);
181: createArgumentArrayAt(cv, 1);
182: cv.visitVarInsn(ALOAD, 1);
183: cv.visitMethodInsn(INVOKEVIRTUAL, METHOD_RTTI_IMPL_CLASS_NAME,
184: SET_PARAMETER_VALUES_METHOD_NAME,
185: SET_PARAMETER_VALUES_METHOD_SIGNATURE);
186:
187: // set the Returned instance
188: if (m_returnType.getSort() != Type.VOID) {
189: cv.visitInsn(DUP);
190: if (AsmHelper.isPrimitive(m_returnType)) {
191: AsmHelper.prepareWrappingOfPrimitiveType(cv,
192: m_returnType);
193: cv.visitVarInsn(ALOAD, 0);
194: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
195: RETURN_VALUE_FIELD_NAME, m_returnType
196: .getDescriptor());
197: AsmHelper.wrapPrimitiveType(cv, m_returnType);
198: } else {
199: cv.visitVarInsn(ALOAD, 0);
200: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
201: RETURN_VALUE_FIELD_NAME, m_returnType
202: .getDescriptor());
203: }
204: cv.visitMethodInsn(INVOKEVIRTUAL,
205: METHOD_RTTI_IMPL_CLASS_NAME,
206: SET_RETURN_VALUE_METHOD_NAME,
207: SET_RETURN_VALUE_METHOD_SIGNATURE);
208: }
209:
210: cv.visitInsn(ARETURN);
211: cv.visitMaxs(0, 0);
212: }
213:
214: /**
215: * Creates the getSignature method.
216: */
217: protected void createGetSignatureMethod() {
218: MethodVisitor cv = m_cw.visitMethod(ACC_PUBLIC,
219: GET_SIGNATURE_METHOD_NAME,
220: GET_SIGNATURE_METHOD_SIGNATURE, null, null);
221:
222: cv.visitFieldInsn(GETSTATIC, m_joinPointClassName,
223: SIGNATURE_FIELD_NAME,
224: METHOD_SIGNATURE_IMPL_CLASS_SIGNATURE);
225: cv.visitInsn(ARETURN);
226: cv.visitMaxs(0, 0);
227: }
228: }
|