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.compiler.AbstractJoinPointCompiler;
014: import org.codehaus.aspectwerkz.transform.inlining.AsmHelper;
015:
016: import java.lang.reflect.Modifier;
017:
018: /**
019: * A compiler that compiles/generates a class that represents a specific join point, a class which invokes the advices
020: * and the target join point statically.
021: *
022: * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
023: * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur </a>
024: */
025: public class FieldSetJoinPointCompiler extends
026: AbstractJoinPointCompiler {
027:
028: /**
029: * Creates a new join point compiler instance.
030: *
031: * @param model
032: */
033: FieldSetJoinPointCompiler(final CompilationInfo.Model model) {
034: super (model);
035: }
036:
037: /**
038: * Creates join point specific fields.
039: */
040: protected void createJoinPointSpecificFields() {
041: String[] fieldNames = null;
042: // create the field argument field
043: Type fieldType = Type.getType(m_calleeMemberDesc);
044: fieldNames = new String[1];
045: String fieldName = ARGUMENT_FIELD + 0;
046: fieldNames[0] = fieldName;
047: m_cw.visitField(ACC_PRIVATE, fieldName, fieldType
048: .getDescriptor(), null, null);
049: m_fieldNames = fieldNames;
050:
051: m_cw.visitField(ACC_PRIVATE + ACC_STATIC, SIGNATURE_FIELD_NAME,
052: FIELD_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 CodeVisitor cv) {
063: cv.visitFieldInsn(GETSTATIC, m_joinPointClassName,
064: TARGET_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
065: cv.visitLdcInsn(new Integer(m_joinPointHash));
066:
067: cv.visitMethodInsn(INVOKESTATIC, SIGNATURE_FACTORY_CLASS,
068: NEW_FIELD_SIGNATURE_METHOD_NAME,
069: NEW_FIELD_SIGNATURE_METHOD_SIGNATURE);
070: cv.visitFieldInsn(PUTSTATIC, m_joinPointClassName,
071: SIGNATURE_FIELD_NAME,
072: FIELD_SIGNATURE_IMPL_CLASS_SIGNATURE);
073: }
074:
075: /**
076: * Optimized implementation that does not retrieve the parameters from the join point instance but is passed
077: * directly to the method from the input parameters in the 'invoke' method. Can only be used if no around advice
078: * exists.
079: *
080: * @param cv
081: * @param argStartIndex index on stack of first target method arg (0 or 1, depends of static target or not)
082: */
083: protected void createInlinedJoinPointInvocation(
084: final CodeVisitor cv, final boolean isOptimizedJoinPoint,
085: final int argStartIndex, final int joinPointIndex) {
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: loadArgumentMemberFields(cv, argStartIndex);
093:
094: // do we have a public field ? If so don't use the wrappers
095: if (Modifier.isPublic(m_calleeMemberModifiers)) {
096: if (Modifier.isStatic(m_calleeMemberModifiers)) {
097: cv.visitFieldInsn(PUTSTATIC, m_calleeClassName,
098: m_calleeMemberName, m_calleeMemberDesc);
099: } else {
100: cv.visitFieldInsn(PUTFIELD, m_calleeClassName,
101: m_calleeMemberName, m_calleeMemberDesc);
102: }
103: } else {
104: String joinPointName = null; // can be prefixed
105: joinPointName = m_calleeMemberName;
106: joinPointName = TransformationUtil.getWrapperMethodName(
107: joinPointName, m_calleeMemberDesc,
108: m_calleeClassName, PUTFIELD_WRAPPER_METHOD_PREFIX);
109: StringBuffer sig = new StringBuffer();
110: sig.append('(');
111: sig.append(m_calleeMemberDesc);
112: sig.append(')');
113: sig.append('V');
114: if (Modifier.isStatic(m_calleeMemberModifiers)) {
115: cv.visitMethodInsn(INVOKESTATIC, m_calleeClassName,
116: joinPointName, sig.toString());
117: } else {
118: cv.visitMethodInsn(INVOKEVIRTUAL, m_calleeClassName,
119: joinPointName, sig.toString());
120: }
121: }
122:
123: AsmHelper.addDefaultValue(cv, m_argumentTypes[0]);
124: }
125:
126: /**
127: * Creates a call to the target join point, the parameter(s) to the join point are retrieved from the invocation
128: * local join point instance.
129: *
130: * @param cv
131: */
132: protected void createJoinPointInvocation(final CodeVisitor cv) {
133:
134: // load the target instance member field unless calleeMember is static
135: if (!Modifier.isStatic(m_calleeMemberModifiers)) {
136: cv.visitVarInsn(ALOAD, 0);
137: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
138: CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
139: }
140:
141: loadArguments(cv);
142:
143: // do we have a public field ? If so don't use the wrappers
144: if (Modifier.isPublic(m_calleeMemberModifiers)) {
145: if (Modifier.isStatic(m_calleeMemberModifiers)) {
146: cv.visitFieldInsn(PUTSTATIC, m_calleeClassName,
147: m_calleeMemberName, m_calleeMemberDesc);
148: } else {
149: cv.visitFieldInsn(PUTFIELD, m_calleeClassName,
150: m_calleeMemberName, m_calleeMemberDesc);
151: }
152: } else {
153: String joinPointName = TransformationUtil
154: .getWrapperMethodName(m_calleeMemberName,
155: m_calleeMemberDesc, m_calleeClassName,
156: PUTFIELD_WRAPPER_METHOD_PREFIX);
157: StringBuffer putFieldWrapperDesc = new StringBuffer();
158: putFieldWrapperDesc.append('(');
159: putFieldWrapperDesc.append(m_calleeMemberDesc);
160: putFieldWrapperDesc.append(')');
161: putFieldWrapperDesc.append('V');
162: if (Modifier.isStatic(m_calleeMemberModifiers)) {
163: cv.visitMethodInsn(INVOKESTATIC, m_calleeClassName,
164: joinPointName, putFieldWrapperDesc.toString());
165: } else {
166: cv.visitMethodInsn(INVOKEVIRTUAL, m_calleeClassName,
167: joinPointName, putFieldWrapperDesc.toString());
168: }
169: }
170:
171: AsmHelper.addDefaultValue(cv, m_argumentTypes[0]);
172: }
173:
174: /**
175: * Returns the join points return type.
176: *
177: * @return
178: */
179: protected Type getJoinPointReturnType() {
180: return Type.getType(m_calleeMemberDesc);
181: }
182:
183: /**
184: * Returns the join points argument type(s).
185: *
186: * @return
187: */
188: protected Type[] getJoinPointArgumentTypes() {
189: return new Type[] { Type.getType(m_calleeMemberDesc) };
190: }
191:
192: /**
193: * Creates the getRtti method
194: */
195: protected void createGetRttiMethod() {
196: CodeVisitor cv = m_cw.visitMethod(ACC_PUBLIC,
197: GET_RTTI_METHOD_NAME, GET_RTTI_METHOD_SIGNATURE, null,
198: null);
199:
200: // new FieldRttiImpl( .. )
201: cv.visitTypeInsn(NEW, FIELD_RTTI_IMPL_CLASS_NAME);
202: cv.visitInsn(DUP);
203: cv.visitFieldInsn(GETSTATIC, m_joinPointClassName,
204: SIGNATURE_FIELD_NAME,
205: FIELD_SIGNATURE_IMPL_CLASS_SIGNATURE);
206: cv.visitVarInsn(ALOAD, 0);
207: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
208: CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
209: cv.visitVarInsn(ALOAD, 0);
210: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
211: CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
212: cv.visitMethodInsn(INVOKESPECIAL, FIELD_RTTI_IMPL_CLASS_NAME,
213: INIT_METHOD_NAME, FIELD_RTTI_IMPL_INIT_SIGNATURE);
214:
215: // set the value
216: cv.visitInsn(DUP);
217: if (AsmHelper.isPrimitive(m_returnType)) {
218: AsmHelper.prepareWrappingOfPrimitiveType(cv, m_returnType);
219: cv.visitVarInsn(ALOAD, 0);
220: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
221: RETURN_VALUE_FIELD_NAME, m_returnType
222: .getDescriptor());
223: AsmHelper.wrapPrimitiveType(cv, m_returnType);
224: } else {
225: cv.visitVarInsn(ALOAD, 0);
226: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
227: RETURN_VALUE_FIELD_NAME, m_returnType
228: .getDescriptor());
229: }
230: cv.visitMethodInsn(INVOKEVIRTUAL, FIELD_RTTI_IMPL_CLASS_NAME,
231: SET_FIELD_VALUE_METHOD_NAME,
232: SET_FIELD_VALUE_METHOD_SIGNATURE);
233:
234: cv.visitInsn(ARETURN);
235: cv.visitMaxs(0, 0);
236: }
237:
238: /**
239: * Creates the getSignature method.
240: */
241: protected void createGetSignatureMethod() {
242: CodeVisitor cv = m_cw.visitMethod(ACC_PUBLIC,
243: GET_SIGNATURE_METHOD_NAME,
244: GET_SIGNATURE_METHOD_SIGNATURE, null, null);
245: cv.visitFieldInsn(GETSTATIC, m_joinPointClassName,
246: SIGNATURE_FIELD_NAME,
247: FIELD_SIGNATURE_IMPL_CLASS_SIGNATURE);
248: cv.visitInsn(ARETURN);
249: cv.visitMaxs(0, 0);
250: }
251: }
|