0001: /*
0002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
0003: */
0004: package com.tc.aspectwerkz.transform.inlining.compiler;
0005:
0006: import com.tc.asm.ClassWriter;
0007: import com.tc.asm.MethodVisitor;
0008: import com.tc.asm.Label;
0009: import com.tc.asm.Type;
0010:
0011: import com.tc.aspectwerkz.DeploymentModel;
0012: import com.tc.aspectwerkz.reflect.ClassInfo;
0013: import com.tc.aspectwerkz.aspect.AdviceInfo;
0014: import com.tc.aspectwerkz.aspect.container.AspectFactoryManager;
0015: import com.tc.aspectwerkz.definition.AspectDefinition;
0016: import com.tc.aspectwerkz.joinpoint.management.AdviceInfoContainer;
0017: import com.tc.aspectwerkz.joinpoint.management.JoinPointType;
0018: import com.tc.aspectwerkz.transform.JoinPointCompiler;
0019: import com.tc.aspectwerkz.transform.Properties;
0020: import com.tc.aspectwerkz.transform.TransformationConstants;
0021: import com.tc.aspectwerkz.transform.inlining.AdviceMethodInfo;
0022: import com.tc.aspectwerkz.transform.inlining.AsmHelper;
0023: import com.tc.aspectwerkz.transform.inlining.AspectInfo;
0024: import com.tc.aspectwerkz.transform.inlining.AspectModelManager;
0025: import com.tc.aspectwerkz.transform.inlining.EmittedJoinPoint;
0026: import com.tc.aspectwerkz.transform.inlining.spi.AspectModel;
0027:
0028: import java.lang.reflect.InvocationTargetException;
0029: import java.lang.reflect.Modifier;
0030: import java.util.ArrayList;
0031: import java.util.HashMap;
0032: import java.util.HashSet;
0033: import java.util.Iterator;
0034: import java.util.List;
0035: import java.util.Map;
0036: import java.util.Set;
0037:
0038: /**
0039: * Abstract base class for the different join point compiler implementations.
0040: * <p/>
0041: * Compiles/generates a class that represents a specific join point, a class which invokes the advices
0042: * and the target join point statically.
0043: * <p/>
0044: * FIXME: depending on hotswap needs, remove the implements StaticJP or JP decision
0045: *
0046: * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
0047: * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur </a>
0048: * @author <a href="mailto:the_mindstorm@evolva.ro">Alex Popescu</a>
0049: */
0050: public abstract class AbstractJoinPointCompiler implements
0051: JoinPointCompiler, TransformationConstants {
0052:
0053: public static final boolean DUMP_JP_CLASSES = Properties.DUMP_JIT_CLOSURES;
0054:
0055: // FIXME get rid of public fields - re architect!!!!!!!!!!!!
0056:
0057: protected final String m_callerClassName;
0058: protected final String m_calleeClassName;
0059: public final String m_callerClassSignature;
0060: public final String m_calleeClassSignature;
0061: public final String m_joinPointClassName;
0062:
0063: protected final int m_joinPointType;
0064: protected final int m_joinPointHash;
0065: protected final String m_callerMethodName;
0066: protected final String m_callerMethodDesc;
0067: protected final int m_callerMethodModifiers;
0068: protected final String m_calleeMemberName;
0069: protected final String m_calleeMemberDesc;
0070: protected final int m_calleeMemberModifiers;
0071:
0072: private final CompilationInfo.Model m_model;
0073:
0074: protected ClassWriter m_cw;
0075: protected AspectInfo[] m_aspectInfos;
0076: protected AspectModel[] m_aspectModels;
0077: protected AdviceMethodInfo[] m_aroundAdviceMethodInfos;
0078: protected AdviceMethodInfo[] m_beforeAdviceMethodInfos;
0079: protected AdviceMethodInfo[] m_afterFinallyAdviceMethodInfos;
0080: protected AdviceMethodInfo[] m_afterReturningAdviceMethodInfos;
0081: protected AdviceMethodInfo[] m_afterThrowingAdviceMethodInfos;
0082:
0083: protected boolean m_hasAroundAdvices = false;
0084: protected boolean m_requiresThisOrTarget = false;
0085: protected boolean m_requiresJoinPoint = false;
0086: protected boolean m_requiresProceedMethod = false;
0087:
0088: public String[] m_fieldNames;
0089: public Type[] m_argumentTypes;
0090: protected Type m_returnType;
0091: protected boolean m_isThisAdvisable = false;
0092:
0093: private CompilerInput m_input;
0094:
0095: /**
0096: * Creates a new join point compiler instance.
0097: *
0098: * @param model the compilation model
0099: */
0100: public AbstractJoinPointCompiler(final CompilationInfo.Model model) {
0101: m_model = model;
0102: m_joinPointClassName = model.getJoinPointClassName();
0103:
0104: final EmittedJoinPoint emittedJoinPoint = model
0105: .getEmittedJoinPoint();
0106:
0107: m_joinPointHash = emittedJoinPoint.getJoinPointHash();
0108: m_joinPointType = emittedJoinPoint.getJoinPointType();
0109:
0110: m_callerMethodName = emittedJoinPoint.getCallerMethodName();
0111: m_callerMethodDesc = emittedJoinPoint.getCallerMethodDesc();
0112: m_callerMethodModifiers = emittedJoinPoint
0113: .getCallerMethodModifiers();
0114:
0115: m_calleeMemberName = emittedJoinPoint.getCalleeMemberName();
0116: m_calleeMemberDesc = emittedJoinPoint.getCalleeMemberDesc();
0117: m_calleeMemberModifiers = emittedJoinPoint
0118: .getCalleeMemberModifiers();
0119:
0120: // NOTE: internal compiler class name format is ALWAYS using '/'
0121: m_callerClassName = emittedJoinPoint.getCallerClassName()
0122: .replace('.', '/');
0123: m_calleeClassName = emittedJoinPoint.getCalleeClassName()
0124: .replace('.', '/');
0125: m_callerClassSignature = L
0126: + emittedJoinPoint.getCallerClassName().replace('.',
0127: '/') + SEMICOLON;
0128: m_calleeClassSignature = L
0129: + emittedJoinPoint.getCalleeClassName().replace('.',
0130: '/') + SEMICOLON;
0131:
0132: m_argumentTypes = getJoinPointArgumentTypes();
0133: m_returnType = getJoinPointReturnType();
0134:
0135: // collect information from the compilation model and setup the aspect model
0136: initialize(model);
0137:
0138: // prepare a CompilerInput instance that will host most of the arguments visible to the models
0139: initializeCompilerInput();
0140: }
0141:
0142: //-- implementation of JoinPointCompiler
0143: public String getCallerClassName() {
0144: return m_callerClassName;
0145: }
0146:
0147: public String getCalleeClassName() {
0148: return m_calleeClassName;
0149: }
0150:
0151: public String getCallerClassSignature() {
0152: return m_callerClassSignature;
0153: }
0154:
0155: public String getCalleeClassSignature() {
0156: return m_calleeClassSignature;
0157: }
0158:
0159: public String getJoinPointClassName() {
0160: return m_joinPointClassName;
0161: }
0162:
0163: /**
0164: * Initializes the the join point compiler.
0165: *
0166: * @param model the compilation model
0167: */
0168: private void initialize(final CompilationInfo.Model model) {
0169: // collect the advices
0170: final AdviceInfoContainer advices = model
0171: .getAdviceInfoContainer();
0172: collectAdviceInfo(advices);
0173:
0174: // setup models at the end so that they can override m_requiresJoinPoint
0175: setupReferencedAspectModels();
0176:
0177: // compute the optimization we can use
0178: m_hasAroundAdvices = m_aroundAdviceMethodInfos.length > 0;
0179: // check if 'caller'(this) is Advisable, e.g. can handle runtime per instance deployment
0180: m_isThisAdvisable = isCallerAdvisable(model);
0181: m_requiresThisOrTarget = requiresThisOrTarget();
0182: m_requiresJoinPoint = requiresJoinPoint();
0183: m_requiresProceedMethod = requiresProceedMethod();
0184:
0185: m_cw = AsmHelper.newClassWriter(true);
0186: }
0187:
0188: /**
0189: * Compute and store index and common information that can be passed thru the aspect model
0190: */
0191: private void initializeCompilerInput() {
0192: m_input = new CompilerInput();
0193:
0194: // signatures
0195: m_input.calleeClassSignature = m_calleeClassSignature;
0196: m_input.callerClassSignature = m_callerClassSignature;
0197: m_input.joinPointClassName = m_joinPointClassName;
0198:
0199: // compute the callee and caller index from the invoke(..) signature
0200: m_input.calleeIndex = INDEX_NOTAVAILABLE;
0201: m_input.argStartIndex = 0;
0202: if (!Modifier.isStatic(m_calleeMemberModifiers)
0203: && m_joinPointType != JoinPointType.CONSTRUCTOR_CALL_INT
0204: && m_joinPointType != JoinPointType.HANDLER_INT) {
0205: m_input.calleeIndex = 0;
0206: m_input.argStartIndex++;
0207: } else {
0208: // no callee in the invoke(..) parameters for static call/exe/getDefault/set, ctor call and handler jp
0209: m_input.calleeIndex = INDEX_NOTAVAILABLE;
0210: }
0211: // caller is always last
0212: m_input.callerIndex = m_input.argStartIndex
0213: + AsmHelper.getRegisterDepth(m_argumentTypes);
0214:
0215: // custom logic overrides for handler jp
0216: if (m_joinPointType == JoinPointType.HANDLER_INT) {
0217: m_input.calleeIndex = 0;
0218: m_input.callerIndex = 2;
0219: m_input.argStartIndex = 1;
0220: }
0221:
0222: // optimization level
0223: // do we need to keep track of CALLEE, ARGS etc, if not then completely skip it
0224: // and make use of the optimized join point instance
0225: // while not using its fields (does not support reentrancy and thread safety)
0226: m_input.isOptimizedJoinPoint = !m_requiresJoinPoint
0227: && !m_requiresProceedMethod;
0228: if (m_input.isOptimizedJoinPoint) {
0229: // we will use the static field that host the sole jp shared instance
0230: m_input.joinPointInstanceIndex = INDEX_NOTAVAILABLE;
0231: } else {
0232: // joinpoint will be new() and stored on first local var
0233: m_input.joinPointInstanceIndex = m_input.callerIndex + 1;
0234: }
0235: }
0236:
0237: /**
0238: * Collects the advice info.
0239: *
0240: * @param advices
0241: */
0242: private void collectAdviceInfo(final AdviceInfoContainer advices) {
0243: //final List aspectQualifiedNames = new ArrayList();// in fact a Set but we need indexOf
0244: final Map aspectInfoByQualifiedName = new HashMap();
0245: m_beforeAdviceMethodInfos = getAdviceMethodInfos(
0246: aspectInfoByQualifiedName, advices
0247: .getBeforeAdviceInfos());
0248: m_aroundAdviceMethodInfos = getAdviceMethodInfos(
0249: aspectInfoByQualifiedName, advices
0250: .getAroundAdviceInfos());
0251: m_afterReturningAdviceMethodInfos = getAdviceMethodInfos(
0252: aspectInfoByQualifiedName, advices
0253: .getAfterReturningAdviceInfos());
0254: m_afterFinallyAdviceMethodInfos = getAdviceMethodInfos(
0255: aspectInfoByQualifiedName, advices
0256: .getAfterFinallyAdviceInfos());
0257: m_afterThrowingAdviceMethodInfos = getAdviceMethodInfos(
0258: aspectInfoByQualifiedName, advices
0259: .getAfterThrowingAdviceInfos());
0260:
0261: m_aspectInfos = (AspectInfo[]) aspectInfoByQualifiedName
0262: .values()
0263: .toArray(
0264: new AspectInfo[aspectInfoByQualifiedName.size()]);
0265:
0266: //
0267:
0268: }
0269:
0270: /**
0271: * Checks if the caller class implements the Advisable interface.
0272: *
0273: * @param model
0274: */
0275: private boolean isCallerAdvisable(final CompilationInfo.Model model) {
0276: if (!Modifier.isStatic(m_callerMethodModifiers)) {
0277: ClassInfo[] interfaces = model.getThisClassInfo()
0278: .getInterfaces();
0279: for (int i = 0; i < interfaces.length; i++) {
0280: if (interfaces[i].getName().equals(
0281: ADVISABLE_CLASS_JAVA_NAME)) {
0282: return true;
0283: }
0284: }
0285: }
0286: return false;
0287: }
0288:
0289: /**
0290: * Retrieves and sets the aspect models that are referenced in this compilation phase.
0291: */
0292: private void setupReferencedAspectModels() {
0293: Map aspectModelInstanceByType = new HashMap();
0294: for (int i = 0; i < m_aspectInfos.length; i++) {
0295: AspectDefinition aspectDef = m_aspectInfos[i]
0296: .getAspectDefinition();
0297: if (!aspectModelInstanceByType.containsKey(aspectDef
0298: .getAspectModel())) {
0299: AspectModel aspectModel = AspectModelManager
0300: .getModelFor(aspectDef.getAspectModel())
0301: .getInstance(m_model);
0302: aspectModelInstanceByType.put(aspectDef
0303: .getAspectModel(), aspectModel);
0304: }
0305: // set the model for each aspect info for fast access
0306: AspectModel aspectModel = (AspectModel) aspectModelInstanceByType
0307: .get(aspectDef.getAspectModel());
0308: if (aspectModel == null) {
0309: throw new Error("Could not find AspectModel "
0310: + aspectDef.getAspectModel() + " for "
0311: + m_aspectInfos[i].getAspectQualifiedName());
0312: }
0313: m_aspectInfos[i].setAspectModel(aspectModel);
0314: }
0315:
0316: // keep track of the model instance for fast acccess
0317: m_aspectModels = (AspectModel[]) aspectModelInstanceByType
0318: .values().toArray(new AspectModel[] {});
0319: }
0320:
0321: /**
0322: * Returns the join point interface class name.
0323: *
0324: * @return
0325: */
0326: private String getJoinPointInterface() {
0327: String joinPointInterface;
0328: if (m_requiresProceedMethod || m_requiresJoinPoint) {
0329: joinPointInterface = JOIN_POINT_CLASS_NAME;
0330: } else {
0331: joinPointInterface = STATIC_JOIN_POINT_CLASS_NAME;
0332: }
0333: return joinPointInterface;
0334: }
0335:
0336: /**
0337: * Retrieves the advice method infos.
0338: *
0339: * @param aspectInfoByQualifiedName populated
0340: * @param adviceInfos
0341: * @return
0342: */
0343: private AdviceMethodInfo[] getAdviceMethodInfos(
0344: final Map aspectInfoByQualifiedName,
0345: final AdviceInfo[] adviceInfos) {
0346: List adviceMethodInfosSet = new ArrayList();
0347: for (int i = 0; i < adviceInfos.length; i++) {
0348: AdviceInfo adviceInfo = adviceInfos[i];
0349:
0350: // if we have a perinstance deployed aspect and a static member CALLER -> skip and go on
0351: DeploymentModel deploymentModel = adviceInfo
0352: .getAspectDeploymentModel();
0353:
0354: if (requiresCallerInstance(deploymentModel)
0355: && Modifier.isStatic(m_callerMethodModifiers)) {
0356: continue;
0357: }
0358: if (requiresCalleeInstance(deploymentModel)
0359: && Modifier.isStatic(m_calleeMemberModifiers)) {
0360: continue;
0361: }
0362:
0363: final String aspectClassName = adviceInfo
0364: .getAspectClassName().replace('.', '/');
0365:
0366: final AspectInfo aspectInfo;
0367: if (!aspectInfoByQualifiedName.containsKey(adviceInfo
0368: .getAspectQualifiedName())) {
0369: aspectInfo = new AspectInfo(adviceInfo
0370: .getAdviceDefinition().getAspectDefinition(),
0371: ASPECT_FIELD_PREFIX
0372: + (aspectInfoByQualifiedName.size()),
0373: aspectClassName, L + aspectClassName
0374: + SEMICOLON);
0375: aspectInfoByQualifiedName.put(adviceInfo
0376: .getAspectQualifiedName(), aspectInfo);
0377: } else {
0378: aspectInfo = (AspectInfo) aspectInfoByQualifiedName
0379: .get(adviceInfo.getAspectQualifiedName());
0380: }
0381:
0382: AdviceMethodInfo adviceMethodInfo = new AdviceMethodInfo(
0383: aspectInfo, adviceInfo, m_callerClassSignature,
0384: m_calleeClassSignature, m_joinPointClassName,
0385: m_calleeMemberDesc);
0386: adviceMethodInfosSet.add(adviceMethodInfo);
0387: }
0388: return (AdviceMethodInfo[]) adviceMethodInfosSet
0389: .toArray(new AdviceMethodInfo[adviceMethodInfosSet
0390: .size()]);
0391: }
0392:
0393: /**
0394: * Creates join point specific fields.
0395: */
0396: protected abstract void createJoinPointSpecificFields();
0397:
0398: /**
0399: * Creates the signature for the join point.
0400: *
0401: * @param cv
0402: */
0403: protected abstract void createSignature(final MethodVisitor cv);
0404:
0405: /**
0406: * Optimized implementation that does not retrieve the parameters from the join point instance but is passed
0407: * directly to the method from the input parameters in the 'invoke' method. Can only be used if no around advice
0408: * exists.
0409: *
0410: * @param cv
0411: * @param input
0412: */
0413: protected abstract void createInlinedJoinPointInvocation(
0414: final MethodVisitor cv, final CompilerInput input);
0415:
0416: /**
0417: * Creates a call to the target join point, the parameter(s) to the join point are retrieved from the invocation
0418: * local join point instance.
0419: *
0420: * @param cv
0421: */
0422: protected abstract void createJoinPointInvocation(
0423: final MethodVisitor cv);
0424:
0425: /**
0426: * Returns the join points return type.
0427: *
0428: * @return
0429: */
0430: protected abstract Type getJoinPointReturnType();
0431:
0432: /**
0433: * Returns the join points argument type(s).
0434: *
0435: * @return
0436: */
0437: protected abstract Type[] getJoinPointArgumentTypes();
0438:
0439: /**
0440: * Creates the getRtti method
0441: */
0442: protected abstract void createGetRttiMethod();
0443:
0444: /**
0445: * Creates the getSignature method
0446: */
0447: protected abstract void createGetSignatureMethod();
0448:
0449: /**
0450: * Compiles a join point class, one specific class for each distinct join point. The compiled join point class
0451: * inherits the base join point class.
0452: *
0453: * @return the generated, compiled and loaded join point class
0454: */
0455: public final byte[] compile() {
0456: try {
0457: createClassHeader();
0458: createFieldsCommonToAllJoinPoints();
0459: createJoinPointSpecificFields();
0460: createMandatoryMethodInAspectModels();
0461: createStaticInitializer();
0462: createClinit();
0463: createInit();
0464: createUtilityMethods();
0465: createGetSignatureMethod();
0466: createInvokeMethod();
0467: if (m_requiresProceedMethod) {
0468: // prepare a new CompilerInput since jp index changes when in proceed()
0469: createProceedMethod(m_input.getCopyForProceed());
0470: }
0471: if (m_requiresJoinPoint) {
0472: createGetRttiMethod();
0473: }
0474: m_cw.visitEnd();
0475:
0476: if (DUMP_JP_CLASSES) {
0477: AsmHelper.dumpClass(Properties.DUMP_DIR_CLOSURES,
0478: m_joinPointClassName, m_cw);
0479: }
0480: return m_cw.toByteArray();
0481:
0482: } catch (Exception e) {
0483: e.printStackTrace();
0484: StringBuffer buf = new StringBuffer();
0485: buf
0486: .append("could not compile join point instance for join point with hash [");
0487: buf.append(m_joinPointHash);
0488: buf.append("] and declaring class [");
0489: buf.append(m_callerClassName);
0490: buf.append("] due to: ");
0491: if (e instanceof InvocationTargetException) {
0492: buf.append(((InvocationTargetException) e)
0493: .getTargetException().toString());
0494: } else {
0495: buf.append(e.toString());
0496: }
0497: throw new RuntimeException(buf.toString());
0498: }
0499: }
0500:
0501: /**
0502: * Creates join point specific fields.
0503: */
0504: private void createFieldsCommonToAllJoinPoints() {
0505: if (m_returnType.getSort() != Type.VOID) {
0506: m_cw.visitField(ACC_PRIVATE, RETURN_VALUE_FIELD_NAME,
0507: m_returnType.getDescriptor(), null, null);
0508: }
0509: m_cw.visitField(ACC_PRIVATE + ACC_STATIC,
0510: TARGET_CLASS_FIELD_NAME_IN_JP, CLASS_CLASS_SIGNATURE,
0511: null, null);
0512:
0513: m_cw.visitField(ACC_PRIVATE + ACC_STATIC + ACC_FINAL,
0514: THIS_CLASS_FIELD_NAME_IN_JP, CLASS_CLASS_SIGNATURE,
0515: null, null);
0516:
0517: m_cw.visitField(ACC_PRIVATE + ACC_STATIC + ACC_FINAL,
0518: ENCLOSING_SJP_FIELD_NAME,
0519: ENCLOSING_SJP_FIELD_CLASS_SIGNATURE, null, null);
0520:
0521: m_cw.visitField(ACC_PRIVATE + ACC_STATIC, META_DATA_FIELD_NAME,
0522: MAP_CLASS_SIGNATURE, null, null);
0523: m_cw.visitField(ACC_PRIVATE + ACC_STATIC,
0524: OPTIMIZED_JOIN_POINT_INSTANCE_FIELD_NAME, L
0525: + m_joinPointClassName + SEMICOLON, null, null);
0526: m_cw.visitField(ACC_PRIVATE, CALLEE_INSTANCE_FIELD_NAME,
0527: m_calleeClassSignature, null, null);
0528: m_cw.visitField(ACC_PRIVATE, CALLER_INSTANCE_FIELD_NAME,
0529: m_callerClassSignature, null, null);
0530: m_cw.visitField(ACC_PRIVATE, STACK_FRAME_COUNTER_FIELD_NAME, I,
0531: null, null);
0532:
0533: if (m_isThisAdvisable) {
0534: m_cw.visitField(ACC_PRIVATE, INTERCEPTOR_INDEX_FIELD_NAME,
0535: I, null, null);
0536:
0537: m_cw.visitField(ACC_PRIVATE,
0538: AROUND_INTERCEPTORS_FIELD_NAME,
0539: AROUND_ADVICE_ARRAY_CLASS_SIGNATURE, null, null);
0540: m_cw
0541: .visitField(ACC_PRIVATE,
0542: NR_OF_AROUND_INTERCEPTORS_FIELD_NAME, I,
0543: null, null);
0544:
0545: m_cw.visitField(ACC_PRIVATE,
0546: BEFORE_INTERCEPTORS_FIELD_NAME,
0547: BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE, null, null);
0548: m_cw
0549: .visitField(ACC_PRIVATE,
0550: NR_OF_BEFORE_INTERCEPTORS_FIELD_NAME, I,
0551: null, null);
0552:
0553: m_cw.visitField(ACC_PRIVATE, AFTER_INTERCEPTORS_FIELD_NAME,
0554: AFTER_ADVICE_ARRAY_CLASS_SIGNATURE, null, null);
0555: m_cw.visitField(ACC_PRIVATE,
0556: NR_OF_AFTER_INTERCEPTORS_FIELD_NAME, I, null, null);
0557:
0558: m_cw.visitField(ACC_PRIVATE,
0559: AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
0560: AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE, null,
0561: null);
0562: m_cw.visitField(ACC_PRIVATE,
0563: NR_OF_AFTER_RETURNING_INTERCEPTORS_FIELD_NAME, I,
0564: null, null);
0565:
0566: m_cw.visitField(ACC_PRIVATE,
0567: AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
0568: AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE, null,
0569: null);
0570: m_cw.visitField(ACC_PRIVATE,
0571: NR_OF_AFTER_THROWING_INTERCEPTORS_FIELD_NAME, I,
0572: null, null);
0573: }
0574: }
0575:
0576: /**
0577: * Creates the clinit method for the join point.
0578: */
0579: private void createClinit() {
0580: MethodVisitor cv = m_cw.visitMethod(ACC_STATIC,
0581: CLINIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE,
0582: null, null);
0583: cv.visitMethodInsn(INVOKESTATIC, m_joinPointClassName,
0584: STATIC_INITIALIZATION_METHOD_NAME,
0585: NO_PARAM_RETURN_VOID_SIGNATURE);
0586: cv.visitInsn(RETURN);
0587: cv.visitMaxs(0, 0);
0588: }
0589:
0590: /**
0591: * Creates the init method for the join point.
0592: */
0593: private void createInit() {
0594: MethodVisitor cv = m_cw.visitMethod(ACC_PRIVATE,
0595: INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE, null,
0596: null);
0597: cv.visitVarInsn(ALOAD, 0);
0598:
0599: boolean hasAroundClosureBaseClass = false;
0600: AspectModel aspectModel = null;
0601:
0602: for (int i = 0; i < m_aspectModels.length; i++) {
0603: aspectModel = m_aspectModels[i];
0604: if (aspectModel.getAroundClosureClassInfo()
0605: .getSuperClassName() != null
0606: && !OBJECT_CLASS_NAME.equals(aspectModel
0607: .getAroundClosureClassInfo()
0608: .getSuperClassName())) {
0609: hasAroundClosureBaseClass = true;
0610: break;
0611: }
0612: }
0613:
0614: if (hasAroundClosureBaseClass) {
0615: // invoke the super class constructor
0616: aspectModel.createInvocationOfAroundClosureSuperClass(cv);
0617: } else {
0618: // invoke the constructor of java.lang.Object
0619: cv.visitMethodInsn(INVOKESPECIAL, OBJECT_CLASS_NAME,
0620: INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE);
0621: }
0622:
0623: resetStackFrameCounter(cv);
0624:
0625: cv.visitInsn(RETURN);
0626: cv.visitMaxs(0, 0);
0627: }
0628:
0629: /**
0630: * Creates the class header for the join point.
0631: */
0632: private void createClassHeader() {
0633:
0634: Set interfaces = new HashSet();
0635: String baseClass = OBJECT_CLASS_NAME;
0636:
0637: // getDefault the different aspect models required interfaces
0638: for (int i = 0; i < m_aspectModels.length; i++) {
0639: AspectModel aspectModel = m_aspectModels[i];
0640: AspectModel.AroundClosureClassInfo closureClassInfo = aspectModel
0641: .getAroundClosureClassInfo();
0642: final String super ClassName = closureClassInfo
0643: .getSuperClassName();
0644: final String[] interfaceNames = closureClassInfo
0645: .getInterfaceNames();
0646: if (super ClassName != null) {
0647: if (!baseClass.equals(OBJECT_CLASS_NAME)) {
0648: throw new RuntimeException(
0649: "compiled join point can only subclass one around closure base class but more than registered aspect model requires a closure base class");
0650: }
0651: baseClass = super ClassName;
0652: }
0653: if (interfaceNames.length != 0) {
0654: for (int j = 0; j < interfaceNames.length; j++) {
0655: interfaces.add(interfaceNames[j]);
0656: }
0657: }
0658: }
0659:
0660: int i = 1;
0661: String[] interfaceArr = new String[interfaces.size() + 1];
0662: interfaceArr[0] = getJoinPointInterface();
0663: for (Iterator it = interfaces.iterator(); it.hasNext(); i++) {
0664: interfaceArr[i] = (String) it.next();
0665: }
0666:
0667: m_cw.visit(AsmHelper.JAVA_VERSION, ACC_PUBLIC + ACC_SUPER,
0668: m_joinPointClassName, null, baseClass, interfaceArr);
0669: }
0670:
0671: /**
0672: * Creates the methods that are mandatory methods in the around closure in the different aspect models.
0673: */
0674: private void createMandatoryMethodInAspectModels() {
0675: for (int i = 0; i < m_aspectModels.length; i++) {
0676: m_aspectModels[i].createMandatoryMethods(m_cw, this );
0677: }
0678: }
0679:
0680: /**
0681: * Creates the static initialization method (not clinit) for the join point.
0682: */
0683: private void createStaticInitializer() {
0684: MethodVisitor cv = m_cw.visitMethod(ACC_STATIC | ACC_PUBLIC,
0685: STATIC_INITIALIZATION_METHOD_NAME,
0686: NO_PARAM_RETURN_VOID_SIGNATURE, null, null);
0687:
0688: Label tryLabel = new Label();
0689: cv.visitLabel(tryLabel);
0690: cv.visitLdcInsn(m_calleeClassName.replace('/', '.'));
0691: cv.visitMethodInsn(INVOKESTATIC, CLASS_CLASS,
0692: FOR_NAME_METHOD_NAME, FOR_NAME_METHOD_SIGNATURE);
0693: cv.visitFieldInsn(PUTSTATIC, m_joinPointClassName,
0694: TARGET_CLASS_FIELD_NAME_IN_JP, CLASS_CLASS_SIGNATURE);
0695:
0696: cv.visitLdcInsn(m_callerClassName.replace('/', '.'));
0697: cv.visitMethodInsn(INVOKESTATIC, CLASS_CLASS,
0698: FOR_NAME_METHOD_NAME, FOR_NAME_METHOD_SIGNATURE);
0699: cv.visitFieldInsn(PUTSTATIC, m_joinPointClassName,
0700: THIS_CLASS_FIELD_NAME_IN_JP, CLASS_CLASS_SIGNATURE);
0701:
0702: Label finallyLabel = new Label();
0703: cv.visitLabel(finallyLabel);
0704:
0705: Label gotoFinallyLabel = new Label();
0706: cv.visitJumpInsn(GOTO, gotoFinallyLabel);
0707:
0708: Label catchLabel = new Label();
0709: cv.visitLabel(catchLabel);
0710: cv.visitVarInsn(ASTORE, 0);
0711:
0712: cv.visitVarInsn(ALOAD, 0);
0713: cv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Throwable",
0714: "printStackTrace", "()V");
0715:
0716: cv.visitTypeInsn(NEW, RUNTIME_EXCEPTION_CLASS_NAME);
0717: cv.visitInsn(DUP);
0718: cv
0719: .visitLdcInsn("could not load target class using Class.forName() in generated join point base class "
0720: + m_joinPointClassName);
0721:
0722: cv.visitMethodInsn(INVOKESPECIAL, RUNTIME_EXCEPTION_CLASS_NAME,
0723: INIT_METHOD_NAME,
0724: RUNTIME_EXCEPTION_INIT_METHOD_SIGNATURE);
0725:
0726: cv.visitInsn(ATHROW);
0727: cv.visitLabel(gotoFinallyLabel);
0728:
0729: // create the enclosing static joinpoint
0730: createEnclosingStaticJoinPoint(cv);
0731:
0732: // create the metadata map
0733: cv.visitTypeInsn(NEW, HASH_MAP_CLASS_NAME);
0734: cv.visitInsn(DUP);
0735: cv.visitMethodInsn(INVOKESPECIAL, HASH_MAP_CLASS_NAME,
0736: INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE);
0737: cv.visitFieldInsn(PUTSTATIC, m_joinPointClassName,
0738: META_DATA_FIELD_NAME, MAP_CLASS_SIGNATURE);
0739:
0740: // create the Signature instance
0741: createSignature(cv);
0742:
0743: // create the static JoinPoint instance
0744: cv.visitTypeInsn(NEW, m_joinPointClassName);
0745: cv.visitInsn(DUP);
0746: cv.visitMethodInsn(INVOKESPECIAL, m_joinPointClassName,
0747: INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE);
0748: cv.visitFieldInsn(PUTSTATIC, m_joinPointClassName,
0749: OPTIMIZED_JOIN_POINT_INSTANCE_FIELD_NAME, L
0750: + m_joinPointClassName + SEMICOLON);
0751:
0752: // ensure aspect factories are all loaded
0753: for (int i = 0; i < m_aspectInfos.length; i++) {
0754: AspectInfo m_aspectInfo = m_aspectInfos[i];
0755:
0756: cv.visitLdcInsn(m_aspectInfo.getAspectFactoryClassName());
0757: cv.visitLdcInsn(m_aspectInfo.getAspectDefinition()
0758: .getSystemDefinition().getUuid());
0759: cv.visitLdcInsn(m_aspectInfo.getAspectClassName());
0760: cv.visitLdcInsn(m_aspectInfo.getAspectQualifiedName());
0761: AsmHelper.loadStringConstant(cv, m_aspectInfo
0762: .getAspectDefinition().getContainerClassName());
0763: //TODO AVF do it once per aspect def
0764: StringBuffer sb = new StringBuffer();
0765: boolean hasOne = false;
0766: boolean isFirst = true;
0767: for (Iterator iterator = m_aspectInfo.getAspectDefinition()
0768: .getParameters().entrySet().iterator(); iterator
0769: .hasNext();) {
0770: Map.Entry entry = (Map.Entry) iterator.next();
0771: if (!isFirst) {
0772: sb.append(DELIMITER);
0773: }
0774: isFirst = false;
0775: hasOne = true;
0776: sb.append(entry.getKey()).append(DELIMITER).append(
0777: entry.getValue());
0778: }
0779: if (hasOne) {
0780: cv.visitLdcInsn(sb.toString());
0781: } else {
0782: cv.visitInsn(ACONST_NULL);
0783: }
0784: cv.visitFieldInsn(GETSTATIC, m_joinPointClassName,
0785: THIS_CLASS_FIELD_NAME_IN_JP, CLASS_CLASS_SIGNATURE);
0786: cv.visitMethodInsn(INVOKEVIRTUAL, CLASS_CLASS,
0787: GETCLASSLOADER_METHOD_NAME,
0788: CLASS_CLASS_GETCLASSLOADER_METHOD_SIGNATURE);
0789: cv.visitLdcInsn(m_aspectInfo.getDeploymentModel()
0790: .toString());
0791: cv
0792: .visitMethodInsn(
0793: INVOKESTATIC,
0794: Type
0795: .getInternalName(AspectFactoryManager.class),
0796: "loadAspectFactory",
0797: "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/lang/String;)V");
0798: }
0799:
0800: // create and initialize the aspect fields
0801: for (int i = 0; i < m_aspectInfos.length; i++) {
0802: m_aspectInfos[i].getAspectModel()
0803: .createAndStoreStaticAspectInstantiation(m_cw, cv,
0804: m_aspectInfos[i], m_joinPointClassName);
0805: }
0806:
0807: cv.visitInsn(RETURN);
0808: cv.visitTryCatchBlock(tryLabel, finallyLabel, catchLabel,
0809: CLASS_NOT_FOUND_EXCEPTION_CLASS_NAME);
0810: cv.visitMaxs(0, 0);
0811: }
0812:
0813: /**
0814: * Add and initialize the static field for enclosing joint point static part
0815: *
0816: * @param cv
0817: */
0818: private void createEnclosingStaticJoinPoint(MethodVisitor cv) {
0819: cv.visitFieldInsn(GETSTATIC, m_joinPointClassName,
0820: THIS_CLASS_FIELD_NAME_IN_JP, CLASS_CLASS_SIGNATURE);
0821: cv.visitLdcInsn(m_callerMethodName);
0822: cv.visitLdcInsn(m_callerMethodDesc);
0823:
0824: cv.visitMethodInsn(INVOKESTATIC, SIGNATURE_FACTORY_CLASS,
0825: NEW_ENCLOSING_SJP_METHOD_NAME,
0826: NEW_ENCLOSING_SJP_METHOD_SIGNATURE);
0827: cv.visitFieldInsn(PUTSTATIC, m_joinPointClassName,
0828: ENCLOSING_SJP_FIELD_NAME,
0829: ENCLOSING_SJP_FIELD_CLASS_SIGNATURE);
0830: }
0831:
0832: /**
0833: * Creates the 'invoke' method. If possible delegates to the target join point directly, e.g. does not invoke the
0834: * 'proceed' method (Used when a join point has zero around advice).
0835: * <p/>
0836: * The implementation here is suitable for regular JP but not for delegating JP upon hotswap
0837: */
0838: protected void createInvokeMethod() {
0839:
0840: final String invokeDesc = buildInvokeMethodSignature();
0841:
0842: // create the method
0843: MethodVisitor cv = m_cw.visitMethod(ACC_PUBLIC + ACC_FINAL
0844: + ACC_STATIC, INVOKE_METHOD_NAME, invokeDesc, null,
0845: new String[] { THROWABLE_CLASS_NAME });
0846:
0847: if (!m_input.isOptimizedJoinPoint) {
0848: // create a new JP and makes use of it
0849: createInvocationLocalJoinPointInstance(cv, m_input);
0850: }
0851:
0852: //FIXME: see loadAspect and AssociationScopeTest_2_1456425365_738_9001546___AW_JoinPoint f.e.
0853: // there is redundant checks because
0854: // the system perObject aspect for a perX aspect will be called *AFTER* the initializeInstanceLevelAspects
0855: // and thus the aspects.hasAspect will change in the middle of the invoke method
0856: //
0857: // flow should be: invoke perObject before aspect, init instance level, invoke all other before aspects
0858: // we can wether have a createBeforeBefore(...) that checks for this perObject aspect
0859:
0860: // initialize the instance level aspects (perInstance)
0861: initializeInstanceLevelAspects(cv, m_input);
0862:
0863: // before advices
0864: createBeforeAdviceInvocations(cv, m_input);
0865:
0866: // handle different combinations of after advice (finally/throwing/returning)
0867: if (m_afterFinallyAdviceMethodInfos.length == 0
0868: && m_afterThrowingAdviceMethodInfos.length == 0
0869: && !m_isThisAdvisable) {
0870: createPartOfInvokeMethodWithoutAfterFinallyAndAfterThrowingAdviceTypes(
0871: cv, m_input);
0872: } else if (m_afterThrowingAdviceMethodInfos.length == 0
0873: && !m_isThisAdvisable) {
0874: createPartOfInvokeMethodWithoutAfterThrowingAdviceTypes(cv,
0875: m_input);
0876: } else {
0877: createPartOfInvokeMethodWithAllAdviceTypes(cv, m_input);
0878: }
0879:
0880: cv.visitMaxs(0, 0);
0881: }
0882:
0883: /**
0884: * Initializes instance level aspects, retrieves them from the target instance through the
0885: * <code>HasInstanceLevelAspect</code> interfaces.
0886: * <p/>
0887: * Use by 'perInstance', 'perThis' and 'perTarget' deployment models.
0888: *
0889: * @param cv
0890: * @param input
0891: */
0892: private void initializeInstanceLevelAspects(final MethodVisitor cv,
0893: final CompilerInput input) {
0894: for (int i = 0; i < m_aspectInfos.length; i++) {
0895: m_aspectInfos[i].getAspectModel()
0896: .createAndStoreRuntimeAspectInstantiation(cv,
0897: input, m_aspectInfos[i]);
0898: }
0899: }
0900:
0901: /**
0902: * @param cv
0903: * @param input
0904: */
0905: private void createPartOfInvokeMethodWithAllAdviceTypes(
0906: final MethodVisitor cv, final CompilerInput input) {
0907: final int returnValueIndex = (input.joinPointInstanceIndex != INDEX_NOTAVAILABLE) ? (input.joinPointInstanceIndex + 1)
0908: : input.callerIndex + 1;
0909: final int exceptionIndex1 = returnValueIndex + 1;
0910: final int exceptionIndex2 = returnValueIndex + 2;
0911:
0912: cv.visitInsn(ACONST_NULL);
0913: cv.visitVarInsn(ASTORE, returnValueIndex);
0914:
0915: Label tryLabel = new Label();
0916: cv.visitLabel(tryLabel);
0917: if (!m_requiresProceedMethod) {
0918: // if no around advice then optimize by invoking the target JP directly and no call to proceed()
0919: createInlinedJoinPointInvocation(cv, input);
0920: int stackIndex = returnValueIndex;//use another int since storeType will update it
0921: AsmHelper.storeType(cv, stackIndex, m_returnType);
0922: addReturnedValueToJoinPoint(cv, input, returnValueIndex,
0923: false);
0924: } else {
0925: createInvocationToProceedMethod(cv,
0926: input.joinPointInstanceIndex, returnValueIndex);
0927: }
0928:
0929: createAfterReturningAdviceInvocations(cv, input);
0930:
0931: Label finallyLabel1 = new Label();
0932: cv.visitLabel(finallyLabel1);
0933:
0934: if (m_isThisAdvisable) {
0935: final int registerDepth = input.callerIndex + 2; // caller is using last register + possible return value
0936: createAfterInterceptorInvocations(cv,
0937: input.joinPointInstanceIndex, registerDepth);
0938: }
0939: createAfterFinallyAdviceInvocations(cv, input);
0940:
0941: Label gotoFinallyLabel = new Label();
0942: cv.visitJumpInsn(GOTO, gotoFinallyLabel);
0943:
0944: Label catchLabel = new Label();
0945: cv.visitLabel(catchLabel);
0946:
0947: // store the exception
0948: cv.visitVarInsn(ASTORE, exceptionIndex1);
0949:
0950: if (m_isThisAdvisable) {
0951: createAfterThrowingInterceptorInvocations(cv,
0952: input.joinPointInstanceIndex, exceptionIndex1);
0953: }
0954:
0955: // loop over the after throwing advices
0956: for (int i = m_afterThrowingAdviceMethodInfos.length - 1; i >= 0; i--) {
0957: AdviceMethodInfo advice = m_afterThrowingAdviceMethodInfos[i];
0958:
0959: // set the exception argument index
0960: advice.setSpecialArgumentIndex(exceptionIndex1);
0961:
0962: // if (e instanceof TYPE) {...}
0963: cv.visitVarInsn(ALOAD, exceptionIndex1);
0964:
0965: final String specialArgTypeName = advice
0966: .getSpecialArgumentTypeName();
0967: if (specialArgTypeName != null) {
0968: // after throwing <TYPE>
0969: cv.visitTypeInsn(INSTANCEOF, specialArgTypeName);
0970:
0971: Label ifInstanceOfLabel = new Label();
0972: cv.visitJumpInsn(IFEQ, ifInstanceOfLabel);
0973:
0974: // after throwing advice invocation
0975: createAfterAdviceInvocation(cv, input, advice,
0976: exceptionIndex1);
0977:
0978: cv.visitLabel(ifInstanceOfLabel);
0979: } else {
0980: // after throwing
0981: createAfterAdviceInvocation(cv, input, advice,
0982: INDEX_NOTAVAILABLE);
0983: }
0984: }
0985:
0986: // rethrow exception
0987: cv.visitVarInsn(ALOAD, exceptionIndex1);
0988: cv.visitInsn(ATHROW);
0989:
0990: // store exception
0991: Label exceptionLabel = new Label();
0992: cv.visitLabel(exceptionLabel);
0993: cv.visitVarInsn(ASTORE, exceptionIndex2);
0994:
0995: // after finally advice invocation
0996: Label finallyLabel2 = new Label();
0997: cv.visitLabel(finallyLabel2);
0998:
0999: if (m_isThisAdvisable) {
1000: final int registerDepth = input.callerIndex + 2; // caller is using last register + possible return value
1001: createAfterInterceptorInvocations(cv,
1002: input.joinPointInstanceIndex, registerDepth);
1003: }
1004: createAfterFinallyAdviceInvocations(cv, input);
1005:
1006: // rethrow exception
1007: cv.visitVarInsn(ALOAD, exceptionIndex2);
1008: cv.visitInsn(ATHROW);
1009: cv.visitLabel(gotoFinallyLabel);
1010:
1011: // unwrap if around advice and return in all cases
1012: if (m_returnType.getSort() != Type.VOID) {
1013: if (m_requiresProceedMethod) {
1014: cv.visitVarInsn(ALOAD, returnValueIndex);
1015: AsmHelper.unwrapType(cv, m_returnType);
1016: } else {
1017: AsmHelper.loadType(cv, returnValueIndex, m_returnType);
1018: }
1019: }
1020:
1021: AsmHelper.addReturnStatement(cv, m_returnType);
1022:
1023: // build up the exception table
1024: cv.visitTryCatchBlock(tryLabel, finallyLabel1, catchLabel,
1025: THROWABLE_CLASS_NAME);
1026: cv.visitTryCatchBlock(tryLabel, finallyLabel1, exceptionLabel,
1027: null);
1028: cv.visitTryCatchBlock(catchLabel, finallyLabel2,
1029: exceptionLabel, null);
1030: }
1031:
1032: /**
1033: * @param cv
1034: * @param input
1035: */
1036: private void createPartOfInvokeMethodWithoutAfterThrowingAdviceTypes(
1037: final MethodVisitor cv, final CompilerInput input) {
1038: final int returnValueIndex = (input.joinPointInstanceIndex != INDEX_NOTAVAILABLE) ? (input.joinPointInstanceIndex + 1)
1039: : input.callerIndex + 1;
1040: final int exceptionIndex = returnValueIndex + 1;
1041:
1042: cv.visitInsn(ACONST_NULL);
1043: cv.visitVarInsn(ASTORE, returnValueIndex);
1044:
1045: Label tryLabel = new Label();
1046: cv.visitLabel(tryLabel);
1047: if (!m_requiresProceedMethod) {
1048: // if no around advice then optimize by invoking the target JP directly and no call to proceed()
1049: createInlinedJoinPointInvocation(cv, input);
1050: int stackIndex = returnValueIndex;//use another int since storeType will update it
1051: AsmHelper.storeType(cv, stackIndex, m_returnType);
1052: addReturnedValueToJoinPoint(cv, input, returnValueIndex,
1053: false);
1054: } else {
1055: createInvocationToProceedMethod(cv,
1056: input.joinPointInstanceIndex, returnValueIndex);
1057: }
1058:
1059: createAfterReturningAdviceInvocations(cv, input);
1060:
1061: Label finallyLabel1 = new Label();
1062: cv.visitLabel(finallyLabel1);
1063:
1064: createAfterFinallyAdviceInvocations(cv, input);
1065:
1066: Label gotoFinallyLabel = new Label();
1067: cv.visitJumpInsn(GOTO, gotoFinallyLabel);
1068:
1069: Label exceptionLabel = new Label();
1070: cv.visitLabel(exceptionLabel);
1071: cv.visitVarInsn(ASTORE, exceptionIndex);
1072:
1073: Label finallyLabel2 = new Label();
1074: cv.visitLabel(finallyLabel2);
1075:
1076: createAfterFinallyAdviceInvocations(cv, input);
1077:
1078: cv.visitVarInsn(ALOAD, exceptionIndex);
1079: cv.visitInsn(ATHROW);
1080:
1081: cv.visitLabel(gotoFinallyLabel);
1082:
1083: // unwrap if around advice and return in all cases
1084: if (m_returnType.getSort() != Type.VOID) {
1085: if (m_requiresProceedMethod) {
1086: cv.visitVarInsn(ALOAD, returnValueIndex);
1087: AsmHelper.unwrapType(cv, m_returnType);
1088: } else {
1089: AsmHelper.loadType(cv, returnValueIndex, m_returnType);
1090: }
1091: }
1092:
1093: AsmHelper.addReturnStatement(cv, m_returnType);
1094:
1095: cv.visitTryCatchBlock(tryLabel, finallyLabel1, exceptionLabel,
1096: null);
1097: cv.visitTryCatchBlock(exceptionLabel, finallyLabel2,
1098: exceptionLabel, null);
1099: }
1100:
1101: /**
1102: * @param cv
1103: * @param input
1104: */
1105: private void createPartOfInvokeMethodWithoutAfterFinallyAndAfterThrowingAdviceTypes(
1106: final MethodVisitor cv, final CompilerInput input) {
1107:
1108: final int returnValueIndex = (input.joinPointInstanceIndex != INDEX_NOTAVAILABLE) ? (input.joinPointInstanceIndex + 1)
1109: : input.callerIndex + 1;
1110: if (!m_requiresProceedMethod) {
1111: // if no around advice then optimize by invoking the target JP directly and no call to proceed()
1112: createInlinedJoinPointInvocation(cv, input);
1113: int stackIndex = returnValueIndex;//use another int since storeType will update it
1114: AsmHelper.storeType(cv, stackIndex, m_returnType);
1115: addReturnedValueToJoinPoint(cv, input, returnValueIndex,
1116: false);
1117: } else {
1118: createInvocationToProceedMethod(cv,
1119: input.joinPointInstanceIndex, returnValueIndex);
1120: }
1121:
1122: // after returning advice invocations
1123: createAfterReturningAdviceInvocations(cv, input);
1124:
1125: // unwrap if around advice and return in all cases
1126: if (m_returnType.getSort() != Type.VOID) {
1127: if (m_requiresProceedMethod) {
1128: cv.visitVarInsn(ALOAD, returnValueIndex);
1129: AsmHelper.unwrapType(cv, m_returnType);
1130: } else {
1131: AsmHelper.loadType(cv, returnValueIndex, m_returnType);
1132: }
1133: }
1134:
1135: AsmHelper.addReturnStatement(cv, m_returnType);
1136: }
1137:
1138: /**
1139: * Creates an invocation to the proceed method.
1140: *
1141: * @param cv
1142: * @param joinPointInstanceIndex
1143: * @param returnValueIndex
1144: */
1145: private void createInvocationToProceedMethod(
1146: final MethodVisitor cv, final int joinPointInstanceIndex,
1147: final int returnValueIndex) {
1148: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
1149: cv.visitMethodInsn(INVOKEVIRTUAL, m_joinPointClassName,
1150: PROCEED_METHOD_NAME, PROCEED_METHOD_SIGNATURE);
1151: cv.visitVarInsn(ASTORE, returnValueIndex);
1152: }
1153:
1154: /**
1155: * Creates an "invocation local" join point instance, e.g. one join point per invocation. Needed for thread-safety
1156: * when invoking around advice.
1157: *
1158: * @param cv
1159: * @param input
1160: */
1161: private void createInvocationLocalJoinPointInstance(
1162: final MethodVisitor cv, final CompilerInput input) {
1163: // create the join point instance
1164: cv.visitTypeInsn(NEW, m_joinPointClassName);
1165: cv.visitInsn(DUP);
1166: cv.visitMethodInsn(INVOKESPECIAL, m_joinPointClassName,
1167: INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE);
1168:
1169: // store the jp on the stack
1170: cv.visitVarInsn(ASTORE, input.joinPointInstanceIndex);
1171:
1172: // set the argument fields in the join point instance (jp.m_arg<i> = <arg_i>)
1173: int argStackIndex = input.argStartIndex;
1174: for (int i = 0; i < m_fieldNames.length; i++) {
1175: String fieldName = m_fieldNames[i];
1176: cv.visitVarInsn(ALOAD, input.joinPointInstanceIndex);
1177: Type type = m_argumentTypes[i];
1178: argStackIndex = AsmHelper.loadType(cv, argStackIndex, type);
1179: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
1180: fieldName, type.getDescriptor());
1181: }
1182:
1183: // caller (can be assigned to null)
1184: cv.visitVarInsn(ALOAD, input.joinPointInstanceIndex);
1185: cv.visitVarInsn(ALOAD, input.callerIndex);
1186: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
1187: CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
1188:
1189: // callee (can be not available)
1190: cv.visitVarInsn(ALOAD, input.joinPointInstanceIndex);
1191: if (input.calleeIndex != INDEX_NOTAVAILABLE) {
1192: cv.visitVarInsn(ALOAD, 0);
1193: } else {
1194: cv.visitInsn(ACONST_NULL);
1195: }
1196: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
1197: CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
1198:
1199: if (m_isThisAdvisable) {
1200: createInitializationForAdvisableManagement(cv,
1201: input.joinPointInstanceIndex, input.callerIndex);
1202: }
1203: }
1204:
1205: /**
1206: * Create the proceed() method.
1207: *
1208: * @param input a slightly different CompilerInput since jp index, is changed and caller and callee are meaningless
1209: * in the proceed() method.
1210: */
1211: private void createProceedMethod(CompilerInput input) {
1212:
1213: MethodVisitor cv = m_cw.visitMethod(ACC_PUBLIC | ACC_FINAL,
1214: PROCEED_METHOD_NAME, PROCEED_METHOD_SIGNATURE, null,
1215: new String[] { THROWABLE_CLASS_NAME });
1216:
1217: if (m_isThisAdvisable) {
1218: createAroundInterceptorInvocations(cv);
1219: }
1220:
1221: incrementStackFrameCounter(cv);
1222:
1223: // set up the labels
1224: Label tryLabel = new Label();
1225: Label defaultCaseLabel = new Label();
1226: Label gotoLabel = new Label();
1227: Label handlerLabel = new Label();
1228: Label endLabel = new Label();
1229:
1230: int nrOfCases = m_aroundAdviceMethodInfos.length;
1231: if (m_isThisAdvisable) {
1232: nrOfCases++;
1233: }
1234:
1235: Label[] caseLabels = new Label[nrOfCases];
1236: Label[] returnLabels = new Label[nrOfCases];
1237: int[] caseNumbers = new int[nrOfCases];
1238: for (int i = 0; i < caseLabels.length; i++) {
1239: caseLabels[i] = new Label();
1240: caseNumbers[i] = i;
1241: }
1242: for (int i = 0; i < returnLabels.length; i++) {
1243: returnLabels[i] = new Label();
1244: }
1245:
1246: // start try-catch block
1247: cv.visitLabel(tryLabel);
1248:
1249: // start the switch block and set the stackframe as the param to the switch
1250: cv.visitVarInsn(ALOAD, 0);
1251: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
1252: STACK_FRAME_COUNTER_FIELD_NAME, I);
1253: cv.visitLookupSwitchInsn(defaultCaseLabel, caseNumbers,
1254: caseLabels);
1255:
1256: // add one case for each around advice invocation
1257: for (int i = 0; i < m_aroundAdviceMethodInfos.length; i++) {
1258: cv.visitLabel(caseLabels[i]);
1259:
1260: // gather advice info
1261: AdviceMethodInfo adviceInfo = m_aroundAdviceMethodInfos[i];
1262:
1263: Label endInstanceOflabel = beginRuntimeCheck(cv, input,
1264: adviceInfo.getAdviceInfo());
1265:
1266: // getDefault the aspect instance
1267: adviceInfo.getAspectInfo().getAspectModel().loadAspect(cv,
1268: input, adviceInfo.getAspectInfo());
1269:
1270: // load the arguments to the advice
1271: adviceInfo.getAspectInfo().getAspectModel()
1272: .createAroundAdviceArgumentHandling(cv, input,
1273: m_argumentTypes, adviceInfo);
1274:
1275: // invoke the advice method
1276: cv.visitMethodInsn(INVOKEVIRTUAL, adviceInfo
1277: .getAspectInfo().getAspectClassName(), adviceInfo
1278: .getAdviceInfo().getMethodName(), adviceInfo
1279: .getAdviceInfo().getMethodSignature());
1280: cv.visitVarInsn(ASTORE, 1);
1281:
1282: // we need to handle the case when the advice was skipped due to runtime check
1283: // that is : if (runtimeCheck) { ret = advice() } else { ret = proceed() }
1284: if (endInstanceOflabel != null) {
1285: Label elseInstanceOfLabel = new Label();
1286: cv.visitJumpInsn(GOTO, elseInstanceOfLabel);
1287: endRuntimeCheck(cv, adviceInfo.getAdviceInfo(),
1288: endInstanceOflabel);
1289: cv.visitVarInsn(ALOAD, 0);
1290: cv.visitMethodInsn(INVOKESPECIAL, m_joinPointClassName,
1291: PROCEED_METHOD_NAME, PROCEED_METHOD_SIGNATURE);
1292: cv.visitVarInsn(ASTORE, 1);
1293: cv.visitLabel(elseInstanceOfLabel);
1294: }
1295:
1296: cv.visitLabel(returnLabels[i]);
1297:
1298: cv.visitVarInsn(ALOAD, 1);
1299: cv.visitInsn(ARETURN);
1300: }
1301:
1302: if (m_isThisAdvisable) {
1303: int delegationCaseIndex = caseLabels.length - 1;
1304: cv.visitLabel(caseLabels[delegationCaseIndex]);
1305: cv.visitVarInsn(ALOAD, 0);
1306: cv.visitInsn(ICONST_0);
1307: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
1308: INTERCEPTOR_INDEX_FIELD_NAME, I);
1309: cv.visitVarInsn(ALOAD, 0);
1310: cv.visitMethodInsn(INVOKEVIRTUAL, m_joinPointClassName,
1311: PROCEED_METHOD_NAME, PROCEED_METHOD_SIGNATURE);
1312:
1313: cv.visitLabel(returnLabels[delegationCaseIndex]);
1314:
1315: cv.visitInsn(ARETURN);
1316: }
1317:
1318: // invoke the target join point in the default case
1319: cv.visitLabel(defaultCaseLabel);
1320:
1321: AsmHelper.prepareWrappingOfPrimitiveType(cv, Type
1322: .getReturnType(m_calleeMemberDesc));
1323:
1324: createJoinPointInvocation(cv);
1325:
1326: Type m_returnType = null;
1327: if (m_joinPointType != JoinPointType.CONSTRUCTOR_CALL_INT) {
1328: m_returnType = Type.getReturnType(m_calleeMemberDesc);
1329: } else {
1330: m_returnType = Type.getType(m_calleeClassSignature);
1331: }
1332: AsmHelper.wrapPrimitiveType(cv, m_returnType);
1333: cv.visitVarInsn(ASTORE, 1);
1334:
1335: // store it in Rtti return value
1336: addReturnedValueToJoinPoint(cv, input, 1, true);
1337:
1338: // set it as the CALLEE instance for ctor call - TODO refactor somewhere else
1339: if (m_joinPointType == JoinPointType.CONSTRUCTOR_CALL_INT) {
1340: cv.visitVarInsn(ALOAD, 0);
1341: cv.visitVarInsn(ALOAD, 1);
1342: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
1343: CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
1344: }
1345:
1346: cv.visitLabel(gotoLabel);
1347:
1348: cv.visitVarInsn(ALOAD, 1);
1349: cv.visitInsn(ARETURN);
1350:
1351: // finally clause
1352: cv.visitLabel(handlerLabel);
1353: cv.visitVarInsn(ASTORE, 2);
1354: cv.visitLabel(endLabel);
1355:
1356: cv.visitVarInsn(ALOAD, 2);
1357: cv.visitInsn(ATHROW);
1358:
1359: // set up the label table
1360: cv.visitTryCatchBlock(tryLabel, returnLabels[0], handlerLabel,
1361: null);
1362: for (int i = 1; i < caseLabels.length; i++) {
1363: Label caseLabel = caseLabels[i];
1364: Label returnLabel = returnLabels[i];
1365: cv.visitTryCatchBlock(caseLabel, returnLabel, handlerLabel,
1366: null);
1367: }
1368: cv.visitTryCatchBlock(defaultCaseLabel, gotoLabel,
1369: handlerLabel, null);
1370: cv.visitTryCatchBlock(handlerLabel, endLabel, handlerLabel,
1371: null);
1372: cv.visitMaxs(0, 0);
1373: }
1374:
1375: /**
1376: * Adds before advice invocations.
1377: *
1378: * @param cv
1379: */
1380: private void createBeforeAdviceInvocations(final MethodVisitor cv,
1381: CompilerInput input) {
1382: for (int i = 0; i < m_beforeAdviceMethodInfos.length; i++) {
1383: AdviceMethodInfo adviceMethodInfo = m_beforeAdviceMethodInfos[i];
1384: AspectInfo aspectInfo = adviceMethodInfo.getAspectInfo();
1385:
1386: if (requiresCallerInstance(aspectInfo.getDeploymentModel())
1387: && input.callerIndex < 0) {
1388: continue;
1389: }
1390: if (requiresCalleeInstance(aspectInfo.getDeploymentModel())
1391: && input.calleeIndex < 0) {
1392: continue;
1393: }
1394:
1395: // runtime check for target() etc
1396: Label endInstanceOflabel = beginRuntimeCheck(cv, input,
1397: adviceMethodInfo.getAdviceInfo());
1398:
1399: //getDefault the aspect instance
1400: final AspectModel aspectModel = adviceMethodInfo
1401: .getAspectInfo().getAspectModel();
1402: aspectModel.loadAspect(cv, input, adviceMethodInfo
1403: .getAspectInfo());
1404:
1405: // push any needed arguments for the advice invocation
1406: aspectModel.createBeforeOrAfterAdviceArgumentHandling(cv,
1407: input, m_argumentTypes, adviceMethodInfo,
1408: INDEX_NOTAVAILABLE);
1409:
1410: // invoke the advice
1411: cv.visitMethodInsn(INVOKEVIRTUAL, adviceMethodInfo
1412: .getAspectInfo().getAspectClassName(),
1413: adviceMethodInfo.getAdviceInfo().getMethodName(),
1414: adviceMethodInfo.getAdviceInfo()
1415: .getMethodSignature());
1416:
1417: // end label of runtime checks
1418: endRuntimeCheck(cv, adviceMethodInfo.getAdviceInfo(),
1419: endInstanceOflabel);
1420: }
1421:
1422: if (m_isThisAdvisable) {
1423: createBeforeInterceptorInvocations(cv,
1424: input.joinPointInstanceIndex, input.callerIndex + 1);
1425: }
1426: }
1427:
1428: /**
1429: * Adds after advice invocations.
1430: *
1431: * @param cv
1432: * @param input
1433: */
1434: private void createAfterFinallyAdviceInvocations(
1435: final MethodVisitor cv, final CompilerInput input) {
1436: // add after advice in reverse order
1437: for (int i = m_afterFinallyAdviceMethodInfos.length - 1; i >= 0; i--) {
1438: AdviceMethodInfo advice = m_afterFinallyAdviceMethodInfos[i];
1439: createAfterAdviceInvocation(cv, input, advice,
1440: INDEX_NOTAVAILABLE);
1441: }
1442: }
1443:
1444: /**
1445: * Adds after returning advice invocations.
1446: *
1447: * @param cv
1448: * @param input
1449: */
1450: private void createAfterReturningAdviceInvocations(
1451: final MethodVisitor cv, final CompilerInput input) {
1452: final int returnValueIndex = (input.joinPointInstanceIndex != INDEX_NOTAVAILABLE) ? (input.joinPointInstanceIndex + 1)
1453: : input.callerIndex + 1;
1454:
1455: if (m_isThisAdvisable) {
1456: createAfterReturningInterceptorInvocations(cv,
1457: input.joinPointInstanceIndex, returnValueIndex);
1458: }
1459:
1460: boolean hasPoppedReturnValueFromStack = false;
1461: for (int i = m_afterReturningAdviceMethodInfos.length - 1; i >= 0; i--) {
1462: AdviceMethodInfo advice = m_afterReturningAdviceMethodInfos[i];
1463:
1464: // set the return value index that will be used as arg to advice
1465: advice.setSpecialArgumentIndex(returnValueIndex);
1466:
1467: String specialArgDesc = advice.getSpecialArgumentTypeDesc();
1468: if (specialArgDesc == null) {
1469: // after returning
1470: createAfterAdviceInvocation(cv, input, advice,
1471: INDEX_NOTAVAILABLE);
1472: } else {
1473: // after returning <TYPE>
1474: if (AsmHelper.isPrimitive(m_returnType)) {
1475: if (m_returnType.getDescriptor().equals(
1476: specialArgDesc)) {
1477: createAfterAdviceInvocation(cv, input, advice,
1478: returnValueIndex);
1479: }
1480: } else {
1481: cv.visitVarInsn(ALOAD, returnValueIndex);
1482:
1483: cv.visitTypeInsn(INSTANCEOF, advice
1484: .getSpecialArgumentTypeName());
1485:
1486: Label label = new Label();
1487: cv.visitJumpInsn(IFEQ, label);
1488:
1489: createAfterAdviceInvocation(cv, input, advice,
1490: returnValueIndex);
1491:
1492: cv.visitLabel(label);
1493: }
1494: }
1495: }
1496:
1497: // need the return value in return operation
1498: if (!m_requiresProceedMethod && hasPoppedReturnValueFromStack) {
1499: cv.visitVarInsn(ALOAD, returnValueIndex);
1500: }
1501: }
1502:
1503: /**
1504: * Adds a single generic after advice invocation.
1505: *
1506: * @param cv
1507: * @param input
1508: * @param adviceMethodInfo
1509: * @param specialArgIndex for afterReturning / Throwing when binding is used
1510: */
1511: private void createAfterAdviceInvocation(final MethodVisitor cv,
1512: final CompilerInput input,
1513: final AdviceMethodInfo adviceMethodInfo,
1514: final int specialArgIndex) {
1515: AspectInfo aspectInfo = adviceMethodInfo.getAspectInfo();
1516:
1517: if (requiresCallerInstance(aspectInfo.getDeploymentModel())
1518: && input.callerIndex < 0) {
1519: return; // without callER instance we cannot load a PER_THIS aspect instance
1520: }
1521: if (requiresCalleeInstance(aspectInfo.getDeploymentModel())
1522: && input.calleeIndex < 0) {
1523: return;
1524: }
1525: // runtime check for target() etc
1526: Label endInstanceOflabel = beginRuntimeCheck(cv, input,
1527: adviceMethodInfo.getAdviceInfo());
1528:
1529: // getDefault the aspect instance
1530: final AspectModel aspectModel = adviceMethodInfo
1531: .getAspectInfo().getAspectModel();
1532: aspectModel.loadAspect(cv, input, aspectInfo);
1533:
1534: aspectModel.createBeforeOrAfterAdviceArgumentHandling(cv,
1535: input, m_argumentTypes, adviceMethodInfo,
1536: specialArgIndex);
1537:
1538: cv.visitMethodInsn(INVOKEVIRTUAL, adviceMethodInfo
1539: .getAspectInfo().getAspectClassName(), adviceMethodInfo
1540: .getAdviceInfo().getMethodName(), adviceMethodInfo
1541: .getAdviceInfo().getMethodSignature());
1542:
1543: // end label of runtime checks
1544: endRuntimeCheck(cv, adviceMethodInfo.getAdviceInfo(),
1545: endInstanceOflabel);
1546: }
1547:
1548: /**
1549: * Adds the return value to the RETURNED field.
1550: *
1551: * @param cv
1552: * @param input
1553: * @param returnValueIndex
1554: * @param unwrap set to true if already wrapped on the stack (within proceed() code)
1555: */
1556: private void addReturnedValueToJoinPoint(final MethodVisitor cv,
1557: final CompilerInput input, final int returnValueIndex,
1558: final boolean unwrap) {
1559: if (m_requiresJoinPoint && m_returnType.getSort() != Type.VOID) {
1560: if (m_joinPointType == JoinPointType.METHOD_EXECUTION_INT
1561: || m_joinPointType == JoinPointType.METHOD_CALL_INT
1562: || m_joinPointType == JoinPointType.CONSTRUCTOR_CALL_INT) {
1563: //TODO should we do something for field getDefault / set
1564: loadJoinPointInstance(cv, input);
1565: if (unwrap && AsmHelper.isPrimitive(m_returnType)) {
1566: cv.visitVarInsn(ALOAD, returnValueIndex);
1567: AsmHelper.unwrapType(cv, m_returnType);
1568: } else {
1569: AsmHelper.loadType(cv, returnValueIndex,
1570: m_returnType);
1571: }
1572: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
1573: RETURN_VALUE_FIELD_NAME, m_returnType
1574: .getDescriptor());
1575: }
1576: }
1577: }
1578:
1579: /**
1580: * Loads the join point instance, takes static/non-static join point access into account.
1581: *
1582: * @param cv
1583: * @param input
1584: */
1585: public static void loadJoinPointInstance(final MethodVisitor cv,
1586: final CompilerInput input) {
1587: if (input.isOptimizedJoinPoint) {
1588: cv.visitFieldInsn(GETSTATIC, input.joinPointClassName,
1589: OPTIMIZED_JOIN_POINT_INSTANCE_FIELD_NAME, L
1590: + input.joinPointClassName + SEMICOLON);
1591: } else {
1592: cv.visitVarInsn(ALOAD, input.joinPointInstanceIndex);
1593: }
1594: }
1595:
1596: /**
1597: * Loads the argument member fields.
1598: *
1599: * @param cv
1600: * @param argStartIndex
1601: */
1602: protected final void loadArgumentMemberFields(
1603: final MethodVisitor cv, final int argStartIndex) {
1604: int argStackIndex = argStartIndex;
1605: for (int index = 0; index < m_argumentTypes.length; index++) {
1606: Type argumentType = m_argumentTypes[index];
1607: argStackIndex = AsmHelper.loadType(cv, argStackIndex,
1608: argumentType);
1609: }
1610: }
1611:
1612: /**
1613: * Loads the arguments.
1614: *
1615: * @param cv
1616: */
1617: protected final void loadArguments(final MethodVisitor cv) {
1618: for (int i = 0; i < m_fieldNames.length; i++) {
1619: String fieldName = m_fieldNames[i];
1620: Type argumentType = m_argumentTypes[i];
1621: cv.visitVarInsn(ALOAD, 0);
1622: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
1623: fieldName, argumentType.getDescriptor());
1624: }
1625: }
1626:
1627: /**
1628: * Resets the stack frame counter.
1629: *
1630: * @param cv
1631: */
1632: private void resetStackFrameCounter(final MethodVisitor cv) {
1633: cv.visitVarInsn(ALOAD, 0);
1634: cv.visitInsn(ICONST_M1);
1635: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
1636: STACK_FRAME_COUNTER_FIELD_NAME, I);
1637: }
1638:
1639: /**
1640: * Handles the incrementation of the stack frame.
1641: *
1642: * @param cv
1643: */
1644: private void incrementStackFrameCounter(final MethodVisitor cv) {
1645: cv.visitVarInsn(ALOAD, 0);
1646: cv.visitInsn(DUP);
1647: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
1648: STACK_FRAME_COUNTER_FIELD_NAME, I);
1649: cv.visitInsn(ICONST_1);
1650: cv.visitInsn(IADD);
1651: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
1652: STACK_FRAME_COUNTER_FIELD_NAME, I);
1653: }
1654:
1655: /**
1656: * Create and load a structure (f.e. array of Object) where args are stored, before setting the Rtti
1657: * with it (See addParametersToRttiInstance). The structure is stored at the given stackFreeIndex.
1658: * <p/>
1659: * Note: public for createMandatoryMethods in the models
1660: *
1661: * @param cv
1662: * @param stackFreeIndex
1663: */
1664: public final void createArgumentArrayAt(final MethodVisitor cv,
1665: final int stackFreeIndex) {
1666: AsmHelper.loadIntegerConstant(cv, m_fieldNames.length);
1667: cv.visitTypeInsn(ANEWARRAY, OBJECT_CLASS_NAME);
1668: cv.visitVarInsn(ASTORE, stackFreeIndex);
1669:
1670: for (int i = 0; i < m_argumentTypes.length; i++) {
1671: cv.visitVarInsn(ALOAD, stackFreeIndex);
1672: AsmHelper.loadIntegerConstant(cv, i);
1673: AsmHelper.prepareWrappingOfPrimitiveType(cv,
1674: m_argumentTypes[i]);
1675: cv.visitVarInsn(ALOAD, 0);
1676: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
1677: ARGUMENT_FIELD + i, m_argumentTypes[i]
1678: .getDescriptor());
1679: AsmHelper.wrapPrimitiveType(cv, m_argumentTypes[i]);
1680: cv.visitInsn(AASTORE);
1681: }
1682: }
1683:
1684: /**
1685: * Creates utility methods for the join point (getter, setters etc.).
1686: */
1687: private void createUtilityMethods() {
1688: MethodVisitor cv;
1689:
1690: // addMetaData
1691: {
1692: cv = m_cw.visitMethod(ACC_PUBLIC,
1693: ADD_META_DATA_METHOD_NAME,
1694: ADD_META_DATA_METHOD_SIGNATURE, null, null);
1695: cv.visitFieldInsn(GETSTATIC, m_joinPointClassName,
1696: META_DATA_FIELD_NAME, MAP_CLASS_SIGNATURE);
1697: cv.visitVarInsn(ALOAD, 1);
1698: cv.visitVarInsn(ALOAD, 2);
1699: cv.visitMethodInsn(INVOKEINTERFACE, MAP_CLASS_NAME,
1700: PUT_METHOD_NAME, PUT_METHOD_SIGNATURE);
1701: cv.visitInsn(POP);
1702: cv.visitInsn(RETURN);
1703: cv.visitMaxs(0, 0);
1704: }
1705:
1706: // getMetaData
1707: {
1708: cv = m_cw.visitMethod(ACC_PUBLIC,
1709: GET_META_DATA_METHOD_NAME,
1710: GET_META_DATA_METHOD_SIGNATURE, null, null);
1711: cv.visitFieldInsn(GETSTATIC, m_joinPointClassName,
1712: META_DATA_FIELD_NAME, MAP_CLASS_SIGNATURE);
1713: cv.visitVarInsn(ALOAD, 1);
1714: cv.visitMethodInsn(INVOKEINTERFACE, MAP_CLASS_NAME,
1715: GET_METHOD_NAME, GET_METHOD_SIGNATURE);
1716: cv.visitInsn(ARETURN);
1717: cv.visitMaxs(0, 0);
1718: }
1719:
1720: // getCallee
1721: {
1722: cv = m_cw.visitMethod(ACC_PUBLIC, GET_CALLEE_METHOD_NAME,
1723: NO_PARAMS_SIGNATURE + OBJECT_CLASS_SIGNATURE, null,
1724: null);
1725: cv.visitVarInsn(ALOAD, 0);
1726: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
1727: CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
1728: cv.visitInsn(ARETURN);
1729: cv.visitMaxs(0, 0);
1730: }
1731:
1732: // getCaller
1733: {
1734: cv = m_cw.visitMethod(ACC_PUBLIC, GET_CALLER_METHOD_NAME,
1735: NO_PARAMS_SIGNATURE + OBJECT_CLASS_SIGNATURE, null,
1736: null);
1737: cv.visitVarInsn(ALOAD, 0);
1738: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
1739: CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
1740: cv.visitInsn(ARETURN);
1741: cv.visitMaxs(0, 0);
1742: }
1743:
1744: // getTarget
1745: {
1746: cv = m_cw.visitMethod(ACC_PUBLIC, GET_TARGET_METHOD_NAME,
1747: NO_PARAMS_SIGNATURE + OBJECT_CLASS_SIGNATURE, null,
1748: null);
1749: cv.visitVarInsn(ALOAD, 0);
1750: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
1751: CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
1752: cv.visitInsn(ARETURN);
1753: cv.visitMaxs(0, 0);
1754: }
1755:
1756: // getThis
1757: {
1758: cv = m_cw.visitMethod(ACC_PUBLIC, GET_THIS_METHOD_NAME,
1759: NO_PARAMS_SIGNATURE + OBJECT_CLASS_SIGNATURE, null,
1760: null);
1761: cv.visitVarInsn(ALOAD, 0);
1762: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
1763: CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
1764: cv.visitInsn(ARETURN);
1765: cv.visitMaxs(0, 0);
1766: }
1767:
1768: // getCallerClass
1769: {
1770: cv = m_cw.visitMethod(ACC_PUBLIC,
1771: GET_CALLER_CLASS_METHOD_NAME,
1772: GET_CALLER_CLASS_METHOD_SIGNATURE, null, null);
1773: cv.visitFieldInsn(GETSTATIC, m_joinPointClassName,
1774: THIS_CLASS_FIELD_NAME_IN_JP, CLASS_CLASS_SIGNATURE);
1775: cv.visitInsn(ARETURN);
1776: cv.visitMaxs(0, 0);
1777: }
1778:
1779: // getCalleeClass
1780: {
1781: cv = m_cw.visitMethod(ACC_PUBLIC,
1782: GET_CALLEE_CLASS_METHOD_NAME,
1783: GET_CALLEE_CLASS_METHOD_SIGNATURE, null, null);
1784: cv.visitFieldInsn(GETSTATIC, m_joinPointClassName,
1785: TARGET_CLASS_FIELD_NAME_IN_JP,
1786: CLASS_CLASS_SIGNATURE);
1787: cv.visitInsn(ARETURN);
1788: cv.visitMaxs(0, 0);
1789: }
1790:
1791: // getTargetClass, deprecated but still there
1792: {
1793: cv = m_cw.visitMethod(ACC_PUBLIC,
1794: GET_TARGET_CLASS_METHOD_NAME,
1795: GET_TARGET_CLASS_METHOD_SIGNATURE, null, null);
1796: cv.visitFieldInsn(GETSTATIC, m_joinPointClassName,
1797: TARGET_CLASS_FIELD_NAME_IN_JP,
1798: CLASS_CLASS_SIGNATURE);
1799: cv.visitInsn(ARETURN);
1800: cv.visitMaxs(0, 0);
1801: }
1802:
1803: // getType
1804: {
1805: cv = m_cw.visitMethod(ACC_PUBLIC, GET_TYPE_METHOD_NAME,
1806: GET_TYPE_METHOD_SIGNATURE, null, null);
1807: AsmHelper.loadIntegerConstant(cv, m_joinPointType);
1808: cv.visitMethodInsn(INVOKESTATIC, Type.getType(
1809: JoinPointType.class).getInternalName(), "fromInt",
1810: "(I)"
1811: + Type.getType(JoinPointType.class)
1812: .getDescriptor());
1813: cv.visitInsn(ARETURN);
1814: cv.visitMaxs(0, 0);
1815: }
1816:
1817: // getEnclosingStaticJoinPoint
1818: {
1819: cv = m_cw.visitMethod(ACC_PUBLIC,
1820: GET_ENCLOSING_SJP_METHOD_NAME,
1821: GET_ENCLOSING_SJP_METHOD_SIGNATURE, null, null);
1822: cv.visitVarInsn(ALOAD, 0);
1823: cv.visitFieldInsn(GETSTATIC, m_joinPointClassName,
1824: ENCLOSING_SJP_FIELD_NAME,
1825: ENCLOSING_SJP_FIELD_CLASS_SIGNATURE);
1826: cv.visitInsn(ARETURN);
1827: cv.visitMaxs(0, 0);
1828: }
1829:
1830: }
1831:
1832: // TODO might be a use-case now in Uber Container, keep code for now
1833: // /**
1834: // * Creates the copy method.
1835: // * <p/>
1836: // * TODO refactor and put in subclasses
1837: // */
1838: // protected void createCopyMethod() {
1839: //
1840: // MethodVisitor cv = m_cw.visitMethod(ACC_PUBLIC, COPY_METHOD_NAME, COPY_METHOD_SIGNATURE, null, null);
1841: //
1842: // // create a new join point instance
1843: // cv.visitTypeInsn(NEW, m_joinPointClassName);
1844: // cv.visitInsn(DUP);
1845: // int joinPointCloneIndex = 1;
1846: // cv.visitMethodInsn(INVOKESPECIAL, m_joinPointClassName, INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE);
1847: // cv.visitVarInsn(ASTORE, joinPointCloneIndex);
1848: //
1849: // // set stack frame index
1850: // cv.visitVarInsn(ALOAD, joinPointCloneIndex);
1851: // cv.visitVarInsn(ALOAD, 0);
1852: // cv.visitFieldInsn(GETFIELD, m_joinPointClassName, STACK_FRAME_COUNTER_FIELD_NAME, I);
1853: // cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, STACK_FRAME_COUNTER_FIELD_NAME, I);
1854: //
1855: // if (m_isThisAdvisable) {
1856: // // set interceptor index
1857: // cv.visitVarInsn(ALOAD, joinPointCloneIndex);
1858: // cv.visitVarInsn(ALOAD, 0);
1859: // cv.visitFieldInsn(GETFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
1860: // cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
1861: //
1862: // // set array length fields
1863: // cv.visitVarInsn(ALOAD, joinPointCloneIndex);
1864: // cv.visitVarInsn(ALOAD, 0);
1865: // cv.visitFieldInsn(GETFIELD, m_joinPointClassName, NR_OF_BEFORE_INTERCEPTORS_FIELD_NAME, I);
1866: // cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_BEFORE_INTERCEPTORS_FIELD_NAME, I);
1867: // cv.visitVarInsn(ALOAD, joinPointCloneIndex);
1868: // cv.visitVarInsn(ALOAD, 0);
1869: // cv.visitFieldInsn(GETFIELD, m_joinPointClassName, NR_OF_AROUND_INTERCEPTORS_FIELD_NAME, I);
1870: // cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AROUND_INTERCEPTORS_FIELD_NAME, I);
1871: // cv.visitVarInsn(ALOAD, joinPointCloneIndex);
1872: // cv.visitVarInsn(ALOAD, 0);
1873: // cv.visitFieldInsn(GETFIELD, m_joinPointClassName, NR_OF_AFTER_INTERCEPTORS_FIELD_NAME, I);
1874: // cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AFTER_INTERCEPTORS_FIELD_NAME, I);
1875: // cv.visitVarInsn(ALOAD, joinPointCloneIndex);
1876: // cv.visitVarInsn(ALOAD, 0);
1877: // cv.visitFieldInsn(GETFIELD, m_joinPointClassName, NR_OF_AFTER_RETURNING_INTERCEPTORS_FIELD_NAME, I);
1878: // cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AFTER_RETURNING_INTERCEPTORS_FIELD_NAME, I);
1879: // cv.visitVarInsn(ALOAD, joinPointCloneIndex);
1880: // cv.visitVarInsn(ALOAD, 0);
1881: // cv.visitFieldInsn(GETFIELD, m_joinPointClassName, NR_OF_AFTER_THROWING_INTERCEPTORS_FIELD_NAME, I);
1882: // cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AFTER_THROWING_INTERCEPTORS_FIELD_NAME, I);
1883: //
1884: // // set arrays
1885: // cv.visitVarInsn(ALOAD, joinPointCloneIndex);
1886: // cv.visitVarInsn(ALOAD, 0);
1887: // cv.visitFieldInsn(
1888: // GETFIELD, m_joinPointClassName, BEFORE_INTERCEPTORS_FIELD_NAME,
1889: // BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE
1890: // );
1891: // cv.visitFieldInsn(
1892: // PUTFIELD, m_joinPointClassName, BEFORE_INTERCEPTORS_FIELD_NAME,
1893: // BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE
1894: // );
1895: // cv.visitVarInsn(ALOAD, joinPointCloneIndex);
1896: // cv.visitVarInsn(ALOAD, 0);
1897: // cv.visitFieldInsn(
1898: // GETFIELD, m_joinPointClassName, AROUND_INTERCEPTORS_FIELD_NAME,
1899: // AROUND_ADVICE_ARRAY_CLASS_SIGNATURE
1900: // );
1901: // cv.visitFieldInsn(
1902: // PUTFIELD, m_joinPointClassName, AROUND_INTERCEPTORS_FIELD_NAME,
1903: // AROUND_ADVICE_ARRAY_CLASS_SIGNATURE
1904: // );
1905: // cv.visitVarInsn(ALOAD, joinPointCloneIndex);
1906: // cv.visitVarInsn(ALOAD, 0);
1907: // cv.visitFieldInsn(
1908: // GETFIELD, m_joinPointClassName, AFTER_INTERCEPTORS_FIELD_NAME, AFTER_ADVICE_ARRAY_CLASS_SIGNATURE
1909: // );
1910: // cv.visitFieldInsn(
1911: // PUTFIELD, m_joinPointClassName, AFTER_INTERCEPTORS_FIELD_NAME, AFTER_ADVICE_ARRAY_CLASS_SIGNATURE
1912: // );
1913: // cv.visitVarInsn(ALOAD, joinPointCloneIndex);
1914: // cv.visitVarInsn(ALOAD, 0);
1915: // cv.visitFieldInsn(
1916: // GETFIELD, m_joinPointClassName, AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
1917: // AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE
1918: // );
1919: // cv.visitFieldInsn(
1920: // PUTFIELD, m_joinPointClassName, AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
1921: // AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE
1922: // );
1923: // cv.visitVarInsn(ALOAD, joinPointCloneIndex);
1924: // cv.visitVarInsn(ALOAD, 0);
1925: // cv.visitFieldInsn(
1926: // GETFIELD, m_joinPointClassName, AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
1927: // AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE
1928: // );
1929: // cv.visitFieldInsn(
1930: // PUTFIELD, m_joinPointClassName, AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
1931: // AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE
1932: // );
1933: // }
1934: //
1935: // // set callee
1936: // cv.visitVarInsn(ALOAD, joinPointCloneIndex);
1937: // cv.visitVarInsn(ALOAD, 0);
1938: // cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
1939: // cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
1940: //
1941: // // set caller
1942: // cv.visitVarInsn(ALOAD, joinPointCloneIndex);
1943: // cv.visitVarInsn(ALOAD, 0);
1944: // cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
1945: // cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
1946: //
1947: // // set the arguments
1948: // for (int i = 0; i < m_fieldNames.length; i++) {
1949: // String fieldName = m_fieldNames[i];
1950: // cv.visitVarInsn(ALOAD, joinPointCloneIndex);
1951: // cv.visitVarInsn(ALOAD, 0);
1952: // cv.visitFieldInsn(GETFIELD, m_joinPointClassName, fieldName, m_argumentTypes[i].getDescriptor());
1953: // cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, fieldName, m_argumentTypes[i].getDescriptor());
1954: // }
1955: //
1956: // // set the returned field if any
1957: // if (m_returnType.getSort() != Type.VOID) {
1958: // cv.visitVarInsn(ALOAD, joinPointCloneIndex);
1959: // cv.visitVarInsn(ALOAD, 0);
1960: // cv.visitFieldInsn(GETFIELD, m_joinPointClassName, RETURN_VALUE_FIELD_NAME, m_returnType.getDescriptor());
1961: // cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, RETURN_VALUE_FIELD_NAME, m_returnType.getDescriptor());
1962: // }
1963: //
1964: // cv.visitVarInsn(ALOAD, joinPointCloneIndex);
1965: // cv.visitInsn(ARETURN);
1966: // cv.visitMaxs(0, 0);
1967: // }
1968:
1969: /**
1970: * Build up the signature of the 'invoke' methods.
1971: *
1972: * @return
1973: */
1974: protected String buildInvokeMethodSignature() {
1975: StringBuffer invokeDescBuf = new StringBuffer();
1976: invokeDescBuf.append('(');
1977: if (m_joinPointType != JoinPointType.CONSTRUCTOR_CALL_INT) {
1978: if (!Modifier.isStatic(m_calleeMemberModifiers)) {
1979: // callee
1980: invokeDescBuf.append(m_calleeClassSignature);
1981: }
1982: }
1983: // args
1984: for (int i = 0; i < m_argumentTypes.length; i++) {
1985: Type type = m_argumentTypes[i];
1986: invokeDescBuf.append(type.getDescriptor());
1987: }
1988: // caller
1989: invokeDescBuf.append(m_callerClassSignature);
1990: invokeDescBuf.append(')');
1991: invokeDescBuf.append(m_returnType.getDescriptor());
1992: return invokeDescBuf.toString();
1993: }
1994:
1995: /**
1996: * Checks if at least one advice is using this or target (bounded or runtime check)
1997: *
1998: * @return true if so
1999: */
2000: private boolean requiresThisOrTarget() {
2001: return m_isThisAdvisable
2002: || requiresThisOrTarget(m_aroundAdviceMethodInfos)
2003: || requiresThisOrTarget(m_beforeAdviceMethodInfos)
2004: || requiresThisOrTarget(m_afterFinallyAdviceMethodInfos)
2005: || requiresThisOrTarget(m_afterReturningAdviceMethodInfos)
2006: || requiresThisOrTarget(m_afterThrowingAdviceMethodInfos);
2007: }
2008:
2009: /**
2010: * Checks if at least one advice is using the non static JoinPoint explicitly
2011: *
2012: * @return true if so
2013: */
2014: private boolean requiresJoinPoint() {
2015: if (m_isThisAdvisable
2016: || requiresJoinPoint(m_aroundAdviceMethodInfos)
2017: || requiresJoinPoint(m_beforeAdviceMethodInfos)
2018: || requiresJoinPoint(m_afterFinallyAdviceMethodInfos)
2019: || requiresJoinPoint(m_afterReturningAdviceMethodInfos)
2020: || requiresJoinPoint(m_afterThrowingAdviceMethodInfos)) {
2021: return true;
2022: }
2023:
2024: // query the models to know which level of optimization we can use
2025: for (int i = 0; i < m_aspectModels.length; i++) {
2026: if (m_aspectModels[i].requiresReflectiveInfo()) {
2027: // if at least one model requries RTTI then build it
2028: return true;
2029: }
2030: }
2031:
2032: return false;
2033: }
2034:
2035: /**
2036: * Checks if at least one advice is using target or this (bounded or runtime check)
2037: *
2038: * @param adviceMethodInfos
2039: * @return true if so
2040: */
2041: private boolean requiresThisOrTarget(
2042: final AdviceMethodInfo[] adviceMethodInfos) {
2043: for (int i = 0; i < adviceMethodInfos.length; i++) {
2044: if (adviceMethodInfos[i].requiresThisOrTarget()) {
2045: return true;
2046: }
2047: }
2048: return false;
2049: }
2050:
2051: /**
2052: * Checks if at least one advice is using non static JoinPoint explicitly
2053: *
2054: * @param adviceMethodInfos
2055: * @return true if so
2056: */
2057: private boolean requiresJoinPoint(
2058: final AdviceMethodInfo[] adviceMethodInfos) {
2059: for (int i = 0; i < adviceMethodInfos.length; i++) {
2060: if (adviceMethodInfos[i].requiresJoinPoint()) {
2061: return true;
2062: }
2063: }
2064: return false;
2065: }
2066:
2067: /**
2068: * Handles the if case for runtime check (target instanceof, cflow)
2069: *
2070: * @param cv
2071: * @param adviceInfo
2072: * @return the label for endIf or null if the adviceInfo did not required runtime check
2073: */
2074: private Label beginRuntimeCheck(final MethodVisitor cv,
2075: final CompilerInput input, final AdviceInfo adviceInfo) {
2076: Label endRuntimeCheckLabel = null;
2077: DeploymentModel deploymentModel = adviceInfo
2078: .getAspectDeploymentModel();
2079: if (adviceInfo.hasTargetWithRuntimeCheck()
2080: || adviceInfo.getAdviceDefinition()
2081: .hasCflowOrCflowBelow()
2082: || DeploymentModel.PER_THIS.equals(deploymentModel)
2083: || DeploymentModel.PER_TARGET.equals(deploymentModel)) {
2084:
2085: int perObjectCheckType = RuntimeCheckVisitor.NULL_PER_OBJECT_TYPE;
2086:
2087: if (DeploymentModel.PER_THIS.equals(deploymentModel)) {
2088: perObjectCheckType = RuntimeCheckVisitor.PER_THIS_TYPE;
2089: } else if (DeploymentModel.PER_TARGET
2090: .equals(deploymentModel)) {
2091: perObjectCheckType = RuntimeCheckVisitor.PER_TARGET_TYPE;
2092: }
2093:
2094: endRuntimeCheckLabel = new Label();
2095: // create a specific visitor everytime
2096: RuntimeCheckVisitor runtimeCheckVisitor = new RuntimeCheckVisitor(
2097: cv, adviceInfo.getExpressionInfo(), input,
2098: perObjectCheckType, adviceInfo
2099: .getAspectQualifiedName());
2100: runtimeCheckVisitor.pushCheckOnStack(adviceInfo);
2101: cv.visitJumpInsn(IFEQ, endRuntimeCheckLabel);
2102: }
2103: return endRuntimeCheckLabel;
2104: }
2105:
2106: /**
2107: * Ends the ifLabel of a runtime check
2108: *
2109: * @param cv
2110: * @param adviceInfo
2111: * @param label if null, then do nothing (means we did not had a runtime check)
2112: */
2113: private void endRuntimeCheck(final MethodVisitor cv,
2114: final AdviceInfo adviceInfo, final Label label) {
2115: DeploymentModel deployModel = adviceInfo
2116: .getAspectDeploymentModel();
2117:
2118: if (adviceInfo.hasTargetWithRuntimeCheck()
2119: || adviceInfo.getAdviceDefinition()
2120: .hasCflowOrCflowBelow()
2121: || DeploymentModel.PER_THIS.equals(deployModel)
2122: || DeploymentModel.PER_TARGET.equals(deployModel)) {
2123:
2124: cv.visitLabel(label);
2125: }
2126: }
2127:
2128: /**
2129: * Helper method to load the callee on the stack
2130: *
2131: * @param cv
2132: * @param input
2133: */
2134: public static void loadCallee(final MethodVisitor cv,
2135: final CompilerInput input) {
2136: if (input.isOptimizedJoinPoint) {
2137: // grab the callee from the invoke parameters directly
2138: cv.visitVarInsn(ALOAD, input.calleeIndex);
2139: } else {
2140: loadJoinPointInstance(cv, input);
2141: cv.visitFieldInsn(GETFIELD, input.joinPointClassName,
2142: CALLEE_INSTANCE_FIELD_NAME,
2143: input.calleeClassSignature);
2144: }
2145: }
2146:
2147: /**
2148: * Helper method to load the caller on the stack
2149: *
2150: * @param cv
2151: * @param input
2152: */
2153: public static void loadCaller(final MethodVisitor cv,
2154: final CompilerInput input) {
2155: if (input.isOptimizedJoinPoint) {
2156: // grab the callee from the invoke parameters directly
2157: cv.visitVarInsn(ALOAD, input.callerIndex);
2158: } else {
2159: loadJoinPointInstance(cv, input);
2160: cv.visitFieldInsn(GETFIELD, input.joinPointClassName,
2161: CALLER_INSTANCE_FIELD_NAME,
2162: input.callerClassSignature);
2163: }
2164: }
2165:
2166: // /**
2167: // * Creates an invocation to Aspects.aspectOf(..).
2168: // *
2169: // * @param cv
2170: // * @param isOptimizedJoinPoint
2171: // * @param joinPointIndex
2172: // * @param callerIndex
2173: // * @param calleeIndex
2174: // * @param aspectInfo
2175: // */
2176: // public void createInvocationToAspectOf(final MethodVisitor cv,
2177: // final boolean isOptimizedJoinPoint,
2178: // final int joinPointIndex,
2179: // final int callerIndex,
2180: // final int calleeIndex,
2181: // final AspectInfo aspectInfo) {
2182: // if (DeploymentModel.PER_INSTANCE.equals(aspectInfo.getDeploymentModel())) {
2183: //
2184: // //generates code: aspectField = (cast) Aspects.aspect$Of(aspectQN, containerClassName, callee)
2185: // loadJoinPointInstance(cv, m_joinPointClassName, isOptimizedJoinPoint, joinPointIndex);
2186: // cv.visitLdcInsn(aspectInfo.getAspectQualifiedName());
2187: // if (calleeIndex >= 0) {
2188: // cv.visitVarInsn(ALOAD, calleeIndex);
2189: // cv.visitLdcInsn(aspectInfo.getAspectDefinition().getContainerClassName());
2190: // cv.visitMethodInsn(
2191: // INVOKESTATIC,
2192: // ASPECTS_CLASS_NAME,
2193: // ASPECT_OF_METHOD_NAME,
2194: // ASPECT_OF_PER_INSTANCE_METHOD_SIGNATURE
2195: // );
2196: // } else {
2197: // // TODO: should this really happen? we are filtering at early stage now. - REMOVE CODE BLOCK
2198: // // fallback to perClass
2199: // //aspectField = (cast) Aspects.aspectOf(aspectQN, containerClass, calleeClass)
2200: // cv.visitFieldInsn(GETSTATIC, m_joinPointClassName, TARGET_CLASS_FIELD_NAME_IN_JP, CLASS_CLASS_SIGNATURE);
2201: // cv.visitLdcInsn(aspectInfo.getAspectDefinition().getContainerClassName());
2202: // cv.visitMethodInsn(
2203: // INVOKESTATIC,
2204: // ASPECTS_CLASS_NAME,
2205: // ASPECT_OF_METHOD_NAME,
2206: // ASPECT_OF_PER_CLASS_METHOD_SIGNATURE
2207: // );
2208: // }
2209: // cv.visitTypeInsn(CHECKCAST, aspectInfo.getAspectClassName());
2210: // cv.visitFieldInsn(
2211: // PUTFIELD, m_joinPointClassName, aspectInfo.getAspectFieldName(),
2212: // aspectInfo.getAspectClassSignature()
2213: // );
2214: // }
2215: // }
2216:
2217: /**
2218: * Generates code needed for handling Advisable management for the target class.
2219: *
2220: * @param cv
2221: * @param joinPointInstanceIndex
2222: * @param advisableIndex
2223: */
2224: private void createInitializationForAdvisableManagement(
2225: final MethodVisitor cv, final int joinPointInstanceIndex,
2226: final int advisableIndex) {
2227: // interceptor index
2228: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2229: cv.visitInsn(ICONST_M1);
2230: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2231: INTERCEPTOR_INDEX_FIELD_NAME, I);
2232:
2233: initializeAroundInterceptors(cv, joinPointInstanceIndex,
2234: advisableIndex);
2235: initializeBeforeInterceptors(cv, joinPointInstanceIndex,
2236: advisableIndex);
2237: initializeAfterInterceptors(cv, joinPointInstanceIndex,
2238: advisableIndex);
2239: initializeAfterReturningInterceptors(cv,
2240: joinPointInstanceIndex, advisableIndex);
2241: initializeAfterThrowingInterceptors(cv, joinPointInstanceIndex,
2242: advisableIndex);
2243: }
2244:
2245: /**
2246: * Handle the around interceptor init.
2247: *
2248: * @param cv
2249: * @param joinPointInstanceIndex
2250: * @param advisableIndex
2251: */
2252: private void initializeAroundInterceptors(final MethodVisitor cv,
2253: final int joinPointInstanceIndex, final int advisableIndex) {
2254: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2255: cv.visitVarInsn(ALOAD, advisableIndex);
2256: cv.visitTypeInsn(CHECKCAST, ADVISABLE_CLASS_NAME);
2257: cv.visitLdcInsn(new Integer(m_joinPointClassName.hashCode()));
2258: cv.visitMethodInsn(INVOKEINTERFACE, ADVISABLE_CLASS_NAME,
2259: GET_AROUND_ADVICE_METHOD_NAME,
2260: GET_AROUND_ADVICE_METHOD_SIGNATURE);
2261: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2262: AROUND_INTERCEPTORS_FIELD_NAME,
2263: AROUND_ADVICE_ARRAY_CLASS_SIGNATURE);
2264:
2265: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2266: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2267: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2268: AROUND_INTERCEPTORS_FIELD_NAME,
2269: AROUND_ADVICE_ARRAY_CLASS_SIGNATURE);
2270: cv.visitInsn(ARRAYLENGTH);
2271: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2272: NR_OF_AROUND_INTERCEPTORS_FIELD_NAME, I);
2273: }
2274:
2275: /**
2276: * Handle the before interceptor init.
2277: *
2278: * @param cv
2279: * @param joinPointInstanceIndex
2280: * @param advisableIndex
2281: */
2282: private void initializeBeforeInterceptors(final MethodVisitor cv,
2283: final int joinPointInstanceIndex, final int advisableIndex) {
2284: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2285: cv.visitVarInsn(ALOAD, advisableIndex);
2286: cv.visitTypeInsn(CHECKCAST, ADVISABLE_CLASS_NAME);
2287: cv.visitLdcInsn(new Integer(m_joinPointClassName.hashCode()));
2288: cv.visitMethodInsn(INVOKEINTERFACE, ADVISABLE_CLASS_NAME,
2289: GET_BEFORE_ADVICE_METHOD_NAME,
2290: GET_BEFORE_ADVICE_METHOD_SIGNATURE);
2291: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2292: BEFORE_INTERCEPTORS_FIELD_NAME,
2293: BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE);
2294:
2295: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2296: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2297: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2298: BEFORE_INTERCEPTORS_FIELD_NAME,
2299: BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE);
2300: cv.visitInsn(ARRAYLENGTH);
2301: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2302: NR_OF_BEFORE_INTERCEPTORS_FIELD_NAME, I);
2303: }
2304:
2305: /**
2306: * Handle the after finally interceptor init.
2307: *
2308: * @param cv
2309: * @param joinPointInstanceIndex
2310: * @param advisableIndex
2311: */
2312: private void initializeAfterInterceptors(final MethodVisitor cv,
2313: final int joinPointInstanceIndex, final int advisableIndex) {
2314: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2315: cv.visitVarInsn(ALOAD, advisableIndex);
2316: cv.visitTypeInsn(CHECKCAST, ADVISABLE_CLASS_NAME);
2317: cv.visitLdcInsn(new Integer(m_joinPointClassName.hashCode()));
2318: cv.visitMethodInsn(INVOKEINTERFACE, ADVISABLE_CLASS_NAME,
2319: GET_AFTER_ADVICE_METHOD_NAME,
2320: GET_AFTER_ADVICE_METHOD_SIGNATURE);
2321: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2322: AFTER_INTERCEPTORS_FIELD_NAME,
2323: AFTER_ADVICE_ARRAY_CLASS_SIGNATURE);
2324:
2325: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2326: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2327: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2328: AFTER_INTERCEPTORS_FIELD_NAME,
2329: AFTER_ADVICE_ARRAY_CLASS_SIGNATURE);
2330: cv.visitInsn(ARRAYLENGTH);
2331: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2332: NR_OF_AFTER_INTERCEPTORS_FIELD_NAME, I);
2333: }
2334:
2335: /**
2336: * Handle the after returning interceptor init.
2337: *
2338: * @param cv
2339: * @param joinPointInstanceIndex
2340: * @param advisableIndex
2341: */
2342: private void initializeAfterReturningInterceptors(
2343: final MethodVisitor cv, final int joinPointInstanceIndex,
2344: final int advisableIndex) {
2345: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2346: cv.visitVarInsn(ALOAD, advisableIndex);
2347: cv.visitTypeInsn(CHECKCAST, ADVISABLE_CLASS_NAME);
2348: cv.visitLdcInsn(new Integer(m_joinPointClassName.hashCode()));
2349: cv.visitMethodInsn(INVOKEINTERFACE, ADVISABLE_CLASS_NAME,
2350: GET_AFTER_RETURNING_ADVICE_METHOD_NAME,
2351: GET_AFTER_RETURNING_ADVICE_METHOD_SIGNATURE);
2352: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2353: AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
2354: AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE);
2355:
2356: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2357: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2358: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2359: AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
2360: AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE);
2361: cv.visitInsn(ARRAYLENGTH);
2362: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2363: NR_OF_AFTER_RETURNING_INTERCEPTORS_FIELD_NAME, I);
2364: }
2365:
2366: /**
2367: * Handle the after throwing interceptor init.
2368: *
2369: * @param cv
2370: * @param joinPointInstanceIndex
2371: * @param advisableIndex
2372: */
2373: private void initializeAfterThrowingInterceptors(
2374: final MethodVisitor cv, final int joinPointInstanceIndex,
2375: final int advisableIndex) {
2376: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2377: cv.visitVarInsn(ALOAD, advisableIndex);
2378: cv.visitTypeInsn(CHECKCAST, ADVISABLE_CLASS_NAME);
2379: cv.visitLdcInsn(new Integer(m_joinPointClassName.hashCode()));
2380: cv.visitMethodInsn(INVOKEINTERFACE, ADVISABLE_CLASS_NAME,
2381: GET_AFTER_THROWING_ADVICE_METHOD_NAME,
2382: GET_AFTER_THROWING_ADVICE_METHOD_SIGNATURE);
2383: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2384: AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
2385: AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE);
2386:
2387: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2388: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2389: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2390: AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
2391: AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE);
2392: cv.visitInsn(ARRAYLENGTH);
2393: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2394: NR_OF_AFTER_THROWING_INTERCEPTORS_FIELD_NAME, I);
2395: }
2396:
2397: /**
2398: * Handles the around interceptor invocations.
2399: *
2400: * @param cv
2401: */
2402: private void createAroundInterceptorInvocations(
2403: final MethodVisitor cv) {
2404: cv.visitVarInsn(ALOAD, 0);
2405: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2406: INTERCEPTOR_INDEX_FIELD_NAME, I);
2407: cv.visitInsn(ICONST_M1);
2408: Label ifStatementLabel = new Label();
2409: cv.visitJumpInsn(IF_ICMPEQ, ifStatementLabel);
2410: cv.visitVarInsn(ALOAD, 0);
2411: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2412: INTERCEPTOR_INDEX_FIELD_NAME, I);
2413: cv.visitVarInsn(ALOAD, 0);
2414: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2415: NR_OF_AROUND_INTERCEPTORS_FIELD_NAME, I);
2416: cv.visitJumpInsn(IF_ICMPGE, ifStatementLabel);
2417: cv.visitVarInsn(ALOAD, 0);
2418: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2419: AROUND_INTERCEPTORS_FIELD_NAME,
2420: AROUND_ADVICE_ARRAY_CLASS_SIGNATURE);
2421: cv.visitVarInsn(ALOAD, 0);
2422: cv.visitInsn(DUP);
2423: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2424: INTERCEPTOR_INDEX_FIELD_NAME, I);
2425: cv.visitInsn(DUP_X1);
2426: cv.visitInsn(ICONST_1);
2427: cv.visitInsn(IADD);
2428: cv.visitFieldInsn(PUTFIELD, m_joinPointClassName,
2429: INTERCEPTOR_INDEX_FIELD_NAME, I);
2430: cv.visitInsn(AALOAD);
2431: cv.visitVarInsn(ALOAD, 0);
2432: cv.visitMethodInsn(INVOKEINTERFACE, AROUND_ADVICE_CLASS_NAME,
2433: INTERCEPT_INVOKE_METHOD_NAME,
2434: AROUND_ADVICE_INVOKE_METHOD_SIGNATURE);
2435: cv.visitInsn(ARETURN);
2436: cv.visitLabel(ifStatementLabel);
2437: }
2438:
2439: /**
2440: * Creates invocations fo the before interceptors.
2441: *
2442: * @param cv
2443: * @param joinPointInstanceIndex
2444: * @param registerDepth
2445: */
2446: private void createBeforeInterceptorInvocations(
2447: final MethodVisitor cv, final int joinPointInstanceIndex,
2448: final int registerDepth) {
2449: final int loopIndex = registerDepth + 1;
2450: cv.visitInsn(ICONST_0);
2451: cv.visitVarInsn(ISTORE, loopIndex);
2452: Label loopStartLabel = new Label();
2453: cv.visitLabel(loopStartLabel);
2454: cv.visitVarInsn(ILOAD, loopIndex);
2455: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2456: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2457: NR_OF_BEFORE_INTERCEPTORS_FIELD_NAME, I);
2458: Label loopCheckCondLabel = new Label();
2459: cv.visitJumpInsn(IF_ICMPGE, loopCheckCondLabel);
2460: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2461: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2462: BEFORE_INTERCEPTORS_FIELD_NAME,
2463: BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE);
2464: cv.visitVarInsn(ILOAD, loopIndex);
2465: cv.visitInsn(AALOAD);
2466: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2467: cv.visitMethodInsn(INVOKEINTERFACE, BEFORE_ADVICE_CLASS_NAME,
2468: INTERCEPT_INVOKE_METHOD_NAME,
2469: BEFORE_ADVICE_INVOKE_METHOD_SIGNATURE);
2470: cv.visitIincInsn(loopIndex, 1);
2471: cv.visitJumpInsn(GOTO, loopStartLabel);
2472: cv.visitLabel(loopCheckCondLabel);
2473: }
2474:
2475: /**
2476: * Creates invocations fo the after finally interceptors.
2477: *
2478: * @param cv
2479: * @param joinPointInstanceIndex
2480: * @param registerDepth
2481: */
2482: private void createAfterInterceptorInvocations(
2483: final MethodVisitor cv, final int joinPointInstanceIndex,
2484: final int registerDepth) {
2485: final int loopIndex = registerDepth + 1;
2486: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2487: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2488: NR_OF_AFTER_INTERCEPTORS_FIELD_NAME, I);
2489: cv.visitInsn(ICONST_1);
2490: cv.visitInsn(ISUB);
2491: cv.visitVarInsn(ISTORE, loopIndex);
2492: Label loopLabel1 = new Label();
2493: cv.visitLabel(loopLabel1);
2494: cv.visitVarInsn(ILOAD, loopIndex);
2495: Label loopLabel2 = new Label();
2496: cv.visitJumpInsn(IFLT, loopLabel2);
2497: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2498: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2499: AFTER_INTERCEPTORS_FIELD_NAME,
2500: AFTER_ADVICE_ARRAY_CLASS_SIGNATURE);
2501: cv.visitVarInsn(ILOAD, loopIndex);
2502: cv.visitInsn(AALOAD);
2503: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2504: cv.visitMethodInsn(INVOKEINTERFACE, AFTER_ADVICE_CLASS_NAME,
2505: INTERCEPT_INVOKE_METHOD_NAME,
2506: AFTER_ADVICE_INVOKE_METHOD_SIGNATURE);
2507: cv.visitIincInsn(loopIndex, -1);
2508: cv.visitJumpInsn(GOTO, loopLabel1);
2509: cv.visitLabel(loopLabel2);
2510: }
2511:
2512: /**
2513: * Creates invocations fo the after returning interceptors.
2514: *
2515: * @param cv
2516: * @param joinPointInstanceIndex
2517: * @param returnValueInstanceIndex
2518: */
2519: private void createAfterReturningInterceptorInvocations(
2520: final MethodVisitor cv, final int joinPointInstanceIndex,
2521: final int returnValueInstanceIndex) {
2522: final int loopIndex = returnValueInstanceIndex + 1;
2523: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2524: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2525: NR_OF_AFTER_RETURNING_INTERCEPTORS_FIELD_NAME, I);
2526: cv.visitInsn(ICONST_1);
2527: cv.visitInsn(ISUB);
2528: cv.visitVarInsn(ISTORE, loopIndex);
2529: Label loopLabel1 = new Label();
2530: cv.visitLabel(loopLabel1);
2531: cv.visitVarInsn(ILOAD, loopIndex);
2532: Label loopLabel2 = new Label();
2533: cv.visitJumpInsn(IFLT, loopLabel2);
2534: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2535: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2536: AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
2537: AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE);
2538: cv.visitVarInsn(ILOAD, loopIndex);
2539: cv.visitInsn(AALOAD);
2540: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2541: cv.visitVarInsn(ALOAD, returnValueInstanceIndex);
2542: cv.visitMethodInsn(INVOKEINTERFACE,
2543: AFTER_RETURNING_ADVICE_CLASS_NAME,
2544: INTERCEPT_INVOKE_METHOD_NAME,
2545: AFTER_RETURNING_ADVICE_INVOKE_METHOD_SIGNATURE);
2546: cv.visitIincInsn(loopIndex, -1);
2547: cv.visitJumpInsn(GOTO, loopLabel1);
2548: cv.visitLabel(loopLabel2);
2549: }
2550:
2551: /**
2552: * Creates invocations fo the after returning interceptors.
2553: *
2554: * @param cv
2555: * @param joinPointInstanceIndex
2556: * @param exceptionInstanceIndex
2557: */
2558: private void createAfterThrowingInterceptorInvocations(
2559: final MethodVisitor cv, final int joinPointInstanceIndex,
2560: final int exceptionInstanceIndex) {
2561: final int loopIndex = exceptionInstanceIndex + 1;
2562: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2563: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2564: NR_OF_AFTER_THROWING_INTERCEPTORS_FIELD_NAME, I);
2565: cv.visitInsn(ICONST_1);
2566: cv.visitInsn(ISUB);
2567: cv.visitVarInsn(ISTORE, loopIndex);
2568: Label loopLabel1 = new Label();
2569: cv.visitLabel(loopLabel1);
2570: cv.visitVarInsn(ILOAD, loopIndex);
2571: Label loopLabel2 = new Label();
2572: cv.visitJumpInsn(IFLT, loopLabel2);
2573: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2574: cv.visitFieldInsn(GETFIELD, m_joinPointClassName,
2575: AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
2576: AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE);
2577: cv.visitVarInsn(ILOAD, loopIndex);
2578: cv.visitInsn(AALOAD);
2579: cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2580: cv.visitVarInsn(ALOAD, exceptionInstanceIndex);
2581: cv.visitMethodInsn(INVOKEINTERFACE,
2582: AFTER_THROWING_ADVICE_CLASS_NAME,
2583: INTERCEPT_INVOKE_METHOD_NAME,
2584: AFTER_THROWING_ADVICE_INVOKE_METHOD_SIGNATURE);
2585: cv.visitIincInsn(loopIndex, -1);
2586: cv.visitJumpInsn(GOTO, loopLabel1);
2587: cv.visitLabel(loopLabel2);
2588: }
2589:
2590: /**
2591: * Checks if the join point requires a proceed() method.
2592: *
2593: * @return
2594: */
2595: private boolean requiresProceedMethod() {
2596: return m_hasAroundAdvices || m_isThisAdvisable;
2597: }
2598:
2599: public static boolean requiresCallerInstance(
2600: DeploymentModel deployModel) {
2601: return DeploymentModel.PER_INSTANCE.equals(deployModel)
2602: || DeploymentModel.PER_THIS.equals(deployModel);
2603: }
2604:
2605: public static boolean requiresCalleeInstance(
2606: DeploymentModel deployModel) {
2607: return DeploymentModel.PER_TARGET.equals(deployModel);
2608: }
2609:
2610: public static boolean requiresCallerOrCallee(
2611: DeploymentModel deploymentModel) {
2612: return requiresCallerInstance(deploymentModel)
2613: || requiresCalleeInstance(deploymentModel);
2614: }
2615:
2616: public final AspectModel[] getAspectModels() {
2617: return m_aspectModels;
2618: }
2619:
2620: }
|