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