/************************************************************************************** * Copyright (c) Jonas Bon�r, Alexandre Vasseur. All rights reserved. * * http://aspectwerkz.codehaus.org * * ---------------------------------------------------------------------------------- * * The software in this package is published under the terms of the LGPL license * * a copy of which has been included with this distribution in the license.txt file. * **************************************************************************************/ package org.codehaus.aspectwerkz.transform.inlining.compiler; import org.codehaus.aspectwerkz.DeploymentModel; import org.codehaus.aspectwerkz.aspect.AdviceInfo; import org.codehaus.aspectwerkz.aspect.AdviceType; import org.codehaus.aspectwerkz.aspect.container.AspectFactoryManager; import org.codehaus.aspectwerkz.cflow.CflowCompiler; import org.codehaus.aspectwerkz.definition.AspectDefinition; import org.codehaus.aspectwerkz.exception.DefinitionException; import org.codehaus.aspectwerkz.joinpoint.management.AdviceInfoContainer; import org.codehaus.aspectwerkz.reflect.ClassInfo; import org.codehaus.aspectwerkz.reflect.ClassInfoHelper; import org.codehaus.aspectwerkz.reflect.MethodInfo; import org.codehaus.aspectwerkz.reflect.impl.asm.AsmClassInfo; import org.codehaus.aspectwerkz.transform.TransformationConstants; import org.codehaus.aspectwerkz.transform.JoinPointCompiler; import org.codehaus.aspectwerkz.transform.inlining.AdviceMethodInfo; import org.codehaus.aspectwerkz.transform.inlining.AsmHelper; import org.codehaus.aspectwerkz.transform.inlining.AspectInfo; import org.codehaus.aspectwerkz.transform.inlining.spi.AspectModel; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Label; import org.objectweb.asm.Type; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; /** * FIXME doc * * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a> */ public class AspectWerkzAspectModel implements AspectModel, Opcodes, TransformationConstants { protected final List m_customProceedMethodStructs; public AspectWerkzAspectModel() { m_customProceedMethodStructs = null; //prototype } private AspectWerkzAspectModel(CompilationInfo.Model compilationModel) { m_customProceedMethodStructs = new ArrayList(0); collectCustomProceedMethods(compilationModel, compilationModel.getAdviceInfoContainer()); } public static final String TYPE = AspectWerkzAspectModel.class.getName(); public AspectModel getInstance(CompilationInfo.Model compilationModel) { // return a new instance to handle custom proceed return new AspectWerkzAspectModel(compilationModel); } public String getAspectModelType() { return TYPE; } public void defineAspect(ClassInfo aspectClassInfo, AspectDefinition aspectDef, ClassLoader loader) { //FIXME - refactor there ? } public AroundClosureClassInfo getAroundClosureClassInfo() { if (m_customProceedMethodStructs.isEmpty()) { //let the compiler deal with JP / SJP interface return new AroundClosureClassInfo(OBJECT_CLASS_NAME, new String[0]); } else { // get the custom join point interfaces Set interfaces = new HashSet(); for (Iterator it = m_customProceedMethodStructs.iterator(); it.hasNext();) { MethodInfo methodInfo = ((CustomProceedMethodStruct) it.next()).customProceed; interfaces.add(methodInfo.getDeclaringType().getName().replace('.', '/')); } return new AroundClosureClassInfo(OBJECT_CLASS_NAME, (String[]) interfaces.toArray(new String[]{})); } } public void createMandatoryMethods(ClassWriter cw, JoinPointCompiler compiler) { createCustomProceedMethods(cw, (AbstractJoinPointCompiler)compiler); } public void createInvocationOfAroundClosureSuperClass(MethodVisitor cv) { ;// AW model has no super class apart Object, which is handled by the compiler } /** * Create and initialize the aspect field for a specific aspect (qualified since it depends * on the param, deployment model, container etc). * And creates instantiation of aspects using the Aspects.aspectOf() methods which uses the AspectContainer impls. * We are using the THIS_CLASS classloader since the aspect can be visible from that one only f.e. for get/set/call * * TODO for perJVM and perClass aspect this means we eagerly load the aspect. Different from AJ * * @param cw * @param cv * @param aspectInfo * @param joinPointClassName */ public void createAndStoreStaticAspectInstantiation(ClassVisitor cw, MethodVisitor cv, AspectInfo aspectInfo, String joinPointClassName) { String aspectClassSignature = aspectInfo.getAspectClassSignature(); String aspectClassName = aspectInfo.getAspectClassName(); // retrieve the aspect set it to the field DeploymentModel deploymentModel = aspectInfo.getDeploymentModel(); if (CflowCompiler.isCflowClass(aspectClassName)) { cw.visitField(ACC_PRIVATE + ACC_STATIC, aspectInfo.getAspectFieldName(), aspectClassSignature, null, null); // handle Cflow native aspectOf //TODO: would be better done with a custom aspectModel for cflow, or with default factory handling //FIXME AVF what does factory do there ? cv.visitMethodInsn( INVOKESTATIC, aspectClassName, CflowCompiler.CFLOW_ASPECTOF_METHOD_NAME, "()" + aspectClassSignature ); cv.visitFieldInsn(PUTSTATIC, joinPointClassName, aspectInfo.getAspectFieldName(), aspectClassSignature); } else if (deploymentModel.equals(DeploymentModel.PER_JVM)) { cw.visitField(ACC_PRIVATE + ACC_STATIC, aspectInfo.getAspectFieldName(), aspectClassSignature, null, null); cv.visitMethodInsn( INVOKESTATIC, aspectInfo.getAspectFactoryClassName(), "aspectOf", "()"+aspectClassSignature ); cv.visitFieldInsn(PUTSTATIC, joinPointClassName, aspectInfo.getAspectFieldName(), aspectClassSignature); } else if (deploymentModel.equals(DeploymentModel.PER_CLASS)) { cw.visitField(ACC_PRIVATE + ACC_STATIC, aspectInfo.getAspectFieldName(), aspectClassSignature, null, null); cv.visitFieldInsn(GETSTATIC, joinPointClassName, THIS_CLASS_FIELD_NAME_IN_JP, CLASS_CLASS_SIGNATURE); cv.visitMethodInsn( INVOKESTATIC, aspectInfo.getAspectFactoryClassName(), "aspectOf", "(Ljava/lang/Class;)"+aspectClassSignature ); cv.visitFieldInsn(PUTSTATIC, joinPointClassName, aspectInfo.getAspectFieldName(), aspectClassSignature); } else if (AbstractJoinPointCompiler.requiresCallerOrCallee(deploymentModel)) { cw.visitField(ACC_PRIVATE, aspectInfo.getAspectFieldName(), aspectClassSignature, null, null); } else { throw new UnsupportedOperationException( "unsupported deployment model - " + aspectInfo.getAspectClassName() + " " + deploymentModel ); } } /** * Initializes instance level aspects, retrieves them from the target instance through the * <code>HasInstanceLevelAspect</code> interfaces. * <p/> * Use by 'perInstance', 'perThis' and 'perTarget' deployment models. * * @param cv * @param aspectInfo * @param input */ public void createAndStoreRuntimeAspectInstantiation(final MethodVisitor cv, final CompilerInput input, final AspectInfo aspectInfo) { // gen code: if (Aspects.hasAspect(...) { aspectField = (<TYPE>)((HasInstanceLocalAspect)CALLER).aw$getAspect(className, qualifiedName, containerClassName) } if (DeploymentModel.PER_INSTANCE.equals(aspectInfo.getDeploymentModel())) {//TODO && callerIndex >= 0 //storeAspectInstance(cv, input, aspectInfo, input.callerIndex); } else if (DeploymentModel.PER_THIS.equals(aspectInfo.getDeploymentModel()) && input.callerIndex >= 0) { Label hasAspectCheck = pushPerXCondition(cv, input.callerIndex, aspectInfo); storeAspectInstance(cv, input, aspectInfo, input.callerIndex); cv.visitLabel(hasAspectCheck); } else if (DeploymentModel.PER_TARGET.equals(aspectInfo.getDeploymentModel()) && input.calleeIndex >= 0) { Label hasAspectCheck = pushPerXCondition(cv, input.calleeIndex, aspectInfo); storeAspectInstance(cv, input, aspectInfo, input.calleeIndex); cv.visitLabel(hasAspectCheck); } if (aspectInfo.getDeploymentModel() == DeploymentModel.PER_INSTANCE) {//TODO refactor with previous if block // gen code: aspectField = (<TYPE>)((HasInstanceLocalAspect)CALLER).aw$getAspect(className, qualifiedName, containerClassName) AbstractJoinPointCompiler.loadJoinPointInstance(cv, input); if (input.callerIndex >= 0) { cv.visitVarInsn(ALOAD, input.callerIndex); } else { // caller instance not available - skipping //TODO clean up should not occur } cv.visitMethodInsn( INVOKESTATIC, aspectInfo.getAspectFactoryClassName(), "aspectOf", "(Ljava/lang/Object;)"+aspectInfo.getAspectClassSignature() ); // cv.visitLdcInsn(aspectInfo.getAspectClassName().replace('/', '.')); // cv.visitLdcInsn(aspectInfo.getAspectQualifiedName()); // AsmHelper.loadStringConstant(cv, aspectInfo.getAspectDefinition().getContainerClassName()); // cv.visitMethodInsn( // INVOKEINTERFACE, // HAS_INSTANCE_LEVEL_ASPECT_INTERFACE_NAME, // INSTANCE_LEVEL_GETASPECT_METHOD_NAME, // INSTANCE_LEVEL_GETASPECT_METHOD_SIGNATURE // ); // cv.visitTypeInsn(CHECKCAST, aspectInfo.getAspectClassName()); cv.visitFieldInsn( PUTFIELD, input.joinPointClassName, aspectInfo.getAspectFieldName(), aspectInfo.getAspectClassSignature() ); } } /** * Load aspect instance on stack * * @param cv * @param input * @param aspectInfo */ public void loadAspect(final MethodVisitor cv, final CompilerInput input, final AspectInfo aspectInfo) { DeploymentModel deploymentModel = aspectInfo.getDeploymentModel(); if (DeploymentModel.PER_JVM.equals(deploymentModel) || DeploymentModel.PER_CLASS.equals(deploymentModel)) { cv.visitFieldInsn( GETSTATIC, input.joinPointClassName, aspectInfo.getAspectFieldName(), aspectInfo.getAspectClassSignature() ); } else if (DeploymentModel.PER_INSTANCE.equals(deploymentModel)) { AbstractJoinPointCompiler.loadJoinPointInstance(cv, input); cv.visitFieldInsn( GETFIELD, input.joinPointClassName, aspectInfo.getAspectFieldName(), aspectInfo.getAspectClassSignature() ); } else if (DeploymentModel.PER_THIS.equals(deploymentModel)) { AbstractJoinPointCompiler.loadJoinPointInstance(cv, input); cv.visitFieldInsn( GETFIELD, input.joinPointClassName, aspectInfo.getAspectFieldName(), aspectInfo.getAspectClassSignature() ); //FIXME see FIXME on aspect instantion Label nullCheck = new Label(); cv.visitJumpInsn(IFNONNULL, nullCheck); storeAspectInstance(cv, input, aspectInfo, input.callerIndex); cv.visitLabel(nullCheck); AbstractJoinPointCompiler.loadJoinPointInstance(cv, input); cv.visitFieldInsn( GETFIELD, input.joinPointClassName, aspectInfo.getAspectFieldName(), aspectInfo.getAspectClassSignature() ); } else if (DeploymentModel.PER_TARGET.equals(deploymentModel)) { AbstractJoinPointCompiler.loadJoinPointInstance(cv, input); cv.visitFieldInsn( GETFIELD, input.joinPointClassName, aspectInfo.getAspectFieldName(), aspectInfo.getAspectClassSignature() ); //FIXME see FIXME on aspect instantion Label nullCheck = new Label(); cv.visitJumpInsn(IFNONNULL, nullCheck); storeAspectInstance(cv, input, aspectInfo, input.calleeIndex); cv.visitLabel(nullCheck); AbstractJoinPointCompiler.loadJoinPointInstance(cv, input); cv.visitFieldInsn( GETFIELD, input.joinPointClassName, aspectInfo.getAspectFieldName(), aspectInfo.getAspectClassSignature() ); } else { throw new DefinitionException("deployment model [" + deploymentModel + "] is not supported"); } } public void createAroundAdviceArgumentHandling(MethodVisitor cv, CompilerInput input, Type[] joinPointArgumentTypes, AdviceMethodInfo adviceMethodInfo) { defaultCreateAroundAdviceArgumentHandling( cv, input, joinPointArgumentTypes, adviceMethodInfo ); } public void createBeforeOrAfterAdviceArgumentHandling(MethodVisitor cv, CompilerInput input, Type[] joinPointArgumentTypes, AdviceMethodInfo adviceMethodInfo, int specialArgIndex) { defaultCreateBeforeOrAfterAdviceArgumentHandling( cv, input, joinPointArgumentTypes, adviceMethodInfo, specialArgIndex ); } public boolean requiresReflectiveInfo() { // custom proceed() JoinPoint will not be recognize by the default logic return m_customProceedMethodStructs.size() > 0; } ///////---------- Helpers /** * Generate a "if Aspects.hasAspect(qName, instance)" * * @param cv * @param perInstanceIndex * @param aspectInfo * @return */ private Label pushPerXCondition(final MethodVisitor cv, final int perInstanceIndex, final AspectInfo aspectInfo) { Label hasAspectCheck = new Label(); cv.visitVarInsn(ALOAD, perInstanceIndex); cv.visitMethodInsn( INVOKESTATIC, aspectInfo.getAspectFactoryClassName(), FACTORY_HASASPECT_METHOD_NAME, FACTORY_HASASPECT_PEROBJECT_METHOD_SIGNATURE ); cv.visitJumpInsn(IFEQ, hasAspectCheck); return hasAspectCheck; } /** * Creates the instance of an aspect by invoking * "HasInstanceLevelAspect.aw$getAspect(String, String)" on perInstanceIndex variable * and stores the aspect instance in the joinpoint instance field */ private void storeAspectInstance(final MethodVisitor cv, final CompilerInput input, final AspectInfo aspectInfo, final int perInstanceIndex) { AbstractJoinPointCompiler.loadJoinPointInstance(cv, input); if (perInstanceIndex >= 0) { cv.visitVarInsn(ALOAD, perInstanceIndex); } cv.visitMethodInsn( INVOKESTATIC, aspectInfo.getAspectFactoryClassName(), FACTORY_ASPECTOF_METHOD_NAME, "(Ljava/lang/Object;)" + aspectInfo.getAspectClassSignature() ); // // cv.visitLdcInsn(aspectInfo.getAspectClassName().replace('/', '.')); // cv.visitLdcInsn(aspectInfo.getAspectQualifiedName()); // AsmHelper.loadStringConstant(cv, aspectInfo.getAspectDefinition().getContainerClassName()); // cv.visitMethodInsn( // INVOKEINTERFACE, // HAS_INSTANCE_LEVEL_ASPECT_INTERFACE_NAME, // INSTANCE_LEVEL_GETASPECT_METHOD_NAME, // INSTANCE_LEVEL_GETASPECT_METHOD_SIGNATURE // ); // // cv.visitTypeInsn(CHECKCAST, aspectInfo.getAspectClassName()); cv.visitFieldInsn( PUTFIELD, input.joinPointClassName, aspectInfo.getAspectFieldName(), aspectInfo.getAspectClassSignature() ); } /** * Creates the custom proceed methods. */ private void createCustomProceedMethods(ClassWriter cw, AbstractJoinPointCompiler compiler) { Set addedMethodSignatures = new HashSet(); for (Iterator it = m_customProceedMethodStructs.iterator(); it.hasNext();) { CustomProceedMethodStruct customProceedStruct = (CustomProceedMethodStruct) it.next(); MethodInfo methodInfo = customProceedStruct.customProceed; final String desc = methodInfo.getSignature(); if (addedMethodSignatures.contains(desc)) { continue; } addedMethodSignatures.add(desc); MethodVisitor cv = cw.visitMethod( ACC_PUBLIC | ACC_FINAL, PROCEED_METHOD_NAME, desc, null, new String[]{ THROWABLE_CLASS_NAME } ); // update the joinpoint instance with the given values // starts at 1 since first arg is the custom join point by convention //TODO see JoinPointManage for this custom jp is first convention int argStackIndex = 1; for (int i = 1; i < customProceedStruct.adviceToTargetArgs.length; i++) { int targetArg = customProceedStruct.adviceToTargetArgs[i]; if (targetArg >= 0) { // regular arg String fieldName = compiler.m_fieldNames[targetArg]; cv.visitVarInsn(ALOAD, 0); Type type = compiler.m_argumentTypes[targetArg]; argStackIndex = AsmHelper.loadType(cv, argStackIndex, type); cv.visitFieldInsn(PUTFIELD, compiler.m_joinPointClassName, fieldName, type.getDescriptor()); } else if (targetArg == AdviceInfo.TARGET_ARG) { cv.visitVarInsn(ALOAD, 0); argStackIndex = AsmHelper.loadType( cv, argStackIndex, Type.getType(compiler.m_calleeClassSignature) ); cv.visitFieldInsn( PUTFIELD, compiler.m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, compiler.m_calleeClassSignature ); } else if (targetArg == AdviceInfo.THIS_ARG) { cv.visitVarInsn(ALOAD, 0); argStackIndex = AsmHelper.loadType( cv, argStackIndex, Type.getType(compiler.m_callerClassSignature) ); cv.visitFieldInsn( PUTFIELD, compiler.m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, compiler.m_callerClassSignature ); } else { ;//skip it } } // call proceed() // and handles unwrapping for returning primitive Type returnType = Type.getType(customProceedStruct.customProceed.getReturnType().getSignature()); if (AsmHelper.isPrimitive(returnType)) { cv.visitVarInsn(ALOAD, 0); cv.visitMethodInsn( INVOKESPECIAL, compiler.m_joinPointClassName, PROCEED_METHOD_NAME, PROCEED_METHOD_SIGNATURE ); AsmHelper.unwrapType(cv, returnType); } else { cv.visitVarInsn(ALOAD, 0); cv.visitMethodInsn( INVOKESPECIAL, compiler.m_joinPointClassName, PROCEED_METHOD_NAME, PROCEED_METHOD_SIGNATURE ); if (!returnType.getClassName().equals(OBJECT_CLASS_SIGNATURE)) { cv.visitTypeInsn(CHECKCAST, returnType.getInternalName()); } } AsmHelper.addReturnStatement(cv, returnType); cv.visitMaxs(0, 0); } } //---------- Model specific methods /** * Collects the custom proceed methods used in the advice specified. * * @param model * @param advices */ private void collectCustomProceedMethods(final CompilationInfo.Model model, final AdviceInfoContainer advices) { ClassLoader loader = model.getThisClassInfo().getClassLoader(); final AdviceInfo[] beforeAdviceInfos = advices.getBeforeAdviceInfos(); for (int i = 0; i < beforeAdviceInfos.length; i++) { collectCustomProceedMethods(beforeAdviceInfos[i], loader); } final AdviceInfo[] aroundAdviceInfos = advices.getAroundAdviceInfos(); for (int i = 0; i < aroundAdviceInfos.length; i++) { collectCustomProceedMethods(aroundAdviceInfos[i], loader); } final AdviceInfo[] afterFinallyAdviceInfos = advices.getAfterFinallyAdviceInfos(); for (int i = 0; i < afterFinallyAdviceInfos.length; i++) { collectCustomProceedMethods(afterFinallyAdviceInfos[i], loader); } final AdviceInfo[] afterReturningAdviceInfos = advices.getAfterReturningAdviceInfos(); for (int i = 0; i < afterReturningAdviceInfos.length; i++) { collectCustomProceedMethods(afterReturningAdviceInfos[i], loader); } final AdviceInfo[] afterThrowingAdviceInfos = advices.getAfterThrowingAdviceInfos(); for (int i = 0; i < afterThrowingAdviceInfos.length; i++) { collectCustomProceedMethods(afterThrowingAdviceInfos[i], loader); } } /** * Collects the custom proceed methods used in the advice specified. * * @param adviceInfo * @param loader */ private void collectCustomProceedMethods(final AdviceInfo adviceInfo, final ClassLoader loader) { final Type[] paramTypes = adviceInfo.getMethodParameterTypes(); if (paramTypes.length != 0) { Type firstParam = paramTypes[0]; //TODO should we support JP at other positions or lock the other advice models then so that JP.. // ..is not there or first only ? // check if first param is an object but not a JP or SJP if (firstParam.getSort() == Type.OBJECT && !firstParam.getClassName().equals(JOIN_POINT_JAVA_CLASS_NAME) && !firstParam.getClassName().equals(STATIC_JOIN_POINT_JAVA_CLASS_NAME)) { ClassInfo classInfo = AsmClassInfo.getClassInfo(firstParam.getClassName(), loader); if (ClassInfoHelper.implementsInterface(classInfo, JOIN_POINT_JAVA_CLASS_NAME) || ClassInfoHelper.implementsInterface(classInfo, STATIC_JOIN_POINT_JAVA_CLASS_NAME)) { // we have ourselves a custom joinpoint MethodInfo[] methods = classInfo.getMethods(); for (int j = 0; j < methods.length; j++) { MethodInfo method = methods[j]; if (method.getName().equals(PROCEED_METHOD_NAME)) { // we inherit the binding from the advice that actually use us // for now the first advice sets the rule // it is up to the user to ensure consistency if the custom proceed // is used more than once in different advices. m_customProceedMethodStructs.add( new CustomProceedMethodStruct( method, adviceInfo.getMethodToArgIndexes() ) ); } } } } } } private static class CustomProceedMethodStruct { MethodInfo customProceed; int[] adviceToTargetArgs; public CustomProceedMethodStruct(MethodInfo customProceed, int[] adviceToTargetArgs) { this.customProceed = customProceed; this.adviceToTargetArgs = adviceToTargetArgs; } } public static void defaultCreateBeforeOrAfterAdviceArgumentHandling(MethodVisitor cv, CompilerInput input, Type[] joinPointArgumentTypes, AdviceMethodInfo adviceMethodInfo, int specialArgIndex) { int[] argIndexes = adviceMethodInfo.getAdviceMethodArgIndexes(); // if empty, we consider for now that we have to push JoinPoint for old advice with JoinPoint as sole arg for (int j = 0; j < argIndexes.length; j++) { int argIndex = argIndexes[j]; if (argIndex >= 0) { Type argumentType = joinPointArgumentTypes[argIndex]; int argStackIndex = AsmHelper.getRegisterIndexOf(joinPointArgumentTypes, argIndex) + input.argStartIndex; AsmHelper.loadType(cv, argStackIndex, argumentType); } else if (argIndex == AdviceInfo.JOINPOINT_ARG || argIndex == AdviceInfo.STATIC_JOINPOINT_ARG) { AbstractJoinPointCompiler.loadJoinPointInstance(cv, input); } else if (argIndex == AdviceInfo.TARGET_ARG) { AbstractJoinPointCompiler.loadCallee(cv, input); // add a cast if runtime check was used if (adviceMethodInfo.getAdviceInfo().hasTargetWithRuntimeCheck()) { cv.visitTypeInsn( CHECKCAST, adviceMethodInfo.getAdviceInfo().getMethodParameterTypes()[j].getInternalName() ); } } else if (argIndex == AdviceInfo.THIS_ARG) { AbstractJoinPointCompiler.loadCaller(cv, input); } else if (argIndex == AdviceInfo.SPECIAL_ARGUMENT && specialArgIndex != INDEX_NOTAVAILABLE) { Type argumentType = adviceMethodInfo.getAdviceInfo().getMethodParameterTypes()[j]; AsmHelper.loadType(cv, specialArgIndex, argumentType); if (AdviceType.AFTER_THROWING.equals(adviceMethodInfo.getAdviceInfo().getAdviceDefinition().getType()) || AdviceType.AFTER_RETURNING.equals(adviceMethodInfo.getAdviceInfo().getAdviceDefinition().getType())) { cv.visitTypeInsn(CHECKCAST, argumentType.getInternalName()); } } else { throw new Error("magic index is not supported: " + argIndex); } } } public static void defaultCreateAroundAdviceArgumentHandling(MethodVisitor cv, CompilerInput input, Type[] joinPointArgumentTypes, AdviceMethodInfo adviceMethodInfo) { int[] argIndexes = adviceMethodInfo.getAdviceMethodArgIndexes(); for (int j = 0; j < argIndexes.length; j++) { int argIndex = argIndexes[j]; if (argIndex >= 0) { Type argumentType = joinPointArgumentTypes[argIndex]; cv.visitVarInsn(ALOAD, 0); cv.visitFieldInsn( GETFIELD, input.joinPointClassName, ARGUMENT_FIELD + argIndex, argumentType.getDescriptor() ); } else if (argIndex == AdviceInfo.JOINPOINT_ARG || argIndex == AdviceInfo.STATIC_JOINPOINT_ARG || argIndex == AdviceInfo.VALID_NON_AW_AROUND_CLOSURE_TYPE || argIndex == AdviceInfo.CUSTOM_JOIN_POINT_ARG) { cv.visitVarInsn(ALOAD, 0); } else if (argIndex == AdviceInfo.TARGET_ARG) { AbstractJoinPointCompiler.loadCallee(cv, input); // add a cast if runtime check was used if (adviceMethodInfo.getAdviceInfo().hasTargetWithRuntimeCheck()) { cv.visitTypeInsn( CHECKCAST, adviceMethodInfo.getAdviceInfo().getMethodParameterTypes()[j].getInternalName() ); } } else if (argIndex == AdviceInfo.THIS_ARG) { AbstractJoinPointCompiler.loadCaller(cv, input); } else { throw new Error("advice method argument index type is not supported: " + argIndex); } } } }