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