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 FieldGetJoinPointCompiler extends
025: AbstractJoinPointCompiler {
026:
027: /**
028: * Creates a new join point compiler instance.
029: *
030: * @param model
031: */
032: FieldGetJoinPointCompiler(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 field argument field
042: Type fieldType = Type.getType(m_calleeMemberDesc);
043: fieldNames = new String[1];
044: String fieldName = ARGUMENT_FIELD + 0;
045: fieldNames[0] = fieldName;
046: m_cw.visitField(ACC_PRIVATE, fieldName, fieldType
047: .getDescriptor(), null, null);
048: m_fieldNames = fieldNames;
049:
050: m_cw.visitField(ACC_PRIVATE + ACC_STATIC, SIGNATURE_FIELD_NAME,
051: FIELD_SIGNATURE_IMPL_CLASS_SIGNATURE, null, null);
052: }
053:
054: /**
055: * Creates the signature for the join point.
056: * <p/>
057: * FIXME signature field should NOT be of type Signature but of the specific type (update all refs as well)
058: *
059: * @param cv
060: */
061: protected void createSignature(final CodeVisitor cv) {
062: cv.visitFieldInsn(GETSTATIC, m_joinPointClassName,
063: TARGET_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
064: cv.visitLdcInsn(new Integer(m_joinPointHash));
065:
066: cv.visitMethodInsn(INVOKESTATIC, SIGNATURE_FACTORY_CLASS,
067: NEW_FIELD_SIGNATURE_METHOD_NAME,
068: NEW_FIELD_SIGNATURE_METHOD_SIGNATURE);
069: cv.visitFieldInsn(PUTSTATIC, m_joinPointClassName,
070: SIGNATURE_FIELD_NAME,
071: FIELD_SIGNATURE_IMPL_CLASS_SIGNATURE);
072: }
073:
074: /**
075: * Optimized implementation that does not retrieve the parameters from the join point instance but is passed
076: * directly to the method from the input parameters in the 'invoke' method. Can only be used if no around advice
077: * exists.
078: *
079: * @param cv
080: * @param argStartIndex index on stack of first target method arg (0 or 1, depends of static target or not)
081: */
082: protected void createInlinedJoinPointInvocation(
083: final CodeVisitor cv, final boolean isOptimizedJoinPoint,
084: final int argStartIndex, final int joinPointIndex) {
085:
086: // load the target instance (arg0 else not available for static target)
087: if (!Modifier.isStatic(m_calleeMemberModifiers)) {
088: cv.visitVarInsn(ALOAD, 0);
089: }
090:
091: // do we have a public field ? If so don't use the wrappers
092: if (Modifier.isPublic(m_calleeMemberModifiers)) {
093: if (Modifier.isStatic(m_calleeMemberModifiers)) {
094: cv.visitFieldInsn(GETSTATIC, m_calleeClassName,
095: m_calleeMemberName, m_calleeMemberDesc);
096: } else {
097: cv.visitFieldInsn(GETFIELD, m_calleeClassName,
098: m_calleeMemberName, m_calleeMemberDesc);
099: }
100: } else {
101: // use the wrapper
102: String joinPointName = TransformationUtil
103: .getWrapperMethodName(m_calleeMemberName,
104: m_calleeMemberDesc, m_calleeClassName,
105: GETFIELD_WRAPPER_METHOD_PREFIX);
106: StringBuffer getFieldWrapperDesc = new StringBuffer();
107: getFieldWrapperDesc.append('(');
108: getFieldWrapperDesc.append(')');
109: getFieldWrapperDesc.append(m_calleeMemberDesc);
110: if (Modifier.isStatic(m_calleeMemberModifiers)) {
111: cv.visitMethodInsn(INVOKESTATIC, m_calleeClassName,
112: joinPointName, getFieldWrapperDesc.toString());
113: } else {
114: cv.visitMethodInsn(INVOKEVIRTUAL, m_calleeClassName,
115: joinPointName, getFieldWrapperDesc.toString());
116: }
117: }
118: }
119:
120: /**
121: * Creates a call to the target join point, the parameter(s) to the join point are retrieved from the invocation
122: * local join point instance.
123: *
124: * @param cv
125: */
126: protected void createJoinPointInvocation(final CodeVisitor cv) {
127:
128: // load the target instance member field unless calleeMember is static
129: if (!Modifier.isStatic(m_calleeMemberModifiers)) {
130: cv.visitVarInsn(ALOAD, 0);
131: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
132: CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
133: }
134:
135: // do we have a public field ? If so don't use the wrappers
136: if (Modifier.isPublic(m_calleeMemberModifiers)) {
137: if (Modifier.isStatic(m_calleeMemberModifiers)) {
138: cv.visitFieldInsn(GETSTATIC, m_calleeClassName,
139: m_calleeMemberName, m_calleeMemberDesc);
140: } else {
141: cv.visitFieldInsn(GETFIELD, m_calleeClassName,
142: m_calleeMemberName, m_calleeMemberDesc);
143: }
144: } else {
145: String joinPointName = TransformationUtil
146: .getWrapperMethodName(m_calleeMemberName,
147: m_calleeMemberDesc, m_calleeClassName,
148: GETFIELD_WRAPPER_METHOD_PREFIX);
149: StringBuffer getFieldWrapperDesc = new StringBuffer();
150: getFieldWrapperDesc.append('(');
151: getFieldWrapperDesc.append(')');
152: getFieldWrapperDesc.append(m_calleeMemberDesc);
153: if (Modifier.isStatic(m_calleeMemberModifiers)) {
154: cv.visitMethodInsn(INVOKESTATIC, m_calleeClassName,
155: joinPointName, getFieldWrapperDesc.toString());
156: } else {
157: cv.visitMethodInsn(INVOKEVIRTUAL, m_calleeClassName,
158: joinPointName, getFieldWrapperDesc.toString());
159: }
160: }
161: }
162:
163: /**
164: * Returns the join points return type.
165: *
166: * @return
167: */
168: protected Type getJoinPointReturnType() {
169: return Type.getType(m_calleeMemberDesc);
170: }
171:
172: /**
173: * Returns the join points argument type(s).
174: *
175: * @return
176: */
177: protected Type[] getJoinPointArgumentTypes() {
178: return new Type[] { Type.getType(m_calleeMemberDesc) };
179: }
180:
181: /**
182: * Creates the getRtti method
183: */
184: protected void createGetRttiMethod() {
185: CodeVisitor cv = m_cw.visitMethod(ACC_PUBLIC,
186: GET_RTTI_METHOD_NAME, GET_RTTI_METHOD_SIGNATURE, null,
187: null);
188:
189: // new FieldRttiImpl( .. )
190: cv.visitTypeInsn(NEW, FIELD_RTTI_IMPL_CLASS_NAME);
191: cv.visitInsn(DUP);
192: cv.visitFieldInsn(GETSTATIC, m_joinPointClassName,
193: SIGNATURE_FIELD_NAME,
194: FIELD_SIGNATURE_IMPL_CLASS_SIGNATURE);
195: cv.visitVarInsn(ALOAD, 0);
196: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
197: CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
198: cv.visitVarInsn(ALOAD, 0);
199: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
200: CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
201: cv.visitMethodInsn(INVOKESPECIAL, FIELD_RTTI_IMPL_CLASS_NAME,
202: INIT_METHOD_NAME, FIELD_RTTI_IMPL_INIT_SIGNATURE);
203:
204: // set the value
205: cv.visitInsn(DUP);
206: if (AsmHelper.isPrimitive(m_returnType)) {
207: AsmHelper.prepareWrappingOfPrimitiveType(cv, m_returnType);
208: cv.visitVarInsn(ALOAD, 0);
209: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
210: RETURN_VALUE_FIELD_NAME, m_returnType
211: .getDescriptor());
212: AsmHelper.wrapPrimitiveType(cv, m_returnType);
213: } else {
214: cv.visitVarInsn(ALOAD, 0);
215: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
216: RETURN_VALUE_FIELD_NAME, m_returnType
217: .getDescriptor());
218: }
219: cv.visitMethodInsn(INVOKEVIRTUAL, FIELD_RTTI_IMPL_CLASS_NAME,
220: SET_FIELD_VALUE_METHOD_NAME,
221: SET_FIELD_VALUE_METHOD_SIGNATURE);
222:
223: cv.visitInsn(ARETURN);
224: cv.visitMaxs(0, 0);
225: }
226:
227: /**
228: * Creates the getSignature method.
229: */
230: protected void createGetSignatureMethod() {
231: CodeVisitor cv = m_cw.visitMethod(ACC_PUBLIC,
232: GET_SIGNATURE_METHOD_NAME,
233: GET_SIGNATURE_METHOD_SIGNATURE, null, null);
234: cv.visitFieldInsn(GETSTATIC, m_joinPointClassName,
235: SIGNATURE_FIELD_NAME,
236: FIELD_SIGNATURE_IMPL_CLASS_SIGNATURE);
237: cv.visitInsn(ARETURN);
238: cv.visitMaxs(0, 0);
239: }
240: }
|