1 /***************************************************************************************
2 * Copyright (c) Jonas BonŽr, Alexandre Vasseur. All rights reserved. *
3 * http://aspectwerkz.codehaus.org *
4 * ---------------------------------------------------------------------------------- *
5 * The software in this package is published under the terms of the LGPL license *
6 * a copy of which has been included with this distribution in the license.txt file. *
7 **************************************************************************************/
8 package org.codehaus.aspectwerkz.transform.inlining.compiler;
9
10 import org.objectweb.asm.ClassWriter;
11 import org.objectweb.asm.CodeVisitor;
12 import org.objectweb.asm.Constants;
13 import org.objectweb.asm.Label;
14 import org.objectweb.asm.Type;
15
16 import org.codehaus.aspectwerkz.DeploymentModel;
17 import org.codehaus.aspectwerkz.cflow.CflowCompiler;
18 import org.codehaus.aspectwerkz.reflect.ClassInfo;
19 import org.codehaus.aspectwerkz.reflect.ClassInfoHelper;
20 import org.codehaus.aspectwerkz.reflect.MethodInfo;
21 import org.codehaus.aspectwerkz.reflect.ReflectionInfo;
22 import org.codehaus.aspectwerkz.reflect.impl.asm.AsmClassInfo;
23 import org.codehaus.aspectwerkz.aspect.AdviceInfo;
24 import org.codehaus.aspectwerkz.exception.DefinitionException;
25 import org.codehaus.aspectwerkz.aspect.AdviceType;
26 import org.codehaus.aspectwerkz.definition.AspectDefinition;
27 import org.codehaus.aspectwerkz.transform.Compiler;
28 import org.codehaus.aspectwerkz.transform.TransformationConstants;
29 import org.codehaus.aspectwerkz.transform.inlining.EmittedJoinPoint;
30 import org.codehaus.aspectwerkz.transform.inlining.AsmHelper;
31 import org.codehaus.aspectwerkz.transform.inlining.AdviceMethodInfo;
32 import org.codehaus.aspectwerkz.transform.inlining.AspectInfo;
33 import org.codehaus.aspectwerkz.transform.inlining.AspectModelManager;
34 import org.codehaus.aspectwerkz.transform.inlining.spi.AspectModel;
35 import org.codehaus.aspectwerkz.joinpoint.management.JoinPointType;
36 import org.codehaus.aspectwerkz.joinpoint.management.AdviceInfoContainer;
37
38 import java.lang.reflect.InvocationTargetException;
39 import java.lang.reflect.Modifier;
40 import java.util.Iterator;
41 import java.util.ArrayList;
42 import java.util.List;
43 import java.util.Set;
44 import java.util.HashSet;
45 import java.util.HashMap;
46 import java.util.Map;
47
48 /***
49 * Abstract base class for the different join point compiler implementations.
50 * <p/>
51 * Compiles/generates a class that represents a specific join point, a class which invokes the advices
52 * and the target join point statically.
53 * <p/>
54 * FIXME: depending on hotswap needs, remove the implements StaticJP or JP decision
55 * FIXME: remove isOptimizedJP and put it global
56 *
57 * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
58 * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur </a>
59 * @author <a href="mailto:the_mindstorm@evolva.ro">Alex Popescu</a>
60 */
61 public abstract class AbstractJoinPointCompiler implements Compiler, TransformationConstants {
62
63 protected static final String TARGET_CLASS_FIELD_NAME = "TARGET_CLASS";
64 protected static final String THIS_CLASS_FIELD_NAME = "THIS_CLASS";
65
66
67 public static final boolean DUMP_JIT_CLASSES = false;
68 protected static final String DUMP_DIR = "_dump";
69
70 protected final String m_callerClassName;
71 protected final String m_calleeClassName;
72 protected final String m_callerClassSignature;
73 protected final String m_calleeClassSignature;
74 protected final String m_joinPointClassName;
75 protected final int m_joinPointType;
76 protected final int m_joinPointHash;
77 protected final String m_callerMethodName;
78 protected final String m_callerMethodDesc;
79 protected final int m_callerMethodModifiers;
80 protected final String m_calleeMemberName;
81 protected final String m_calleeMemberDesc;
82 protected final int m_calleeMemberModifiers;
83
84 protected ClassWriter m_cw;
85 protected AspectInfo[] m_aspectInfos;
86 protected AspectModel[] m_aspectModels;
87 protected AdviceMethodInfo[] m_aroundAdviceMethodInfos;
88 protected AdviceMethodInfo[] m_beforeAdviceMethodInfos;
89 protected AdviceMethodInfo[] m_afterFinallyAdviceMethodInfos;
90 protected AdviceMethodInfo[] m_afterReturningAdviceMethodInfos;
91 protected AdviceMethodInfo[] m_afterThrowingAdviceMethodInfos;
92 protected final List m_customProceedMethodStructs = new ArrayList();
93
94 protected boolean m_hasAroundAdvices = false;
95 protected boolean m_requiresThisOrTarget = false;
96 protected boolean m_requiresJoinPoint = false;
97
98 protected String[] m_fieldNames;
99 protected Type[] m_argumentTypes;
100 protected Type m_returnType;
101 protected boolean m_isThisAdvisable = false;
102
103 /***
104 * Creates a new join point compiler instance.
105 *
106 * @param model the compilation model
107 */
108 public AbstractJoinPointCompiler(final CompilationInfo.Model model) {
109 m_joinPointClassName = model.getJoinPointClassName();
110
111 final EmittedJoinPoint emittedJoinPoint = model.getEmittedJoinPoint();
112
113 m_joinPointHash = emittedJoinPoint.getJoinPointHash();
114 m_joinPointType = emittedJoinPoint.getJoinPointType();
115
116 m_callerMethodName = emittedJoinPoint.getCallerMethodName();
117 m_callerMethodDesc = emittedJoinPoint.getCallerMethodDesc();
118 m_callerMethodModifiers = emittedJoinPoint.getCallerMethodModifiers();
119
120 m_calleeMemberName = emittedJoinPoint.getCalleeMemberName();
121 m_calleeMemberDesc = emittedJoinPoint.getCalleeMemberDesc();
122 m_calleeMemberModifiers = emittedJoinPoint.getCalleeMemberModifiers();
123
124
125 m_callerClassName = emittedJoinPoint.getCallerClassName().replace('.', '/');
126 m_calleeClassName = emittedJoinPoint.getCalleeClassName().replace('.', '/');
127 m_callerClassSignature = L + emittedJoinPoint.getCallerClassName().replace('.', '/') + SEMICOLON;
128 m_calleeClassSignature = L + emittedJoinPoint.getCalleeClassName().replace('.', '/') + SEMICOLON;
129
130 m_argumentTypes = getJoinPointArgumentTypes();
131 m_returnType = getJoinPointReturnType();
132
133 initialize(model);
134 }
135
136 /***
137 * Initializes the the join point compiler.
138 *
139 * @param model the compilation model
140 */
141 private synchronized void initialize(final CompilationInfo.Model model) {
142
143 checkIfThisIsAdvisable(model);
144
145
146 final AdviceInfoContainer advices = model.getAdviceInfoContainer();
147
148 collectAdviceInfo(advices);
149 collectCustomProceedMethods(model, advices);
150
151
152 m_hasAroundAdvices = m_aroundAdviceMethodInfos.length > 0;
153 m_requiresThisOrTarget = requiresThisOrTarget();
154 m_requiresJoinPoint = requiresJoinPoint();
155
156
157 setupReferencedAspectModels();
158
159 m_cw = AsmHelper.newClassWriter(true);
160 }
161
162 /***
163 * Collects the advice info.
164 *
165 * @param advices
166 */
167 private void collectAdviceInfo(final AdviceInfoContainer advices) {
168 final List aspectQualifiedNames = new ArrayList();
169 final Set aspectInfos = new HashSet();
170 m_beforeAdviceMethodInfos = getAdviceMethodInfos(
171 aspectQualifiedNames, aspectInfos, advices.getBeforeAdviceInfos()
172 );
173 m_aroundAdviceMethodInfos = getAdviceMethodInfos(
174 aspectQualifiedNames, aspectInfos, advices.getAroundAdviceInfos()
175 );
176 m_afterReturningAdviceMethodInfos = getAdviceMethodInfos(
177 aspectQualifiedNames, aspectInfos, advices.getAfterReturningAdviceInfos()
178 );
179 m_afterFinallyAdviceMethodInfos = getAdviceMethodInfos(
180 aspectQualifiedNames, aspectInfos, advices.getAfterFinallyAdviceInfos()
181 );
182 m_afterThrowingAdviceMethodInfos = getAdviceMethodInfos(
183 aspectQualifiedNames, aspectInfos, advices.getAfterThrowingAdviceInfos()
184 );
185
186 m_aspectInfos = (AspectInfo[]) aspectInfos.toArray(new AspectInfo[aspectInfos.size()]);
187 }
188
189 /***
190 * Collects the custom proceed methods used in the advice specified.
191 *
192 * @param model
193 * @param advices
194 */
195 private void collectCustomProceedMethods(final CompilationInfo.Model model,
196 final AdviceInfoContainer advices) {
197 ClassLoader loader = model.getThisClassInfo().getClassLoader();
198 final AdviceInfo[] beforeAdviceInfos = advices.getBeforeAdviceInfos();
199 for (int i = 0; i < beforeAdviceInfos.length; i++) {
200 collectCustomProceedMethods(beforeAdviceInfos[i], loader);
201 }
202 final AdviceInfo[] aroundAdviceInfos = advices.getAroundAdviceInfos();
203 for (int i = 0; i < aroundAdviceInfos.length; i++) {
204 collectCustomProceedMethods(aroundAdviceInfos[i], loader);
205 }
206 final AdviceInfo[] afterFinallyAdviceInfos = advices.getAfterFinallyAdviceInfos();
207 for (int i = 0; i < afterFinallyAdviceInfos.length; i++) {
208 collectCustomProceedMethods(afterFinallyAdviceInfos[i], loader);
209 }
210 final AdviceInfo[] afterReturningAdviceInfos = advices.getAfterReturningAdviceInfos();
211 for (int i = 0; i < afterReturningAdviceInfos.length; i++) {
212 collectCustomProceedMethods(afterReturningAdviceInfos[i], loader);
213 }
214 final AdviceInfo[] afterThrowingAdviceInfos = advices.getAfterThrowingAdviceInfos();
215 for (int i = 0; i < afterThrowingAdviceInfos.length; i++) {
216 collectCustomProceedMethods(afterThrowingAdviceInfos[i], loader);
217 }
218 }
219
220 /***
221 * Collects the custom proceed methods used in the advice specified.
222 *
223 * @param adviceInfo
224 * @param loader
225 */
226 private void collectCustomProceedMethods(final AdviceInfo adviceInfo, final ClassLoader loader) {
227 final Type[] paramTypes = adviceInfo.getMethodParameterTypes();
228 if (paramTypes.length != 0) {
229 Type firstParam = paramTypes[0];
230
231
232
233 if (firstParam.getSort() == Type.OBJECT &&
234 !firstParam.getClassName().equals(JOIN_POINT_JAVA_CLASS_NAME) &&
235 !firstParam.getClassName().equals(STATIC_JOIN_POINT_JAVA_CLASS_NAME)) {
236 ClassInfo classInfo = AsmClassInfo.getClassInfo(firstParam.getClassName(), loader);
237 if (ClassInfoHelper.implementsInterface(classInfo, JOIN_POINT_JAVA_CLASS_NAME) ||
238 ClassInfoHelper.implementsInterface(classInfo, STATIC_JOIN_POINT_JAVA_CLASS_NAME)) {
239
240 MethodInfo[] methods = classInfo.getMethods();
241 for (int j = 0; j < methods.length; j++) {
242 MethodInfo method = methods[j];
243 if (method.getName().equals(PROCEED_METHOD_NAME)) {
244
245
246
247
248 m_customProceedMethodStructs.add(new CustomProceedMethodStruct(
249 method,
250 adviceInfo.getMethodToArgIndexes()
251 ));
252 }
253 }
254 }
255 }
256 }
257 }
258
259 /***
260 * Checks if the this class implements the Advisable interface.
261 *
262 * @param model
263 */
264 private void checkIfThisIsAdvisable(final CompilationInfo.Model model) {
265 if (!Modifier.isStatic(m_callerMethodModifiers)) {
266 ClassInfo[] interfaces = model.getThisClassInfo().getInterfaces();
267 for (int i = 0; i < interfaces.length; i++) {
268 if (interfaces[i].getName().equals(ADVISABLE_CLASS_JAVA_NAME)) {
269 m_isThisAdvisable = true;
270 break;
271 }
272 }
273 }
274 }
275
276 /***
277 * Retrives and sets the aspect models that are referenced in this compilation phase.
278 */
279 private void setupReferencedAspectModels() {
280 Map aspectModelMap = new HashMap();
281 for (int i = 0; i < m_aspectInfos.length; i++) {
282 AspectDefinition aspectDef = m_aspectInfos[i].getAspectDefinition();
283 if (aspectDef.isAspectWerkzAspect()) {
284 continue;
285 }
286 String type = aspectDef.getAspectModel();
287 AspectModel aspectModel = AspectModelManager.getModelFor(type);
288 aspectModelMap.put(type, aspectModel);
289 if (aspectModel.requiresReflectiveInfo()) {
290 m_requiresJoinPoint = true;
291 }
292 }
293 m_aspectModels = (AspectModel[]) aspectModelMap.values().toArray(new AspectModel[aspectModelMap.size()]);
294 }
295
296 /***
297 * Returns the join point interface class name.
298 *
299 * @return
300 */
301 private String getJoinPointInterface() {
302 String joinPointInterface;
303 if (requiresProceedMethod() || m_requiresJoinPoint) {
304 joinPointInterface = JOIN_POINT_CLASS_NAME;
305 } else {
306 joinPointInterface = STATIC_JOIN_POINT_CLASS_NAME;
307 }
308 return joinPointInterface;
309 }
310
311 /***
312 * Retrieves the advice method infos.
313 *
314 * @param aspectQualifiedNames
315 * @param aspectInfos
316 * @param adviceInfos
317 * @return
318 */
319 protected AdviceMethodInfo[] getAdviceMethodInfos(final List aspectQualifiedNames,
320 final Set aspectInfos,
321 final AdviceInfo[] adviceInfos) {
322 List adviceMethodInfosSet = new ArrayList();
323 for (int i = 0; i < adviceInfos.length; i++) {
324 AdviceInfo adviceInfo = adviceInfos[i];
325
326
327 DeploymentModel deploymentModel = adviceInfo.getAdviceDefinition().getAspectDefinition()
328 .getDeploymentModel();
329 if (deploymentModel.equals(DeploymentModel.PER_INSTANCE) &&
330 Modifier.isStatic(m_callerMethodModifiers)) {
331 continue;
332 }
333
334 final String aspectClassName = adviceInfo.getAspectClassName().replace('.', '/');
335
336 if (!aspectQualifiedNames.contains(adviceInfo.getAspectQualifiedName())) {
337 aspectQualifiedNames.add(adviceInfo.getAspectQualifiedName());
338 }
339 int aspectIndex = aspectQualifiedNames.indexOf(adviceInfo.getAspectQualifiedName());
340 AdviceMethodInfo adviceMethodInfo = new AdviceMethodInfo(
341 adviceInfo,
342 ASPECT_FIELD_PREFIX + aspectIndex,
343 aspectClassName,
344 L + aspectClassName + SEMICOLON,
345 m_callerClassSignature,
346 m_calleeClassSignature,
347 m_joinPointClassName,
348 m_calleeMemberDesc
349 );
350 adviceMethodInfosSet.add(adviceMethodInfo);
351 aspectInfos.add(adviceMethodInfo.getAspectInfo());
352 }
353 return (AdviceMethodInfo[]) adviceMethodInfosSet.toArray(new AdviceMethodInfo[adviceMethodInfosSet.size()]);
354 }
355
356 /***
357 * Creates join point specific fields.
358 */
359 protected abstract void createJoinPointSpecificFields();
360
361 /***
362 * Creates the signature for the join point.
363 *
364 * @param cv
365 */
366 protected abstract void createSignature(final CodeVisitor cv);
367
368 /***
369 * Optimized implementation that does not retrieve the parameters from the join point instance but is passed
370 * directly to the method from the input parameters in the 'invoke' method. Can only be used if no around advice
371 * exists.
372 *
373 * @param cv
374 * @param argStartIndex index on stack of first target method arg (0 or 1, depends of static target or not)
375 */
376 protected abstract void createInlinedJoinPointInvocation(final CodeVisitor cv,
377 final boolean isOptimizedJoinPoint,
378 final int argStartIndex,
379 final int joinPointIndex);
380
381 /***
382 * Creates a call to the target join point, the parameter(s) to the join point are retrieved from the invocation
383 * local join point instance.
384 *
385 * @param cv
386 */
387 protected abstract void createJoinPointInvocation(final CodeVisitor cv);
388
389 /***
390 * Returns the join points return type.
391 *
392 * @return
393 */
394 protected abstract Type getJoinPointReturnType();
395
396 /***
397 * Returns the join points argument type(s).
398 *
399 * @return
400 */
401 protected abstract Type[] getJoinPointArgumentTypes();
402
403 /***
404 * Creates the getRtti method
405 */
406 protected abstract void createGetRttiMethod();
407
408 /***
409 * Creates the getSignature method
410 */
411 protected abstract void createGetSignatureMethod();
412
413 /***
414 * Compiles a join point class, one specific class for each distinct join point. The compiled join point class
415 * inherits the base join point class.
416 *
417 * @return the generated, compiled and loaded join point class
418 */
419 public byte[] compile() {
420 try {
421
422
423
424
425
426
427
428
429
430 createClassHeader();
431 createMandatoryMethodInAspectModels();
432 createFieldsCommonToAllJoinPoints();
433 createJoinPointSpecificFields();
434 createStaticInitializer();
435 createClinit();
436 createInit();
437 createUtilityMethods();
438 createCopyMethod();
439 createGetSignatureMethod();
440 createInvokeMethod();
441 if (requiresProceedMethod()) {
442 createProceedMethod();
443 }
444 if (m_requiresJoinPoint) {
445 createGetRttiMethod();
446 }
447 createCustomProceedMethods();
448 m_cw.visitEnd();
449
450 if (DUMP_JIT_CLASSES) {
451 AsmHelper.dumpClass(DUMP_DIR, m_joinPointClassName, m_cw);
452 }
453 return m_cw.toByteArray();
454
455 } catch (Exception e) {
456 e.printStackTrace();
457 StringBuffer buf = new StringBuffer();
458 buf.append("could not compile join point instance for join point with hash [");
459 buf.append(m_joinPointHash);
460 buf.append("] and declaring class [");
461 buf.append(m_callerClassName);
462 buf.append("] due to: ");
463 if (e instanceof InvocationTargetException) {
464 buf.append(((InvocationTargetException) e).getTargetException().toString());
465 } else {
466 buf.append(e.toString());
467 }
468 throw new RuntimeException(buf.toString());
469 }
470 }
471
472 /***
473 * Creates join point specific fields.
474 */
475 protected void createFieldsCommonToAllJoinPoints() {
476 if (m_returnType.getSort() != Type.VOID) {
477 m_cw.visitField(ACC_PRIVATE, RETURN_VALUE_FIELD_NAME, m_returnType.getDescriptor(), null, null);
478 }
479 m_cw.visitField(
480 ACC_PRIVATE + ACC_STATIC,
481 TARGET_CLASS_FIELD_NAME,
482 CLASS_CLASS_SIGNATURE,
483 null,
484 null
485 );
486
487 m_cw.visitField(
488 ACC_PRIVATE + ACC_STATIC + ACC_FINAL,
489 THIS_CLASS_FIELD_NAME,
490 CLASS_CLASS_SIGNATURE,
491 null,
492 null
493 );
494
495 m_cw.visitField(
496 ACC_PRIVATE + ACC_STATIC + ACC_FINAL,
497 ENCLOSING_SJP_FIELD_NAME,
498 ENCLOSING_SJP_FIELD_CLASS_SIGNATURE,
499 null,
500 null
501 );
502
503 m_cw.visitField(ACC_PRIVATE + ACC_STATIC, META_DATA_FIELD_NAME, MAP_CLASS_SIGNATURE, null, null);
504 m_cw.visitField(
505 ACC_PRIVATE + ACC_STATIC,
506 OPTIMIZED_JOIN_POINT_INSTANCE_FIELD_NAME,
507 L + m_joinPointClassName + SEMICOLON,
508 null, null
509 );
510 m_cw.visitField(ACC_PRIVATE, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature, null, null);
511 m_cw.visitField(ACC_PRIVATE, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature, null, null);
512 m_cw.visitField(ACC_PRIVATE, STACK_FRAME_COUNTER_FIELD_NAME, I, null, null);
513
514 if (m_isThisAdvisable) {
515 m_cw.visitField(ACC_PRIVATE, INTERCEPTOR_INDEX_FIELD_NAME, I, null, null);
516
517 m_cw.visitField(
518 ACC_PRIVATE, AROUND_INTERCEPTORS_FIELD_NAME,
519 AROUND_ADVICE_ARRAY_CLASS_SIGNATURE, null, null
520 );
521 m_cw.visitField(ACC_PRIVATE, NR_OF_AROUND_INTERCEPTORS_FIELD_NAME, I, null, null);
522
523 m_cw.visitField(
524 ACC_PRIVATE, BEFORE_INTERCEPTORS_FIELD_NAME,
525 BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE, null, null
526 );
527 m_cw.visitField(ACC_PRIVATE, NR_OF_BEFORE_INTERCEPTORS_FIELD_NAME, I, null, null);
528
529 m_cw.visitField(
530 ACC_PRIVATE, AFTER_INTERCEPTORS_FIELD_NAME,
531 AFTER_ADVICE_ARRAY_CLASS_SIGNATURE, null, null
532 );
533 m_cw.visitField(ACC_PRIVATE, NR_OF_AFTER_INTERCEPTORS_FIELD_NAME, I, null, null);
534
535 m_cw.visitField(
536 ACC_PRIVATE, AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
537 AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE, null, null
538 );
539 m_cw.visitField(ACC_PRIVATE, NR_OF_AFTER_RETURNING_INTERCEPTORS_FIELD_NAME, I, null, null);
540
541 m_cw.visitField(
542 ACC_PRIVATE, AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
543 AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE, null, null
544 );
545 m_cw.visitField(ACC_PRIVATE, NR_OF_AFTER_THROWING_INTERCEPTORS_FIELD_NAME, I, null, null);
546 }
547 }
548
549 /***
550 * Creates the clinit method for the join point.
551 */
552 protected void createClinit() {
553 CodeVisitor cv = m_cw.visitMethod(ACC_STATIC, CLINIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE, null, null);
554 cv.visitMethodInsn(
555 INVOKESTATIC, m_joinPointClassName,
556 STATIC_INITIALIZATION_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE
557 );
558 cv.visitInsn(RETURN);
559 cv.visitMaxs(0, 0);
560 }
561
562 /***
563 * Creates the init method for the join point.
564 */
565 protected void createInit() {
566 CodeVisitor cv = m_cw.visitMethod(ACC_PRIVATE, INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE, null, null);
567 cv.visitVarInsn(ALOAD, 0);
568
569 boolean hasAroundClosureBaseClass = false;
570 AspectModel aspectModel = null;
571
572 for (int i = 0; i < m_aspectModels.length; i++) {
573 aspectModel = m_aspectModels[i];
574 if (aspectModel.getAroundClosureClassInfo().getSuperClassName() != null) {
575 hasAroundClosureBaseClass = true;
576 break;
577 }
578 }
579
580 if (hasAroundClosureBaseClass) {
581
582 aspectModel.createInvocationOfAroundClosureSuperClass(cv);
583 } else {
584
585 cv.visitMethodInsn(INVOKESPECIAL, OBJECT_CLASS_NAME, INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE);
586 }
587
588 resetStackFrameCounter(cv);
589
590 cv.visitInsn(RETURN);
591 cv.visitMaxs(0, 0);
592 }
593
594 /***
595 * Creates the class header for the join point.
596 */
597 private void createClassHeader() {
598
599 Set interfaces = new HashSet();
600 String baseClass = OBJECT_CLASS_NAME;
601
602
603 for (int i = 0; i < m_aspectModels.length; i++) {
604 AspectModel aspectModel = m_aspectModels[i];
605 AspectModel.AroundClosureClassInfo closureClassInfo = aspectModel.getAroundClosureClassInfo();
606 final String superClassName = closureClassInfo.getSuperClassName();
607 final String[] interfaceNames = closureClassInfo.getInterfaceNames();
608 if (superClassName != null) {
609 if (!baseClass.equals(OBJECT_CLASS_NAME)) {
610 throw new RuntimeException(
611 "compiled join point can only subclass one around closure base class but more than registered aspect model requires a closure base class"
612 );
613 }
614 baseClass = superClassName;
615 }
616 if (interfaceNames.length != 0) {
617 for (int j = 0; j < interfaceNames.length; j++) {
618 interfaces.add(interfaceNames[j]);
619 }
620 }
621 }
622
623
624 for (Iterator it = m_customProceedMethodStructs.iterator(); it.hasNext();) {
625 MethodInfo methodInfo = ((CustomProceedMethodStruct) it.next()).customProceed;
626 interfaces.add(methodInfo.getDeclaringType().getName().replace('.', '/'));
627 }
628
629 int i = 1;
630 String[] interfaceArr = new String[interfaces.size() + 1];
631 interfaceArr[0] = getJoinPointInterface();
632 for (Iterator it = interfaces.iterator(); it.hasNext(); i++) {
633 interfaceArr[i] = (String) it.next();
634 }
635
636 m_cw.visit(
637 AsmHelper.JAVA_VERSION,
638 ACC_PUBLIC + ACC_SUPER,
639 m_joinPointClassName,
640 baseClass,
641 interfaceArr,
642 null
643 );
644 }
645
646 /***
647 * Creates the methods that are mandatory methods in the around closure in the different aspect models.
648 */
649 private void createMandatoryMethodInAspectModels() {
650 for (int i = 0; i < m_aspectModels.length; i++) {
651 m_aspectModels[i].createMandatoryMethods(m_cw, m_joinPointClassName);
652 }
653 }
654
655 /***
656 * Creates the custom proceed methods.
657 */
658 private void createCustomProceedMethods() {
659 Set addedMethodSignatures = new HashSet();
660 for (Iterator it = m_customProceedMethodStructs.iterator(); it.hasNext();) {
661 CustomProceedMethodStruct customProceedStruct = (CustomProceedMethodStruct) it.next();
662 MethodInfo methodInfo = customProceedStruct.customProceed;
663 final String desc = methodInfo.getSignature();
664
665 if (addedMethodSignatures.contains(desc)) {
666 continue;
667 }
668 addedMethodSignatures.add(desc);
669
670 CodeVisitor cv = m_cw.visitMethod(
671 ACC_PUBLIC | ACC_FINAL,
672 PROCEED_METHOD_NAME,
673 desc,
674 new String[]{
675 THROWABLE_CLASS_NAME
676 },
677 null
678 );
679
680
681
682
683 int argStackIndex = 1;
684 for (int i = 1; i < customProceedStruct.adviceToTargetArgs.length; i++) {
685 int targetArg = customProceedStruct.adviceToTargetArgs[i];
686 if (targetArg >= 0) {
687
688 String fieldName = m_fieldNames[targetArg];
689 cv.visitVarInsn(ALOAD, 0);
690 Type type = m_argumentTypes[targetArg];
691 argStackIndex = AsmHelper.loadType(cv, argStackIndex, type);
692 cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, fieldName, type.getDescriptor());
693 } else if (targetArg == AdviceInfo.TARGET_ARG) {
694 cv.visitVarInsn(ALOAD, 0);
695 argStackIndex = AsmHelper.loadType(cv, argStackIndex, Type.getType(m_calleeClassSignature));
696 cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
697 } else if (targetArg == AdviceInfo.THIS_ARG) {
698 cv.visitVarInsn(ALOAD, 0);
699 argStackIndex = AsmHelper.loadType(cv, argStackIndex, Type.getType(m_callerClassSignature));
700 cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
701 } else {
702 ;
703 }
704 }
705
706
707
708 Type returnType = Type.getType(customProceedStruct.customProceed.getReturnType().getSignature());
709 if (AsmHelper.isPrimitive(returnType)) {
710 cv.visitVarInsn(ALOAD, 0);
711 cv.visitMethodInsn(
712 INVOKESPECIAL,
713 m_joinPointClassName,
714 PROCEED_METHOD_NAME,
715 PROCEED_METHOD_SIGNATURE
716 );
717 AsmHelper.unwrapType(cv, returnType);
718 } else {
719 cv.visitVarInsn(ALOAD, 0);
720 cv.visitMethodInsn(
721 INVOKESPECIAL,
722 m_joinPointClassName,
723 PROCEED_METHOD_NAME,
724 PROCEED_METHOD_SIGNATURE
725 );
726 if (!returnType.getClassName().equals(OBJECT_CLASS_SIGNATURE)) {
727 cv.visitTypeInsn(CHECKCAST, returnType.getInternalName());
728 }
729 }
730 AsmHelper.addReturnStatement(cv, returnType);
731 cv.visitMaxs(0, 0);
732 }
733 }
734
735 /***
736 * Creates the static initialization method (not clinit) for the join point.
737 */
738 protected void createStaticInitializer() {
739 CodeVisitor cv = m_cw.visitMethod(
740 ACC_STATIC | ACC_PUBLIC,
741 STATIC_INITIALIZATION_METHOD_NAME,
742 NO_PARAM_RETURN_VOID_SIGNATURE,
743 null, null
744 );
745
746 Label tryLabel = new Label();
747 cv.visitLabel(tryLabel);
748 cv.visitLdcInsn(m_calleeClassName.replace('/', '.'));
749 cv.visitMethodInsn(INVOKESTATIC, CLASS_CLASS, FOR_NAME_METHOD_NAME, FOR_NAME_METHOD_SIGNATURE);
750 cv.visitFieldInsn(PUTSTATIC, m_joinPointClassName, TARGET_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
751
752 cv.visitLdcInsn(m_callerClassName.replace('/', '.'));
753 cv.visitMethodInsn(INVOKESTATIC, CLASS_CLASS, FOR_NAME_METHOD_NAME, FOR_NAME_METHOD_SIGNATURE);
754 cv.visitFieldInsn(PUTSTATIC, m_joinPointClassName, THIS_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
755
756 Label finallyLabel = new Label();
757 cv.visitLabel(finallyLabel);
758
759 Label gotoFinallyLabel = new Label();
760 cv.visitJumpInsn(GOTO, gotoFinallyLabel);
761
762 Label catchLabel = new Label();
763 cv.visitLabel(catchLabel);
764 cv.visitVarInsn(ASTORE, 0);
765
766 cv.visitVarInsn(ALOAD, 0);
767 cv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Throwable", "printStackTrace", "()V");
768
769 cv.visitTypeInsn(NEW, RUNTIME_EXCEPTION_CLASS_NAME);
770 cv.visitInsn(DUP);
771 cv.visitLdcInsn("could not load target class using Class.forName() in generated join point base class "
772 + m_joinPointClassName);
773
774 cv.visitMethodInsn(
775 INVOKESPECIAL,
776 RUNTIME_EXCEPTION_CLASS_NAME,
777 INIT_METHOD_NAME,
778 RUNTIME_EXCEPTION_INIT_METHOD_SIGNATURE
779 );
780
781 cv.visitInsn(ATHROW);
782 cv.visitLabel(gotoFinallyLabel);
783
784
785 createEnclosingStaticJoinPoint(cv);
786
787
788 cv.visitTypeInsn(NEW, HASH_MAP_CLASS_NAME);
789 cv.visitInsn(DUP);
790 cv.visitMethodInsn(INVOKESPECIAL, HASH_MAP_CLASS_NAME, INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE);
791 cv.visitFieldInsn(PUTSTATIC, m_joinPointClassName, META_DATA_FIELD_NAME, MAP_CLASS_SIGNATURE);
792
793
794 createSignature(cv);
795
796
797 cv.visitTypeInsn(NEW, m_joinPointClassName);
798 cv.visitInsn(DUP);
799 cv.visitMethodInsn(INVOKESPECIAL, m_joinPointClassName, INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE);
800 cv.visitFieldInsn(
801 PUTSTATIC,
802 m_joinPointClassName,
803 OPTIMIZED_JOIN_POINT_INSTANCE_FIELD_NAME,
804 L + m_joinPointClassName + SEMICOLON
805 );
806
807
808 for (int i = 0; i < m_aspectInfos.length; i++) {
809 createAndInitializeAspectField(m_aspectInfos[i], cv);
810 }
811
812 cv.visitInsn(RETURN);
813 cv.visitTryCatchBlock(tryLabel, finallyLabel, catchLabel, CLASS_NOT_FOUND_EXCEPTION_CLASS_NAME);
814 cv.visitMaxs(0, 0);
815 }
816
817 /***
818 * Add and initialize the static field for enclosing joint point static part
819 *
820 * @param cv
821 */
822 protected void createEnclosingStaticJoinPoint(CodeVisitor cv) {
823 cv.visitFieldInsn(GETSTATIC,
824 m_joinPointClassName,
825 THIS_CLASS_FIELD_NAME,
826 CLASS_CLASS_SIGNATURE);
827 cv.visitLdcInsn(m_callerMethodName);
828 cv.visitLdcInsn(m_callerMethodDesc);
829
830 cv.visitMethodInsn(INVOKESTATIC,
831 SIGNATURE_FACTORY_CLASS,
832 NEW_ENCLOSING_SJP_METHOD_NAME,
833 NEW_ENCLOSING_SJP_METHOD_SIGNATURE);
834 cv.visitFieldInsn(
835 PUTSTATIC,
836 m_joinPointClassName,
837 ENCLOSING_SJP_FIELD_NAME,
838 ENCLOSING_SJP_FIELD_CLASS_SIGNATURE);
839 }
840
841 /***
842 * Create and initialize the aspect field for a specific aspect (qualified since it depends
843 * on the param, deployment model, container etc).
844 *
845 * @param aspectInfo
846 * @param cv
847 */
848 protected boolean createAndInitializeAspectField(final AspectInfo aspectInfo, final CodeVisitor cv) {
849 if (aspectInfo.getAspectDefinition().isAspectWerkzAspect()) {
850
851
852 createAspectReferenceField(m_cw, aspectInfo);
853 createAspectInstantiation(cv, aspectInfo, m_joinPointClassName);
854 } else {
855
856 final String type = aspectInfo.getAspectDefinition().getAspectModel();
857 final AspectModel aspectModel = AspectModelManager.getModelFor(type);
858 aspectModel.createAspectReferenceField(m_cw, aspectInfo, m_joinPointClassName);
859 aspectModel.createAspectInstantiation(cv, aspectInfo, m_joinPointClassName);
860 }
861
862 return false;
863 }
864
865 /***
866 * Creates aspect reference field (static or non static field).
867 *
868 * @param cw
869 * @param aspectInfo
870 */
871 public static void createAspectReferenceField(final ClassWriter cw,
872 final AspectInfo aspectInfo) {
873 String aspectClassSignature = aspectInfo.getAspectClassSignature();
874
875
876 DeploymentModel deploymentModel = aspectInfo.getDeploymentModel();
877 if (deploymentModel.equals(DeploymentModel.PER_JVM) ||
878 deploymentModel.equals(DeploymentModel.PER_CLASS)) {
879
880 cw.visitField(ACC_PRIVATE + ACC_STATIC, aspectInfo.getAspectFieldName(), aspectClassSignature, null, null);
881 } else if (deploymentModel.equals(DeploymentModel.PER_INSTANCE)) {
882
883
884
885 cw.visitField(ACC_PRIVATE, aspectInfo.getAspectFieldName(), aspectClassSignature, null, null);
886 } else {
887 throw new UnsupportedOperationException(
888 "unsupported deployment model - " +
889 aspectInfo.getAspectClassName() + " " +
890 deploymentModel
891 );
892 }
893 }
894
895 /***
896 * Creates instantiation of aspects using the Aspects.aspectOf() methods which uses the AspectContainer impls.
897 * We are using the THIS_CLASS classloader since the aspect can be visible from that one only f.e. for get/set/call
898 *
899 * @param cv
900 * @param aspectInfo
901 * @param joinPointClassName
902 */
903 public static void createAspectInstantiation(final CodeVisitor cv,
904 final AspectInfo aspectInfo,
905 final String joinPointClassName) {
906 String aspectClassSignature = aspectInfo.getAspectClassSignature();
907 String aspectClassName = aspectInfo.getAspectClassName();
908
909 DeploymentModel deploymentModel = aspectInfo.getDeploymentModel();
910 if (CflowCompiler.isCflowClass(aspectClassName)) {
911
912 cv.visitMethodInsn(
913 INVOKESTATIC,
914 aspectClassName,
915 CflowCompiler.CFLOW_ASPECTOF_METHOD_NAME,
916 "()"+aspectClassSignature
917 );
918 cv.visitFieldInsn(PUTSTATIC, joinPointClassName, aspectInfo.getAspectFieldName(), aspectClassSignature);
919 } else if (deploymentModel.equals(DeploymentModel.PER_JVM)) {
920
921 cv.visitFieldInsn(GETSTATIC, joinPointClassName, THIS_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
922 cv.visitMethodInsn(
923 INVOKEVIRTUAL, CLASS_CLASS, GETCLASSLOADER_METHOD_NAME,
924 CLASS_CLASS_GETCLASSLOADER_METHOD_SIGNATURE
925 );
926 cv.visitLdcInsn(aspectInfo.getAspectQualifiedName());
927 cv.visitLdcInsn(aspectInfo.getAspectDefinition().getContainerClassName());
928 cv.visitMethodInsn(
929 INVOKESTATIC,
930 ASPECTS_CLASS_NAME,
931 ASPECT_OF_METHOD_NAME,
932 ASPECT_OF_PER_JVM_METHOD_SIGNATURE
933 );
934 cv.visitTypeInsn(CHECKCAST, aspectClassName);
935 cv.visitFieldInsn(PUTSTATIC, joinPointClassName, aspectInfo.getAspectFieldName(), aspectClassSignature);
936 } else if (deploymentModel.equals(DeploymentModel.PER_CLASS)) {
937 cv.visitLdcInsn(aspectInfo.getAspectQualifiedName());
938 cv.visitLdcInsn(aspectInfo.getAspectDefinition().getContainerClassName());
939 cv.visitFieldInsn(GETSTATIC, joinPointClassName, THIS_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
940 cv.visitMethodInsn(
941 INVOKESTATIC,
942 ASPECTS_CLASS_NAME,
943 ASPECT_OF_METHOD_NAME,
944 ASPECT_OF_PER_CLASS_METHOD_SIGNATURE
945 );
946 cv.visitTypeInsn(CHECKCAST, aspectClassName);
947 cv.visitFieldInsn(PUTSTATIC, joinPointClassName, aspectInfo.getAspectFieldName(), aspectClassSignature);
948 } else if (deploymentModel.equals(DeploymentModel.PER_INSTANCE)) {
949 } else {
950 throw new UnsupportedOperationException(
951 "unsupported deployment model - " +
952 aspectInfo.getAspectClassName() + " " +
953 deploymentModel
954 );
955 }
956 }
957
958 /***
959 * Creates the 'invoke' method. If possible delegates to the target join point directly, e.g. does not invoke the
960 * 'proceed' method (Used when a join point has zero around advice).
961 */
962 protected void createInvokeMethod() {
963
964 final String invokeDesc = buildInvokeMethodSignature();
965
966
967 CodeVisitor cv = m_cw.visitMethod(
968 ACC_PUBLIC + ACC_FINAL + ACC_STATIC,
969 INVOKE_METHOD_NAME,
970 invokeDesc,
971 new String[]{
972 THROWABLE_CLASS_NAME
973 },
974 null
975 );
976
977
978 int calleeIndex = INDEX_NOTAVAILABLE;
979 int argStartIndex = 0;
980 if (!Modifier.isStatic(m_calleeMemberModifiers) &&
981 m_joinPointType != JoinPointType.CONSTRUCTOR_CALL_INT &&
982 m_joinPointType != JoinPointType.HANDLER_INT) {
983 calleeIndex = 0;
984 argStartIndex++;
985 } else {
986 calleeIndex = INDEX_NOTAVAILABLE;
987 }
988 int callerIndex = argStartIndex + AsmHelper.getRegisterDepth(m_argumentTypes);
989
990
991 if (m_joinPointType == JoinPointType.HANDLER_INT) {
992 calleeIndex = 0;
993 callerIndex = 2;
994 argStartIndex = 1;
995 }
996
997
998
999
1000 final boolean isOptimizedJoinPoint = !m_requiresJoinPoint && !requiresProceedMethod();
1001 int joinPointIndex = INDEX_NOTAVAILABLE;
1002
1003 if (!isOptimizedJoinPoint) {
1004
1005 joinPointIndex = callerIndex + 1;
1006 createInvocationLocalJoinPointInstance(cv, argStartIndex, joinPointIndex, callerIndex, calleeIndex);
1007 }
1008
1009
1010 initializeInstanceLevelAspects(cv, isOptimizedJoinPoint, joinPointIndex, callerIndex, calleeIndex);
1011
1012
1013 createBeforeAdviceInvocations(
1014 cv, isOptimizedJoinPoint, argStartIndex, joinPointIndex, callerIndex, calleeIndex
1015 );
1016
1017
1018 if (m_afterFinallyAdviceMethodInfos.length == 0 &&
1019 m_afterThrowingAdviceMethodInfos.length == 0 &&
1020 !m_isThisAdvisable) {
1021 createPartOfInvokeMethodWithoutAfterFinallyAndAfterThrowingAdviceTypes(
1022 cv, isOptimizedJoinPoint, joinPointIndex, argStartIndex, callerIndex, calleeIndex
1023 );
1024 } else if (m_afterThrowingAdviceMethodInfos.length == 0 &&
1025 !m_isThisAdvisable) {
1026 createPartOfInvokeMethodWithoutAfterThrowingAdviceTypes(
1027 cv, isOptimizedJoinPoint, joinPointIndex, argStartIndex, callerIndex, calleeIndex
1028 );
1029 } else {
1030 createPartOfInvokeMethodWithAllAdviceTypes(
1031 cv, OPTIMIZED_JOIN_POINT, joinPointIndex, argStartIndex, callerIndex, calleeIndex
1032 );
1033 }
1034
1035 cv.visitMaxs(0, 0);
1036 }
1037
1038 /***
1039 * Initializes instance level aspects, retrieves them from the target instance through the
1040 * <code>HasInstanceLevelAspect</code> interfaces.
1041 * <p/>
1042 * Use by 'perInstance', 'perThis' and 'perTarget' deployment models.
1043 *
1044 * @param cv
1045 * @param isOptimizedJoinPoint
1046 * @param joinPointIndex
1047 * @param callerIndex
1048 * @param calleeIndex
1049 */
1050 protected void initializeInstanceLevelAspects(final CodeVisitor cv,
1051 final boolean isOptimizedJoinPoint,
1052 final int joinPointIndex,
1053 final int callerIndex,
1054 final int calleeIndex) {
1055 for (int i = 0; i < m_aspectInfos.length; i++) {
1056 AspectInfo aspectInfo = m_aspectInfos[i];
1057 if (aspectInfo.getDeploymentModel() == DeploymentModel.PER_INSTANCE) {
1058
1059 loadJoinPointInstance(cv, isOptimizedJoinPoint, joinPointIndex);
1060 if (callerIndex >= 0) {
1061 cv.visitVarInsn(ALOAD, callerIndex);
1062 } else {
1063
1064
1065 }
1066 cv.visitLdcInsn(aspectInfo.getAspectClassName().replace('/', '.'));
1067 cv.visitLdcInsn(aspectInfo.getAspectQualifiedName());
1068 cv.visitLdcInsn(aspectInfo.getAspectDefinition().getContainerClassName());
1069 cv.visitMethodInsn(
1070 INVOKEINTERFACE,
1071 HAS_INSTANCE_LEVEL_ASPECT_INTERFACE_NAME,
1072 GET_INSTANCE_LEVEL_ASPECT_METHOD_NAME,
1073 GET_INSTANCE_LEVEL_ASPECT_METHOD_SIGNATURE
1074 );
1075 cv.visitTypeInsn(CHECKCAST, aspectInfo.getAspectClassName());
1076 cv.visitFieldInsn(
1077 PUTFIELD,
1078 m_joinPointClassName,
1079 aspectInfo.getAspectFieldName(),
1080 aspectInfo.getAspectClassSignature()
1081 );
1082 }
1083 }
1084 }
1085
1086 /***
1087 * @param cv
1088 * @param isOptimizedJoinPoint
1089 * @param joinPointInstanceIndex
1090 * @param argStartIndex
1091 * @param callerIndex
1092 * @param calleeIndex
1093 */
1094 protected void createPartOfInvokeMethodWithAllAdviceTypes(final CodeVisitor cv,
1095 final boolean isOptimizedJoinPoint,
1096 final int joinPointInstanceIndex,
1097 final int argStartIndex,
1098 final int callerIndex,
1099 final int calleeIndex) {
1100 final int returnValueIndex = (joinPointInstanceIndex != INDEX_NOTAVAILABLE) ?
1101 (joinPointInstanceIndex + 1) : callerIndex + 1;
1102 final int exceptionIndex1 = returnValueIndex + 1;
1103 final int exceptionIndex2 = returnValueIndex + 2;
1104
1105 cv.visitInsn(ACONST_NULL);
1106 cv.visitVarInsn(ASTORE, returnValueIndex);
1107
1108 Label tryLabel = new Label();
1109 cv.visitLabel(tryLabel);
1110 if (!requiresProceedMethod()) {
1111
1112 createInlinedJoinPointInvocation(cv, isOptimizedJoinPoint, argStartIndex, joinPointInstanceIndex);
1113 int stackIndex = returnValueIndex;
1114 AsmHelper.storeType(cv, stackIndex, m_returnType);
1115 addReturnedValueToJoinPoint(cv, returnValueIndex, joinPointInstanceIndex, false);
1116 } else {
1117 createInvocationToProceedMethod(cv, joinPointInstanceIndex, returnValueIndex);
1118 }
1119
1120 createAfterReturningAdviceInvocations(
1121 cv, isOptimizedJoinPoint, argStartIndex, joinPointInstanceIndex,
1122 callerIndex, calleeIndex
1123 );
1124
1125 Label finallyLabel1 = new Label();
1126 cv.visitLabel(finallyLabel1);
1127
1128 if (m_isThisAdvisable) {
1129 final int registerDepth = callerIndex + 2;
1130 createAfterInterceptorInvocations(cv, joinPointInstanceIndex, registerDepth);
1131 }
1132 createAfterFinallyAdviceInvocations(
1133 cv, isOptimizedJoinPoint, argStartIndex, joinPointInstanceIndex,
1134 callerIndex, calleeIndex
1135 );
1136
1137 Label gotoFinallyLabel = new Label();
1138 cv.visitJumpInsn(GOTO, gotoFinallyLabel);
1139
1140 Label catchLabel = new Label();
1141 cv.visitLabel(catchLabel);
1142
1143
1144 cv.visitVarInsn(ASTORE, exceptionIndex1);
1145
1146 if (m_isThisAdvisable) {
1147 createAfterThrowingInterceptorInvocations(cv, joinPointInstanceIndex, exceptionIndex1);
1148 }
1149
1150
1151 for (int i = m_afterThrowingAdviceMethodInfos.length - 1; i >= 0; i--) {
1152 AdviceMethodInfo advice = m_afterThrowingAdviceMethodInfos[i];
1153
1154
1155 advice.setSpecialArgumentIndex(exceptionIndex1);
1156
1157
1158 cv.visitVarInsn(ALOAD, exceptionIndex1);
1159
1160 final String specialArgTypeName = advice.getSpecialArgumentTypeName();
1161 if (specialArgTypeName != null) {
1162
1163 cv.visitTypeInsn(INSTANCEOF, specialArgTypeName);
1164
1165 Label ifInstanceOfLabel = new Label();
1166 cv.visitJumpInsn(IFEQ, ifInstanceOfLabel);
1167
1168
1169 createAfterAdviceInvocation(
1170 cv, isOptimizedJoinPoint, advice, joinPointInstanceIndex,
1171 argStartIndex, callerIndex, calleeIndex, exceptionIndex1
1172 );
1173
1174 cv.visitLabel(ifInstanceOfLabel);
1175 } else {
1176
1177 createAfterAdviceInvocation(
1178 cv, isOptimizedJoinPoint, advice, joinPointInstanceIndex,
1179 argStartIndex, callerIndex, calleeIndex, INDEX_NOTAVAILABLE
1180 );
1181 }
1182 }
1183
1184
1185 cv.visitVarInsn(ALOAD, exceptionIndex1);
1186 cv.visitInsn(ATHROW);
1187
1188
1189 Label exceptionLabel = new Label();
1190 cv.visitLabel(exceptionLabel);
1191 cv.visitVarInsn(ASTORE, exceptionIndex2);
1192
1193
1194 Label finallyLabel2 = new Label();
1195 cv.visitLabel(finallyLabel2);
1196
1197 if (m_isThisAdvisable) {
1198 final int registerDepth = callerIndex + 2;
1199 createAfterInterceptorInvocations(cv, joinPointInstanceIndex, registerDepth);
1200 }
1201 createAfterFinallyAdviceInvocations(
1202 cv, isOptimizedJoinPoint, argStartIndex, joinPointInstanceIndex,
1203 callerIndex, calleeIndex
1204 );
1205
1206
1207 cv.visitVarInsn(ALOAD, exceptionIndex2);
1208 cv.visitInsn(ATHROW);
1209 cv.visitLabel(gotoFinallyLabel);
1210
1211
1212 if (m_returnType.getSort() != Type.VOID) {
1213 if (requiresProceedMethod()) {
1214 cv.visitVarInsn(ALOAD, returnValueIndex);
1215 AsmHelper.unwrapType(cv, m_returnType);
1216 } else {
1217 AsmHelper.loadType(cv, returnValueIndex, m_returnType);
1218 }
1219 }
1220
1221 AsmHelper.addReturnStatement(cv, m_returnType);
1222
1223
1224 cv.visitTryCatchBlock(tryLabel, finallyLabel1, catchLabel, THROWABLE_CLASS_NAME);
1225 cv.visitTryCatchBlock(tryLabel, finallyLabel1, exceptionLabel, null);
1226 cv.visitTryCatchBlock(catchLabel, finallyLabel2, exceptionLabel, null);
1227 }
1228
1229 /***
1230 * @param cv
1231 * @param isOptimizedJoinPoint
1232 * @param joinPointInstanceIndex
1233 * @param argStartIndex
1234 * @param callerIndex
1235 * @param calleeIndex
1236 */
1237 protected void createPartOfInvokeMethodWithoutAfterThrowingAdviceTypes(final CodeVisitor cv,
1238 final boolean isOptimizedJoinPoint,
1239 final int joinPointInstanceIndex,
1240 final int argStartIndex,
1241 final int callerIndex,
1242 final int calleeIndex) {
1243 final int returnValueIndex = (joinPointInstanceIndex != INDEX_NOTAVAILABLE) ?
1244 (joinPointInstanceIndex + 1) : callerIndex + 1;
1245 final int exceptionIndex = returnValueIndex + 1;
1246
1247 cv.visitInsn(ACONST_NULL);
1248 cv.visitVarInsn(ASTORE, returnValueIndex);
1249
1250 Label tryLabel = new Label();
1251 cv.visitLabel(tryLabel);
1252 if (!requiresProceedMethod()) {
1253
1254 createInlinedJoinPointInvocation(cv, isOptimizedJoinPoint, argStartIndex, joinPointInstanceIndex);
1255 int stackIndex = returnValueIndex;
1256 AsmHelper.storeType(cv, stackIndex, m_returnType);
1257 addReturnedValueToJoinPoint(cv, returnValueIndex, joinPointInstanceIndex, false);
1258 } else {
1259 createInvocationToProceedMethod(cv, joinPointInstanceIndex, returnValueIndex);
1260 }
1261
1262 createAfterReturningAdviceInvocations(
1263 cv, isOptimizedJoinPoint, argStartIndex, joinPointInstanceIndex,
1264 callerIndex, calleeIndex
1265 );
1266
1267 Label finallyLabel1 = new Label();
1268 cv.visitLabel(finallyLabel1);
1269
1270 createAfterFinallyAdviceInvocations(
1271 cv, isOptimizedJoinPoint, argStartIndex, joinPointInstanceIndex,
1272 callerIndex, calleeIndex
1273 );
1274
1275 Label gotoFinallyLabel = new Label();
1276 cv.visitJumpInsn(GOTO, gotoFinallyLabel);
1277
1278 Label exceptionLabel = new Label();
1279 cv.visitLabel(exceptionLabel);
1280 cv.visitVarInsn(ASTORE, exceptionIndex);
1281
1282 Label finallyLabel2 = new Label();
1283 cv.visitLabel(finallyLabel2);
1284
1285 createAfterFinallyAdviceInvocations(
1286 cv, isOptimizedJoinPoint, argStartIndex, joinPointInstanceIndex,
1287 callerIndex, calleeIndex
1288 );
1289
1290 cv.visitVarInsn(ALOAD, exceptionIndex);
1291 cv.visitInsn(ATHROW);
1292
1293 cv.visitLabel(gotoFinallyLabel);
1294
1295
1296 if (m_returnType.getSort() != Type.VOID) {
1297 if (requiresProceedMethod()) {
1298 cv.visitVarInsn(ALOAD, returnValueIndex);
1299 AsmHelper.unwrapType(cv, m_returnType);
1300 } else {
1301 AsmHelper.loadType(cv, returnValueIndex, m_returnType);
1302 }
1303 }
1304
1305 AsmHelper.addReturnStatement(cv, m_returnType);
1306
1307 cv.visitTryCatchBlock(tryLabel, finallyLabel1, exceptionLabel, null);
1308 cv.visitTryCatchBlock(exceptionLabel, finallyLabel2, exceptionLabel, null);
1309 }
1310
1311 /***
1312 * @param cv
1313 * @param isOptimizedJoinPoint
1314 * @param joinPointInstanceIndex
1315 * @param argStartIndex
1316 * @param callerIndex
1317 * @param calleeIndex
1318 */
1319 protected void createPartOfInvokeMethodWithoutAfterFinallyAndAfterThrowingAdviceTypes(final CodeVisitor cv,
1320 final boolean isOptimizedJoinPoint,
1321 final int joinPointInstanceIndex,
1322 final int argStartIndex,
1323 final int callerIndex,
1324 final int calleeIndex) {
1325
1326 final int returnValueIndex = (joinPointInstanceIndex != INDEX_NOTAVAILABLE) ?
1327 (joinPointInstanceIndex + 1) : callerIndex + 1;
1328 if (!requiresProceedMethod()) {
1329
1330 createInlinedJoinPointInvocation(cv, isOptimizedJoinPoint, argStartIndex, joinPointInstanceIndex);
1331 int stackIndex = returnValueIndex;
1332 AsmHelper.storeType(cv, stackIndex, m_returnType);
1333 addReturnedValueToJoinPoint(cv, returnValueIndex, joinPointInstanceIndex, false);
1334 } else {
1335 createInvocationToProceedMethod(cv, joinPointInstanceIndex, returnValueIndex);
1336 }
1337
1338
1339
1340 createAfterReturningAdviceInvocations(
1341 cv, isOptimizedJoinPoint, argStartIndex, joinPointInstanceIndex,
1342 callerIndex, calleeIndex
1343 );
1344
1345
1346 if (m_returnType.getSort() != Type.VOID) {
1347 if (requiresProceedMethod()) {
1348 cv.visitVarInsn(ALOAD, returnValueIndex);
1349 AsmHelper.unwrapType(cv, m_returnType);
1350 } else {
1351 AsmHelper.loadType(cv, returnValueIndex, m_returnType);
1352 }
1353 }
1354
1355 AsmHelper.addReturnStatement(cv, m_returnType);
1356 }
1357
1358 /***
1359 * Creates an invocation to the proceed method.
1360 *
1361 * @param cv
1362 * @param joinPointInstanceIndex
1363 * @param returnValueIndex
1364 */
1365 protected void createInvocationToProceedMethod(final CodeVisitor cv,
1366 final int joinPointInstanceIndex,
1367 final int returnValueIndex) {
1368 cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
1369 cv.visitMethodInsn(INVOKEVIRTUAL, m_joinPointClassName, PROCEED_METHOD_NAME, PROCEED_METHOD_SIGNATURE);
1370 cv.visitVarInsn(ASTORE, returnValueIndex);
1371 }
1372
1373 /***
1374 * Creates an "invocation local" join point instance, e.g. one join point per invocation. Needed for thread-safety
1375 * when invoking around advice.
1376 *
1377 * @param cv
1378 * @param argStartIndex index on stack of first target method arg (0 or 1, depends of static target or
1379 * not)
1380 * @param joinPointInstanceIndex
1381 * @param callerIndex
1382 * @param calleeIndex
1383 */
1384 protected void createInvocationLocalJoinPointInstance(final CodeVisitor cv,
1385 final int argStartIndex,
1386 final int joinPointInstanceIndex,
1387 final int callerIndex,
1388 final int calleeIndex) {
1389
1390 cv.visitTypeInsn(NEW, m_joinPointClassName);
1391 cv.visitInsn(DUP);
1392 cv.visitMethodInsn(INVOKESPECIAL, m_joinPointClassName, INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE);
1393
1394
1395 cv.visitVarInsn(ASTORE, joinPointInstanceIndex);
1396
1397
1398 int argStackIndex = argStartIndex;
1399 for (int i = 0; i < m_fieldNames.length; i++) {
1400 String fieldName = m_fieldNames[i];
1401 cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
1402 Type type = m_argumentTypes[i];
1403 argStackIndex = AsmHelper.loadType(cv, argStackIndex, type);
1404 cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, fieldName, type.getDescriptor());
1405 }
1406
1407
1408 cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
1409 cv.visitVarInsn(ALOAD, callerIndex);
1410 cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
1411
1412
1413 cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
1414 if (calleeIndex != INDEX_NOTAVAILABLE) {
1415 cv.visitVarInsn(ALOAD, 0);
1416 } else {
1417 cv.visitInsn(ACONST_NULL);
1418 }
1419 cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
1420
1421 if (m_isThisAdvisable) {
1422 createInitializationForAdvisableManagement(cv, joinPointInstanceIndex, callerIndex);
1423 }
1424 }
1425
1426 /***
1427 * Create the proceed() method.
1428 */
1429 protected void createProceedMethod() {
1430
1431 CodeVisitor cv = m_cw.visitMethod(
1432 ACC_PUBLIC | ACC_FINAL,
1433 PROCEED_METHOD_NAME,
1434 PROCEED_METHOD_SIGNATURE,
1435 new String[]{
1436 THROWABLE_CLASS_NAME
1437 },
1438 null
1439 );
1440
1441 if (m_isThisAdvisable) {
1442 createAroundInterceptorInvocations(cv);
1443 }
1444
1445 incrementStackFrameCounter(cv);
1446
1447
1448 Label tryLabel = new Label();
1449 Label defaultCaseLabel = new Label();
1450 Label gotoLabel = new Label();
1451 Label handlerLabel = new Label();
1452 Label endLabel = new Label();
1453
1454 int nrOfCases = m_aroundAdviceMethodInfos.length;
1455 if (m_isThisAdvisable) {
1456 nrOfCases++;
1457 }
1458
1459 Label[] caseLabels = new Label[nrOfCases];
1460 Label[] returnLabels = new Label[nrOfCases];
1461 int[] caseNumbers = new int[nrOfCases];
1462 for (int i = 0; i < caseLabels.length; i++) {
1463 caseLabels[i] = new Label();
1464 caseNumbers[i] = i;
1465 }
1466 for (int i = 0; i < returnLabels.length; i++) {
1467 returnLabels[i] = new Label();
1468 }
1469
1470
1471 cv.visitLabel(tryLabel);
1472
1473
1474 cv.visitVarInsn(ALOAD, 0);
1475 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, STACK_FRAME_COUNTER_FIELD_NAME, I);
1476 cv.visitLookupSwitchInsn(defaultCaseLabel, caseNumbers, caseLabels);
1477
1478
1479 for (int i = 0; i < m_aroundAdviceMethodInfos.length; i++) {
1480 cv.visitLabel(caseLabels[i]);
1481
1482
1483 AdviceMethodInfo adviceInfo = m_aroundAdviceMethodInfos[i];
1484
1485 Label endInstanceOflabel = beginRuntimeCheck(cv, false, 0, adviceInfo.getAdviceInfo(), -1);
1486
1487
1488 loadAspect(cv, NON_OPTIMIZED_JOIN_POINT, 0, adviceInfo.getAspectInfo());
1489
1490
1491
1492 int[] argIndexes = adviceInfo.getAdviceMethodArgIndexes();
1493 for (int j = 0; j < argIndexes.length; j++) {
1494 int argIndex = argIndexes[j];
1495 if (argIndex >= 0) {
1496 Type argumentType = m_argumentTypes[argIndex];
1497 cv.visitVarInsn(ALOAD, 0);
1498 cv.visitFieldInsn(
1499 GETFIELD,
1500 m_joinPointClassName,
1501 ARGUMENT_FIELD + argIndex,
1502 argumentType.getDescriptor()
1503 );
1504 } else if (argIndex == AdviceInfo.JOINPOINT_ARG ||
1505 argIndex == AdviceInfo.STATIC_JOINPOINT_ARG ||
1506 argIndex == AdviceInfo.VALID_NON_AW_AROUND_CLOSURE_TYPE ||
1507 argIndex == AdviceInfo.CUSTOM_JOIN_POINT_ARG) {
1508 cv.visitVarInsn(ALOAD, 0);
1509 } else if (argIndex == AdviceInfo.TARGET_ARG) {
1510 loadCallee(cv, NON_OPTIMIZED_JOIN_POINT, 0, INDEX_NOTAVAILABLE);
1511
1512 if (adviceInfo.getAdviceInfo().hasTargetWithRuntimeCheck()) {
1513 cv.visitTypeInsn(
1514 CHECKCAST, adviceInfo.getAdviceInfo().getMethodParameterTypes()[j].getInternalName()
1515 );
1516 }
1517 } else if (argIndex == AdviceInfo.THIS_ARG) {
1518 loadCaller(cv, NON_OPTIMIZED_JOIN_POINT, 0, INDEX_NOTAVAILABLE);
1519 } else {
1520 throw new Error("advice method argument index type is not supported: " + argIndex);
1521 }
1522 }
1523
1524
1525 cv.visitMethodInsn(
1526 INVOKEVIRTUAL,
1527 adviceInfo.getAspectInfo().getAspectClassName(),
1528 adviceInfo.getAdviceInfo().getMethodName(),
1529 adviceInfo.getAdviceInfo().getMethodSignature()
1530 );
1531 cv.visitVarInsn(ASTORE, 1);
1532
1533
1534
1535 if (endInstanceOflabel != null) {
1536 Label elseInstanceOfLabel = new Label();
1537 cv.visitJumpInsn(GOTO, elseInstanceOfLabel);
1538 endRuntimeCheck(cv, adviceInfo.getAdviceInfo(), endInstanceOflabel);
1539 cv.visitVarInsn(ALOAD, 0);
1540 cv.visitMethodInsn(INVOKESPECIAL, m_joinPointClassName, PROCEED_METHOD_NAME, PROCEED_METHOD_SIGNATURE);
1541 cv.visitVarInsn(ASTORE, 1);
1542 cv.visitLabel(elseInstanceOfLabel);
1543 }
1544
1545 cv.visitLabel(returnLabels[i]);
1546
1547 cv.visitVarInsn(ALOAD, 1);
1548 cv.visitInsn(ARETURN);
1549 }
1550
1551 if (m_isThisAdvisable) {
1552 int delegationCaseIndex = caseLabels.length - 1;
1553 cv.visitLabel(caseLabels[delegationCaseIndex]);
1554 cv.visitVarInsn(ALOAD, 0);
1555 cv.visitInsn(ICONST_0);
1556 cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
1557 cv.visitVarInsn(ALOAD, 0);
1558 cv.visitMethodInsn(INVOKEVIRTUAL, m_joinPointClassName, PROCEED_METHOD_NAME, PROCEED_METHOD_SIGNATURE);
1559
1560 cv.visitLabel(returnLabels[delegationCaseIndex]);
1561
1562 cv.visitInsn(ARETURN);
1563 }
1564
1565
1566 cv.visitLabel(defaultCaseLabel);
1567
1568 AsmHelper.prepareWrappingOfPrimitiveType(cv, Type.getReturnType(m_calleeMemberDesc));
1569
1570 createJoinPointInvocation(cv);
1571
1572 Type m_returnType = null;
1573 if (m_joinPointType != JoinPointType.CONSTRUCTOR_CALL_INT) {
1574 m_returnType = Type.getReturnType(m_calleeMemberDesc);
1575 } else {
1576 m_returnType = Type.getType(m_calleeClassSignature);
1577 }
1578 AsmHelper.wrapPrimitiveType(cv, m_returnType);
1579 cv.visitVarInsn(ASTORE, 1);
1580
1581
1582 addReturnedValueToJoinPoint(cv, 1, 0, true);
1583
1584
1585 if (m_joinPointType == JoinPointType.CONSTRUCTOR_CALL_INT) {
1586 cv.visitVarInsn(ALOAD, 0);
1587 cv.visitVarInsn(ALOAD, 1);
1588 cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
1589 }
1590
1591 cv.visitLabel(gotoLabel);
1592
1593 cv.visitVarInsn(ALOAD, 1);
1594 cv.visitInsn(ARETURN);
1595
1596
1597 cv.visitLabel(handlerLabel);
1598 cv.visitVarInsn(ASTORE, 2);
1599 cv.visitLabel(endLabel);
1600
1601 cv.visitVarInsn(ALOAD, 2);
1602 cv.visitInsn(ATHROW);
1603
1604
1605 cv.visitTryCatchBlock(tryLabel, returnLabels[0], handlerLabel, null);
1606 for (int i = 1; i < caseLabels.length; i++) {
1607 Label caseLabel = caseLabels[i];
1608 Label returnLabel = returnLabels[i];
1609 cv.visitTryCatchBlock(caseLabel, returnLabel, handlerLabel, null);
1610 }
1611 cv.visitTryCatchBlock(defaultCaseLabel, gotoLabel, handlerLabel, null);
1612 cv.visitTryCatchBlock(handlerLabel, endLabel, handlerLabel, null);
1613 cv.visitMaxs(0, 0);
1614 }
1615
1616 /***
1617 * Adds before advice invocations.
1618 *
1619 * @param cv
1620 * @param isOptimizedJoinPoint
1621 * @param argStartIndex index on stack of first target method arg (0 or 1, depends of static target or
1622 * not)
1623 * @param joinPointInstanceIndex >= 0 if STATIC_JOIN_POINT is NOT to be used (around advice)
1624 * @param callerIndex
1625 * @param calleeIndex
1626 */
1627 protected void createBeforeAdviceInvocations(final CodeVisitor cv,
1628 final boolean isOptimizedJoinPoint,
1629 final int argStartIndex,
1630 final int joinPointInstanceIndex,
1631 final int callerIndex,
1632 final int calleeIndex) {
1633 for (int i = 0; i < m_beforeAdviceMethodInfos.length; i++) {
1634 AdviceMethodInfo adviceMethodInfo = m_beforeAdviceMethodInfos[i];
1635
1636
1637 Label endInstanceOflabel = beginRuntimeCheck(
1638 cv, isOptimizedJoinPoint, joinPointInstanceIndex, adviceMethodInfo.getAdviceInfo(), calleeIndex
1639 );
1640
1641
1642 loadAspect(cv, isOptimizedJoinPoint, joinPointInstanceIndex, adviceMethodInfo.getAspectInfo());
1643
1644 AspectDefinition aspectDef = adviceMethodInfo.getAdviceInfo().getAdviceDefinition().getAspectDefinition();
1645 if (aspectDef.isAspectWerkzAspect()) {
1646
1647 int[] argIndexes = adviceMethodInfo.getAdviceMethodArgIndexes();
1648
1649 for (int j = 0; j < argIndexes.length; j++) {
1650 int argIndex = argIndexes[j];
1651 if (argIndex >= 0) {
1652 Type argumentType = m_argumentTypes[argIndex];
1653 int argStackIndex = AsmHelper.getRegisterIndexOf(m_argumentTypes, argIndex) + argStartIndex;
1654 AsmHelper.loadType(cv, argStackIndex, argumentType);
1655 } else if (argIndex == AdviceInfo.JOINPOINT_ARG || argIndex == AdviceInfo.STATIC_JOINPOINT_ARG) {
1656 loadJoinPointInstance(cv, isOptimizedJoinPoint, joinPointInstanceIndex);
1657 } else if (argIndex == AdviceInfo.TARGET_ARG) {
1658 loadCallee(cv, isOptimizedJoinPoint, joinPointInstanceIndex, calleeIndex);
1659
1660 if (adviceMethodInfo.getAdviceInfo().hasTargetWithRuntimeCheck()) {
1661 cv.visitTypeInsn(
1662 CHECKCAST,
1663 adviceMethodInfo.getAdviceInfo().getMethodParameterTypes()[j].getInternalName()
1664 );
1665 }
1666 } else if (argIndex == AdviceInfo.THIS_ARG) {
1667 loadCaller(cv, isOptimizedJoinPoint, joinPointInstanceIndex, callerIndex);
1668 } else {
1669 throw new Error("special argument index is not supported: " + argIndex);
1670 }
1671 }
1672 } else {
1673
1674 adviceMethodInfo.setJoinPointIndex(joinPointInstanceIndex);
1675 for (int j = 0; j < m_aspectModels.length; j++) {
1676 AspectModel aspectModel = m_aspectModels[j];
1677 if (aspectDef.getAspectModel().equals(aspectModel.getAspectModelType())) {
1678 aspectModel.createBeforeAdviceArgumentHandling(cv, adviceMethodInfo);
1679 }
1680 }
1681 }
1682
1683 cv.visitMethodInsn(
1684 INVOKEVIRTUAL,
1685 adviceMethodInfo.getAspectInfo().getAspectClassName(),
1686 adviceMethodInfo.getAdviceInfo().getMethodName(),
1687 adviceMethodInfo.getAdviceInfo().getMethodSignature()
1688 );
1689
1690
1691 endRuntimeCheck(cv, adviceMethodInfo.getAdviceInfo(), endInstanceOflabel);
1692 }
1693
1694 if (m_isThisAdvisable) {
1695 createBeforeInterceptorInvocations(cv, joinPointInstanceIndex, callerIndex + 1);
1696 }
1697 }
1698
1699 /***
1700 * Adds after advice invocations.
1701 *
1702 * @param cv
1703 * @param isOptimizedJoinPoint
1704 * @param argStartIndex index on stack of first target method arg (0 or 1, depends of static target or
1705 * not)
1706 * @param joinPointInstanceIndex >= 0 if STATIC_JOIN_POINT is NOT to be used (around advice)
1707 * @param callerIndex
1708 * @param calleeIndex
1709 */
1710 protected void createAfterFinallyAdviceInvocations(final CodeVisitor cv,
1711 final boolean isOptimizedJoinPoint,
1712 final int argStartIndex,
1713 final int joinPointInstanceIndex,
1714 final int callerIndex,
1715 final int calleeIndex) {
1716
1717 for (int i = m_afterFinallyAdviceMethodInfos.length - 1; i >= 0; i--) {
1718 AdviceMethodInfo advice = m_afterFinallyAdviceMethodInfos[i];
1719 createAfterAdviceInvocation(
1720 cv, isOptimizedJoinPoint, advice, joinPointInstanceIndex, argStartIndex,
1721 callerIndex, calleeIndex, INDEX_NOTAVAILABLE
1722 );
1723 }
1724 }
1725
1726 /***
1727 * Adds after returning advice invocations.
1728 *
1729 * @param cv
1730 * @param isOptimizedJoinPoint
1731 * @param argStartIndex index on stack of first target method arg (0 or 1, depends of static target or
1732 * not)
1733 * @param joinPointInstanceIndex >= 0 if STATIC_JOIN_POINT is NOT to be used (around advice)
1734 * @param callerIndex
1735 * @param calleeIndex
1736 */
1737 protected void createAfterReturningAdviceInvocations(final CodeVisitor cv,
1738 final boolean isOptimizedJoinPoint,
1739 final int argStartIndex,
1740 final int joinPointInstanceIndex,
1741 final int callerIndex,
1742 final int calleeIndex) {
1743
1744 final int returnValueIndex = (joinPointInstanceIndex != INDEX_NOTAVAILABLE) ?
1745 (joinPointInstanceIndex + 1) : callerIndex + 1;
1746
1747 if (m_isThisAdvisable) {
1748 createAfterReturningInterceptorInvocations(cv, joinPointInstanceIndex, returnValueIndex);
1749 }
1750
1751 boolean hasPoppedReturnValueFromStack = false;
1752 for (int i = m_afterReturningAdviceMethodInfos.length - 1; i >= 0; i--) {
1753 AdviceMethodInfo advice = m_afterReturningAdviceMethodInfos[i];
1754
1755
1756 advice.setSpecialArgumentIndex(returnValueIndex);
1757
1758 String specialArgDesc = advice.getSpecialArgumentTypeDesc();
1759 if (specialArgDesc == null) {
1760
1761 createAfterAdviceInvocation(
1762 cv, isOptimizedJoinPoint, advice, joinPointInstanceIndex, argStartIndex,
1763 callerIndex, calleeIndex, INDEX_NOTAVAILABLE
1764 );
1765 } else {
1766
1767 if (AsmHelper.isPrimitive(m_returnType)) {
1768 if (m_returnType.getDescriptor().equals(specialArgDesc)) {
1769 createAfterAdviceInvocation(
1770 cv, isOptimizedJoinPoint, advice, joinPointInstanceIndex, argStartIndex,
1771 callerIndex, calleeIndex, returnValueIndex
1772 );
1773 }
1774 } else {
1775 cv.visitVarInsn(ALOAD, returnValueIndex);
1776
1777 cv.visitTypeInsn(INSTANCEOF, advice.getSpecialArgumentTypeName());
1778
1779 Label label = new Label();
1780 cv.visitJumpInsn(IFEQ, label);
1781
1782 createAfterAdviceInvocation(
1783 cv, isOptimizedJoinPoint, advice, joinPointInstanceIndex, argStartIndex,
1784 callerIndex, calleeIndex, returnValueIndex
1785 );
1786
1787 cv.visitLabel(label);
1788 }
1789 }
1790 }
1791
1792
1793 if (!requiresProceedMethod() && hasPoppedReturnValueFromStack) {
1794 cv.visitVarInsn(ALOAD, returnValueIndex);
1795 }
1796 }
1797
1798 /***
1799 * Adds a single generic after advice invocation.
1800 *
1801 * @param cv
1802 * @param isOptimizedJoinPoint
1803 * @param adviceMethodInfo
1804 * @param joinPointInstanceIndex
1805 * @param argStartIndex
1806 * @param callerIndex
1807 * @param calleeIndex
1808 * @param specialArgIndex for afterReturning / Throwing when binding is used
1809 */
1810 protected void createAfterAdviceInvocation(final CodeVisitor cv,
1811 final boolean isOptimizedJoinPoint,
1812 final AdviceMethodInfo adviceMethodInfo,
1813 final int joinPointInstanceIndex,
1814 final int argStartIndex,
1815 final int callerIndex,
1816 final int calleeIndex,
1817 final int specialArgIndex) {
1818
1819 Label endInstanceOflabel = beginRuntimeCheck(
1820 cv, isOptimizedJoinPoint, joinPointInstanceIndex,
1821 adviceMethodInfo.getAdviceInfo(), calleeIndex
1822 );
1823
1824
1825 loadAspect(cv, isOptimizedJoinPoint, joinPointInstanceIndex, adviceMethodInfo.getAspectInfo());
1826
1827 AspectDefinition aspectDef = adviceMethodInfo.getAdviceInfo().getAdviceDefinition().getAspectDefinition();
1828 if (aspectDef.isAspectWerkzAspect()) {
1829
1830
1831 int[] argIndexes = adviceMethodInfo.getAdviceMethodArgIndexes();
1832 for (int j = 0; j < argIndexes.length; j++) {
1833 int argIndex = argIndexes[j];
1834 if (argIndex >= 0) {
1835 Type argumentType = m_argumentTypes[argIndex];
1836 int argStackIndex = AsmHelper.getRegisterIndexOf(m_argumentTypes, argIndex) + argStartIndex;
1837 AsmHelper.loadType(cv, argStackIndex, argumentType);
1838 } else if (argIndex == AdviceInfo.JOINPOINT_ARG || argIndex == AdviceInfo.STATIC_JOINPOINT_ARG) {
1839 loadJoinPointInstance(cv, isOptimizedJoinPoint, joinPointInstanceIndex);
1840 } else if (argIndex == AdviceInfo.TARGET_ARG) {
1841 loadCallee(cv, isOptimizedJoinPoint, joinPointInstanceIndex, calleeIndex);
1842
1843 if (adviceMethodInfo.getAdviceInfo().hasTargetWithRuntimeCheck()) {
1844 cv.visitTypeInsn(
1845 CHECKCAST,
1846 adviceMethodInfo.getAdviceInfo().getMethodParameterTypes()[j].getInternalName()
1847 );
1848 }
1849 } else if (argIndex == AdviceInfo.THIS_ARG) {
1850 loadCaller(cv, isOptimizedJoinPoint, joinPointInstanceIndex, callerIndex);
1851 } else if (argIndex == AdviceInfo.SPECIAL_ARGUMENT && specialArgIndex != INDEX_NOTAVAILABLE) {
1852 Type argumentType = adviceMethodInfo.getAdviceInfo().getMethodParameterTypes()[j];
1853 AsmHelper.loadType(cv, specialArgIndex, argumentType);
1854 if (adviceMethodInfo.getAdviceInfo().getAdviceDefinition().getType().equals(
1855 AdviceType.AFTER_THROWING
1856 )) {
1857 cv.visitTypeInsn(CHECKCAST, argumentType.getInternalName());
1858 }
1859 } else {
1860 throw new Error("magic index is not supported: " + argIndex);
1861 }
1862 }
1863 } else {
1864
1865 adviceMethodInfo.setJoinPointIndex(joinPointInstanceIndex);
1866 for (int i = 0; i < m_aspectModels.length; i++) {
1867 AspectModel aspectModel = m_aspectModels[i];
1868 if (aspectDef.getAspectModel().equals(aspectModel.getAspectModelType())) {
1869 aspectModel.createAfterAdviceArgumentHandling(cv, adviceMethodInfo);
1870 }
1871 }
1872 }
1873
1874 cv.visitMethodInsn(
1875 INVOKEVIRTUAL,
1876 adviceMethodInfo.getAspectInfo().getAspectClassName(),
1877 adviceMethodInfo.getAdviceInfo().getMethodName(),
1878 adviceMethodInfo.getAdviceInfo().getMethodSignature()
1879 );
1880
1881
1882 endRuntimeCheck(cv, adviceMethodInfo.getAdviceInfo(), endInstanceOflabel);
1883 }
1884
1885 /***
1886 * Adds the return value to the RETURNED field.
1887 *
1888 * @param cv
1889 * @param returnValueIndex
1890 * @param joinPointInstanceIndex
1891 * @param unwrap set to true if already wrapped on the stack (within proceed() code)
1892 */
1893 protected void addReturnedValueToJoinPoint(final CodeVisitor cv,
1894 final int returnValueIndex,
1895 final int joinPointInstanceIndex,
1896 final boolean unwrap) {
1897 if (m_requiresJoinPoint && m_returnType.getSort() != Type.VOID) {
1898 if (m_joinPointType == JoinPointType.METHOD_EXECUTION_INT
1899 || m_joinPointType == JoinPointType.METHOD_CALL_INT
1900 || m_joinPointType == JoinPointType.CONSTRUCTOR_CALL_INT) {
1901
1902 loadJoinPointInstance(cv, NON_OPTIMIZED_JOIN_POINT, joinPointInstanceIndex);
1903 if (unwrap && AsmHelper.isPrimitive(m_returnType)) {
1904 cv.visitVarInsn(ALOAD, returnValueIndex);
1905 AsmHelper.unwrapType(cv, m_returnType);
1906 } else {
1907 AsmHelper.loadType(cv, returnValueIndex, m_returnType);
1908 }
1909 cv.visitFieldInsn(
1910 PUTFIELD, m_joinPointClassName,
1911 RETURN_VALUE_FIELD_NAME, m_returnType.getDescriptor()
1912 );
1913 }
1914 }
1915 }
1916
1917 /***
1918 * Loads the join point instance, takes static/non-static join point access into account.
1919 *
1920 * @param cv
1921 * @param isOptimizedJoinPoint
1922 * @param joinPointInstanceIndex
1923 */
1924 protected void loadJoinPointInstance(final CodeVisitor cv,
1925 final boolean isOptimizedJoinPoint,
1926 final int joinPointInstanceIndex) {
1927 if (isOptimizedJoinPoint) {
1928 cv.visitFieldInsn(
1929 GETSTATIC, m_joinPointClassName,
1930 OPTIMIZED_JOIN_POINT_INSTANCE_FIELD_NAME,
1931 L + m_joinPointClassName + SEMICOLON
1932 );
1933 } else {
1934 cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
1935 }
1936 }
1937
1938 /***
1939 * Loads the argument member fields.
1940 *
1941 * @param cv
1942 * @param argStartIndex
1943 */
1944 protected void loadArgumentMemberFields(final CodeVisitor cv, final int argStartIndex) {
1945 int argStackIndex = argStartIndex;
1946 for (int index = 0; index < m_argumentTypes.length; index++) {
1947 Type argumentType = m_argumentTypes[index];
1948 argStackIndex = AsmHelper.loadType(cv, argStackIndex, argumentType);
1949 }
1950 }
1951
1952 /***
1953 * Loads the arguments.
1954 *
1955 * @param cv
1956 */
1957 protected void loadArguments(final CodeVisitor cv) {
1958 for (int i = 0; i < m_fieldNames.length; i++) {
1959 String fieldName = m_fieldNames[i];
1960 Type argumentType = m_argumentTypes[i];
1961 cv.visitVarInsn(ALOAD, 0);
1962 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, fieldName, argumentType.getDescriptor());
1963 }
1964 }
1965
1966 /***
1967 * Resets the stack frame counter.
1968 *
1969 * @param cv
1970 */
1971 protected void resetStackFrameCounter(final CodeVisitor cv) {
1972 cv.visitVarInsn(ALOAD, 0);
1973 cv.visitInsn(ICONST_M1);
1974 cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, STACK_FRAME_COUNTER_FIELD_NAME, I);
1975 }
1976
1977 /***
1978 * Handles the incrementation of the stack frame.
1979 *
1980 * @param cv
1981 */
1982 protected void incrementStackFrameCounter(final CodeVisitor cv) {
1983 cv.visitVarInsn(ALOAD, 0);
1984 cv.visitInsn(DUP);
1985 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, STACK_FRAME_COUNTER_FIELD_NAME, I);
1986 cv.visitInsn(ICONST_1);
1987 cv.visitInsn(IADD);
1988 cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, STACK_FRAME_COUNTER_FIELD_NAME, I);
1989 }
1990
1991 /***
1992 * Create and load a structure (f.e. array of Object) where args are stored, before setting the Rtti
1993 * with it (See addParametersToRttiInstance). The structure is stored at the given stackFreeIndex.
1994 * <p/>
1995 * We provide here a default implementation that is suitable for method and constructor call and execution.
1996 * See createParameterWrappedAt for field get/set and handler compiler (no array of argument needed)
1997 *
1998 * @param cv
1999 * @param stackFreeIndex
2000 */
2001 protected final void createArgumentArrayAt(final CodeVisitor cv, final int stackFreeIndex) {
2002 AsmHelper.loadIntegerConstant(cv, m_fieldNames.length);
2003 cv.visitTypeInsn(ANEWARRAY, OBJECT_CLASS_NAME);
2004 cv.visitVarInsn(ASTORE, stackFreeIndex);
2005
2006 for (int i = 0; i < m_argumentTypes.length; i++) {
2007 cv.visitVarInsn(ALOAD, stackFreeIndex);
2008 AsmHelper.loadIntegerConstant(cv, i);
2009 AsmHelper.prepareWrappingOfPrimitiveType(cv, m_argumentTypes[i]);
2010 cv.visitVarInsn(ALOAD, 0);
2011 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, ARGUMENT_FIELD + i, m_argumentTypes[i].getDescriptor());
2012 AsmHelper.wrapPrimitiveType(cv, m_argumentTypes[i]);
2013 cv.visitInsn(AASTORE);
2014 }
2015 }
2016
2017 /***
2018 * Creates utility methods for the join point (getter, setters etc.).
2019 */
2020 protected void createUtilityMethods() {
2021 CodeVisitor cv;
2022
2023
2024 {
2025 cv = m_cw.visitMethod(ACC_PUBLIC, ADD_META_DATA_METHOD_NAME, ADD_META_DATA_METHOD_SIGNATURE, null, null);
2026 cv.visitFieldInsn(GETSTATIC, m_joinPointClassName, META_DATA_FIELD_NAME, MAP_CLASS_SIGNATURE);
2027 cv.visitVarInsn(ALOAD, 1);
2028 cv.visitVarInsn(ALOAD, 2);
2029 cv.visitMethodInsn(
2030 INVOKEINTERFACE,
2031 MAP_CLASS_NAME,
2032 PUT_METHOD_NAME,
2033 PUT_METHOD_SIGNATURE
2034 );
2035 cv.visitInsn(POP);
2036 cv.visitInsn(RETURN);
2037 cv.visitMaxs(0, 0);
2038 }
2039
2040
2041 {
2042 cv = m_cw.visitMethod(ACC_PUBLIC, GET_META_DATA_METHOD_NAME, GET_META_DATA_METHOD_SIGNATURE, null, null);
2043 cv.visitFieldInsn(GETSTATIC, m_joinPointClassName, META_DATA_FIELD_NAME, MAP_CLASS_SIGNATURE);
2044 cv.visitVarInsn(ALOAD, 1);
2045 cv.visitMethodInsn(INVOKEINTERFACE, MAP_CLASS_NAME, GET_METHOD_NAME, GET_METHOD_SIGNATURE);
2046 cv.visitInsn(ARETURN);
2047 cv.visitMaxs(0, 0);
2048 }
2049
2050
2051 {
2052 cv = m_cw.visitMethod(
2053 ACC_PUBLIC,
2054 GET_CALLEE_METHOD_NAME,
2055 NO_PARAMS_SIGNATURE + OBJECT_CLASS_SIGNATURE,
2056 null, null
2057 );
2058 cv.visitVarInsn(ALOAD, 0);
2059 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
2060 cv.visitInsn(ARETURN);
2061 cv.visitMaxs(0, 0);
2062 }
2063
2064
2065 {
2066 cv = m_cw.visitMethod(
2067 ACC_PUBLIC,
2068 GET_CALLER_METHOD_NAME,
2069 NO_PARAMS_SIGNATURE + OBJECT_CLASS_SIGNATURE,
2070 null, null
2071 );
2072 cv.visitVarInsn(ALOAD, 0);
2073 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
2074 cv.visitInsn(ARETURN);
2075 cv.visitMaxs(0, 0);
2076 }
2077
2078
2079 {
2080 cv = m_cw.visitMethod(
2081 ACC_PUBLIC,
2082 GET_TARGET_METHOD_NAME,
2083 NO_PARAMS_SIGNATURE + OBJECT_CLASS_SIGNATURE,
2084 null, null
2085 );
2086 cv.visitVarInsn(ALOAD, 0);
2087 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
2088 cv.visitInsn(ARETURN);
2089 cv.visitMaxs(0, 0);
2090 }
2091
2092
2093 {
2094 cv = m_cw.visitMethod(
2095 ACC_PUBLIC,
2096 GET_THIS_METHOD_NAME,
2097 NO_PARAMS_SIGNATURE + OBJECT_CLASS_SIGNATURE,
2098 null, null
2099 );
2100 cv.visitVarInsn(ALOAD, 0);
2101 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
2102 cv.visitInsn(ARETURN);
2103 cv.visitMaxs(0, 0);
2104 }
2105
2106
2107 {
2108 cv =
2109 m_cw.visitMethod(
2110 ACC_PUBLIC,
2111 GET_CALLER_CLASS_METHOD_NAME,
2112 GET_CALLER_CLASS_METHOD_SIGNATURE,
2113 null,
2114 null
2115 );
2116 cv.visitFieldInsn(GETSTATIC, m_joinPointClassName, THIS_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
2117 cv.visitInsn(ARETURN);
2118 cv.visitMaxs(0, 0);
2119 }
2120
2121
2122 {
2123 cv =
2124 m_cw.visitMethod(
2125 ACC_PUBLIC,
2126 GET_CALLEE_CLASS_METHOD_NAME,
2127 GET_CALLEE_CLASS_METHOD_SIGNATURE,
2128 null,
2129 null
2130 );
2131 cv.visitFieldInsn(GETSTATIC, m_joinPointClassName, TARGET_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
2132 cv.visitInsn(ARETURN);
2133 cv.visitMaxs(0, 0);
2134 }
2135
2136
2137 {
2138 cv =
2139 m_cw.visitMethod(
2140 ACC_PUBLIC,
2141 GET_TARGET_CLASS_METHOD_NAME,
2142 GET_TARGET_CLASS_METHOD_SIGNATURE,
2143 null,
2144 null
2145 );
2146 cv.visitFieldInsn(GETSTATIC, m_joinPointClassName, TARGET_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
2147 cv.visitInsn(ARETURN);
2148 cv.visitMaxs(0, 0);
2149 }
2150
2151
2152 {
2153 cv = m_cw.visitMethod(ACC_PUBLIC, GET_TYPE_METHOD_NAME, GET_TYPE_METHOD_SIGNATURE, null, null);
2154 AsmHelper.loadIntegerConstant(cv, m_joinPointType);
2155 cv.visitMethodInsn(
2156 INVOKESTATIC, Type.getType(JoinPointType.class).getInternalName(), "fromInt",
2157 "(I)" + Type.getType(JoinPointType.class).getDescriptor()
2158 );
2159 cv.visitInsn(ARETURN);
2160 cv.visitMaxs(0, 0);
2161 }
2162
2163
2164 {
2165 cv = m_cw.visitMethod(
2166 ACC_PUBLIC,
2167 GET_ENCLOSING_SJP_METHOD_NAME,
2168 GET_ENCLOSING_SJP_METHOD_SIGNATURE,
2169 null,
2170 null
2171 );
2172 cv.visitVarInsn(ALOAD, 0);
2173 cv.visitFieldInsn(GETSTATIC,
2174 m_joinPointClassName,
2175 ENCLOSING_SJP_FIELD_NAME,
2176 ENCLOSING_SJP_FIELD_CLASS_SIGNATURE
2177 );
2178 cv.visitInsn(ARETURN);
2179 cv.visitMaxs(0, 0);
2180 }
2181
2182 }
2183
2184 /***
2185 * Creates the copy method.
2186 * <p/>
2187 * TODO refactor and put in subclasses
2188 */
2189 protected void createCopyMethod() {
2190
2191 CodeVisitor cv = m_cw.visitMethod(ACC_PUBLIC, COPY_METHOD_NAME, COPY_METHOD_SIGNATURE, null, null);
2192
2193
2194 cv.visitTypeInsn(NEW, m_joinPointClassName);
2195 cv.visitInsn(DUP);
2196 int joinPointCloneIndex = 1;
2197 cv.visitMethodInsn(INVOKESPECIAL, m_joinPointClassName, INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE);
2198 cv.visitVarInsn(ASTORE, joinPointCloneIndex);
2199
2200
2201 cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2202 cv.visitVarInsn(ALOAD, 0);
2203 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, STACK_FRAME_COUNTER_FIELD_NAME, I);
2204 cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, STACK_FRAME_COUNTER_FIELD_NAME, I);
2205
2206 if (m_isThisAdvisable) {
2207
2208 cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2209 cv.visitVarInsn(ALOAD, 0);
2210 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
2211 cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
2212
2213
2214 cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2215 cv.visitVarInsn(ALOAD, 0);
2216 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, NR_OF_BEFORE_INTERCEPTORS_FIELD_NAME, I);
2217 cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_BEFORE_INTERCEPTORS_FIELD_NAME, I);
2218 cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2219 cv.visitVarInsn(ALOAD, 0);
2220 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, NR_OF_AROUND_INTERCEPTORS_FIELD_NAME, I);
2221 cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AROUND_INTERCEPTORS_FIELD_NAME, I);
2222 cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2223 cv.visitVarInsn(ALOAD, 0);
2224 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, NR_OF_AFTER_INTERCEPTORS_FIELD_NAME, I);
2225 cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AFTER_INTERCEPTORS_FIELD_NAME, I);
2226 cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2227 cv.visitVarInsn(ALOAD, 0);
2228 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, NR_OF_AFTER_RETURNING_INTERCEPTORS_FIELD_NAME, I);
2229 cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AFTER_RETURNING_INTERCEPTORS_FIELD_NAME, I);
2230 cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2231 cv.visitVarInsn(ALOAD, 0);
2232 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, NR_OF_AFTER_THROWING_INTERCEPTORS_FIELD_NAME, I);
2233 cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AFTER_THROWING_INTERCEPTORS_FIELD_NAME, I);
2234
2235
2236 cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2237 cv.visitVarInsn(ALOAD, 0);
2238 cv.visitFieldInsn(
2239 GETFIELD, m_joinPointClassName, BEFORE_INTERCEPTORS_FIELD_NAME,
2240 BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE
2241 );
2242 cv.visitFieldInsn(
2243 PUTFIELD, m_joinPointClassName, BEFORE_INTERCEPTORS_FIELD_NAME,
2244 BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE
2245 );
2246 cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2247 cv.visitVarInsn(ALOAD, 0);
2248 cv.visitFieldInsn(
2249 GETFIELD, m_joinPointClassName, AROUND_INTERCEPTORS_FIELD_NAME,
2250 AROUND_ADVICE_ARRAY_CLASS_SIGNATURE
2251 );
2252 cv.visitFieldInsn(
2253 PUTFIELD, m_joinPointClassName, AROUND_INTERCEPTORS_FIELD_NAME,
2254 AROUND_ADVICE_ARRAY_CLASS_SIGNATURE
2255 );
2256 cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2257 cv.visitVarInsn(ALOAD, 0);
2258 cv.visitFieldInsn(
2259 GETFIELD, m_joinPointClassName, AFTER_INTERCEPTORS_FIELD_NAME, AFTER_ADVICE_ARRAY_CLASS_SIGNATURE
2260 );
2261 cv.visitFieldInsn(
2262 PUTFIELD, m_joinPointClassName, AFTER_INTERCEPTORS_FIELD_NAME, AFTER_ADVICE_ARRAY_CLASS_SIGNATURE
2263 );
2264 cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2265 cv.visitVarInsn(ALOAD, 0);
2266 cv.visitFieldInsn(
2267 GETFIELD, m_joinPointClassName, AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
2268 AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE
2269 );
2270 cv.visitFieldInsn(
2271 PUTFIELD, m_joinPointClassName, AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
2272 AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE
2273 );
2274 cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2275 cv.visitVarInsn(ALOAD, 0);
2276 cv.visitFieldInsn(
2277 GETFIELD, m_joinPointClassName, AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
2278 AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE
2279 );
2280 cv.visitFieldInsn(
2281 PUTFIELD, m_joinPointClassName, AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
2282 AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE
2283 );
2284 }
2285
2286
2287 cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2288 cv.visitVarInsn(ALOAD, 0);
2289 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
2290 cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
2291
2292
2293 cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2294 cv.visitVarInsn(ALOAD, 0);
2295 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
2296 cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
2297
2298
2299 for (int i = 0; i < m_fieldNames.length; i++) {
2300 String fieldName = m_fieldNames[i];
2301 cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2302 cv.visitVarInsn(ALOAD, 0);
2303 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, fieldName, m_argumentTypes[i].getDescriptor());
2304 cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, fieldName, m_argumentTypes[i].getDescriptor());
2305 }
2306
2307
2308 if (m_returnType.getSort() != Type.VOID) {
2309 cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2310 cv.visitVarInsn(ALOAD, 0);
2311 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, RETURN_VALUE_FIELD_NAME, m_returnType.getDescriptor());
2312 cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, RETURN_VALUE_FIELD_NAME, m_returnType.getDescriptor());
2313 }
2314
2315 cv.visitVarInsn(ALOAD, joinPointCloneIndex);
2316 cv.visitInsn(ARETURN);
2317 cv.visitMaxs(0, 0);
2318 }
2319
2320 /***
2321 * Build up the signature of the 'invoke' methods.
2322 *
2323 * @return
2324 */
2325 protected String buildInvokeMethodSignature() {
2326 StringBuffer invokeDescBuf = new StringBuffer();
2327 invokeDescBuf.append('(');
2328 if (m_joinPointType != JoinPointType.CONSTRUCTOR_CALL_INT) {
2329 if (!Modifier.isStatic(m_calleeMemberModifiers)) {
2330
2331 invokeDescBuf.append(m_calleeClassSignature);
2332 }
2333 }
2334
2335 for (int i = 0; i < m_argumentTypes.length; i++) {
2336 Type type = m_argumentTypes[i];
2337 invokeDescBuf.append(type.getDescriptor());
2338 }
2339
2340 invokeDescBuf.append(m_callerClassSignature);
2341 invokeDescBuf.append(')');
2342 invokeDescBuf.append(m_returnType.getDescriptor());
2343 return invokeDescBuf.toString();
2344 }
2345
2346 /***
2347 * Return the number of argument the joinpoint has (excludes JoinPoint, Rtti, this / target) but is only
2348 * the number of argument we will have in the rtti (advised method/ctor args or 1 for field / handler)
2349 *
2350 * @return
2351 */
2352 protected final boolean hasArguments() {
2353 return m_argumentTypes.length > 0;
2354 }
2355
2356 /***
2357 * Checks if at least one advice is using this or target (bounded or runtime check)
2358 *
2359 * @return true if so
2360 */
2361 protected boolean requiresThisOrTarget() {
2362 return m_isThisAdvisable ||
2363 requiresThisOrTarget(m_aroundAdviceMethodInfos) ||
2364 requiresThisOrTarget(m_beforeAdviceMethodInfos) ||
2365 requiresThisOrTarget(m_afterFinallyAdviceMethodInfos) ||
2366 requiresThisOrTarget(m_afterReturningAdviceMethodInfos) ||
2367 requiresThisOrTarget(m_afterThrowingAdviceMethodInfos);
2368 }
2369
2370 /***
2371 * Checks if at least one advice is using the non static JoinPoint explicitly
2372 *
2373 * @return true if so
2374 */
2375 protected boolean requiresJoinPoint() {
2376 return m_isThisAdvisable ||
2377 requiresJoinPoint(m_aroundAdviceMethodInfos) ||
2378 requiresJoinPoint(m_beforeAdviceMethodInfos) ||
2379 requiresJoinPoint(m_afterFinallyAdviceMethodInfos) ||
2380 requiresJoinPoint(m_afterReturningAdviceMethodInfos) ||
2381 requiresJoinPoint(m_afterThrowingAdviceMethodInfos);
2382 }
2383
2384 /***
2385 * Checks if at least one advice is using target or this (bounded or runtime check)
2386 *
2387 * @param adviceMethodInfos
2388 * @return true if so
2389 */
2390 protected boolean requiresThisOrTarget(final AdviceMethodInfo[] adviceMethodInfos) {
2391 for (int i = 0; i < adviceMethodInfos.length; i++) {
2392 if (adviceMethodInfos[i].requiresThisOrTarget()) {
2393 return true;
2394 }
2395 }
2396 return false;
2397 }
2398
2399 /***
2400 * Checks if at least one advice is using non static JoinPoint explicitly
2401 *
2402 * @param adviceMethodInfos
2403 * @return true if so
2404 */
2405 protected boolean requiresJoinPoint(final AdviceMethodInfo[] adviceMethodInfos) {
2406 for (int i = 0; i < adviceMethodInfos.length; i++) {
2407 if (adviceMethodInfos[i].requiresJoinPoint()) {
2408 return true;
2409 }
2410 }
2411 return false;
2412 }
2413
2414 /***
2415 * Handles the if case for runtime check (target instanceof, cflow)
2416 *
2417 * @param cv
2418 * @param isOptimizedJoinPoint
2419 * @param joinPointInstanceIndex
2420 * @param adviceInfo
2421 * @return the label for endIf or null if the adviceInfo did not required runtime check
2422 */
2423 protected Label beginRuntimeCheck(final CodeVisitor cv,
2424 final boolean isOptimizedJoinPoint,
2425 final int joinPointInstanceIndex,
2426 final AdviceInfo adviceInfo,
2427 final int calleeIndex) {
2428 Label endRuntimeCheckLabel = null;
2429 if (adviceInfo.hasTargetWithRuntimeCheck() || adviceInfo.getAdviceDefinition().hasCflowOrCflowBelow()) {
2430 endRuntimeCheckLabel = new Label();
2431
2432 RuntimeCheckVisitor runtimeCheckVisitor = new RuntimeCheckVisitor(
2433 this, cv, adviceInfo.getExpressionInfo(), isOptimizedJoinPoint, joinPointInstanceIndex,
2434 calleeIndex
2435 );
2436 runtimeCheckVisitor.pushCheckOnStack(adviceInfo.getExpressionContext());
2437 cv.visitJumpInsn(IFEQ, endRuntimeCheckLabel);
2438 }
2439 return endRuntimeCheckLabel;
2440 }
2441
2442 /***
2443 * Ends the ifLabel of a runtime check
2444 *
2445 * @param cv
2446 * @param adviceInfo
2447 * @param label if null, then do nothing (means we did not had a runtime check)
2448 */
2449 protected void endRuntimeCheck(final CodeVisitor cv, final AdviceInfo adviceInfo, final Label label) {
2450 if (adviceInfo.hasTargetWithRuntimeCheck() || adviceInfo.getAdviceDefinition().hasCflowOrCflowBelow()) {
2451 cv.visitLabel(label);
2452 }
2453 }
2454
2455 /***
2456 * Helper method to load the callee on the stack
2457 *
2458 * @param cv
2459 * @param isOptimizedJoinPoint
2460 * @param joinPointIndex
2461 * @param calleeIndex
2462 */
2463 public void loadCallee(final CodeVisitor cv,
2464 final boolean isOptimizedJoinPoint,
2465 final int joinPointIndex,
2466 final int calleeIndex) {
2467 if (isOptimizedJoinPoint) {
2468
2469 cv.visitVarInsn(ALOAD, calleeIndex);
2470 } else {
2471 loadJoinPointInstance(cv, isOptimizedJoinPoint, joinPointIndex);
2472 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
2473 }
2474 }
2475
2476 /***
2477 * Helper method to load the caller on the stack
2478 *
2479 * @param cv
2480 * @param isOptimizedJoinPoint
2481 * @param joinPointIndex
2482 * @param callerIndex
2483 */
2484 protected void loadCaller(final CodeVisitor cv,
2485 final boolean isOptimizedJoinPoint,
2486 final int joinPointIndex,
2487 final int callerIndex) {
2488 if (isOptimizedJoinPoint) {
2489
2490 cv.visitVarInsn(ALOAD, callerIndex);
2491 } else {
2492 loadJoinPointInstance(cv, isOptimizedJoinPoint, joinPointIndex);
2493 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, CALLER_INSTANCE_FIELD_NAME, m_callerClassSignature);
2494 }
2495 }
2496
2497 /***
2498 * Loads the aspect instance.
2499 *
2500 * @param cv
2501 * @param isOptimizedJoinPoint
2502 * @param joinPointIndex
2503 * @param aspectInfo
2504 */
2505 protected void loadAspect(final CodeVisitor cv,
2506 final boolean isOptimizedJoinPoint,
2507 final int joinPointIndex,
2508 final AspectInfo aspectInfo) {
2509 DeploymentModel deploymentModel = aspectInfo.getDeploymentModel();
2510 if (deploymentModel.equals(DeploymentModel.PER_JVM) ||
2511 deploymentModel.equals(DeploymentModel.PER_CLASS)) {
2512 cv.visitFieldInsn(
2513 GETSTATIC, m_joinPointClassName, aspectInfo.getAspectFieldName(),
2514 aspectInfo.getAspectClassSignature()
2515 );
2516 } else if (deploymentModel.equals(DeploymentModel.PER_INSTANCE)) {
2517 loadJoinPointInstance(cv, isOptimizedJoinPoint, joinPointIndex);
2518 cv.visitFieldInsn(
2519 GETFIELD, m_joinPointClassName, aspectInfo.getAspectFieldName(),
2520 aspectInfo.getAspectClassSignature()
2521 );
2522 } else {
2523 throw new DefinitionException("deployment model [" + deploymentModel + "] is not supported");
2524 }
2525 }
2526
2527 /***
2528 * Creates an invocation to Aspects.aspectOf(..).
2529 *
2530 * @param cv
2531 * @param isOptimizedJoinPoint
2532 * @param joinPointIndex
2533 * @param callerIndex
2534 * @param calleeIndex
2535 * @param aspectInfo
2536 */
2537 public void createInvocationToAspectOf(final CodeVisitor cv,
2538 final boolean isOptimizedJoinPoint,
2539 final int joinPointIndex,
2540 final int callerIndex,
2541 final int calleeIndex,
2542 final AspectInfo aspectInfo) {
2543 if (aspectInfo.getDeploymentModel() == DeploymentModel.PER_INSTANCE) {
2544
2545
2546 loadJoinPointInstance(cv, isOptimizedJoinPoint, joinPointIndex);
2547 cv.visitLdcInsn(aspectInfo.getAspectQualifiedName());
2548 if (calleeIndex >= 0) {
2549 cv.visitVarInsn(ALOAD, calleeIndex);
2550 cv.visitLdcInsn(aspectInfo.getAspectDefinition().getContainerClassName());
2551 cv.visitMethodInsn(
2552 INVOKESTATIC,
2553 ASPECTS_CLASS_NAME,
2554 ASPECT_OF_METHOD_NAME,
2555 ASPECT_OF_PER_INSTANCE_METHOD_SIGNATURE
2556 );
2557 } else {
2558
2559
2560
2561 cv.visitFieldInsn(GETSTATIC, m_joinPointClassName, TARGET_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE);
2562 cv.visitLdcInsn(aspectInfo.getAspectDefinition().getContainerClassName());
2563 cv.visitMethodInsn(
2564 INVOKESTATIC,
2565 ASPECTS_CLASS_NAME,
2566 ASPECT_OF_METHOD_NAME,
2567 ASPECT_OF_PER_CLASS_METHOD_SIGNATURE
2568 );
2569 }
2570 cv.visitTypeInsn(CHECKCAST, aspectInfo.getAspectClassName());
2571 cv.visitFieldInsn(
2572 PUTFIELD, m_joinPointClassName, aspectInfo.getAspectFieldName(),
2573 aspectInfo.getAspectClassSignature()
2574 );
2575 }
2576 }
2577
2578 /***
2579 * Generates code needed for handling Advisable management for the target class.
2580 *
2581 * @param cv
2582 * @param joinPointInstanceIndex
2583 * @param advisableIndex
2584 */
2585 private void createInitializationForAdvisableManagement(final CodeVisitor cv,
2586 final int joinPointInstanceIndex,
2587 final int advisableIndex) {
2588
2589 cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2590 cv.visitInsn(ICONST_M1);
2591 cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
2592
2593 initializeAroundInterceptors(cv, joinPointInstanceIndex, advisableIndex);
2594 initializeBeforeInterceptors(cv, joinPointInstanceIndex, advisableIndex);
2595 initializeAfterInterceptors(cv, joinPointInstanceIndex, advisableIndex);
2596 initializeAfterReturningInterceptors(cv, joinPointInstanceIndex, advisableIndex);
2597 initializeAfterThrowingInterceptors(cv, joinPointInstanceIndex, advisableIndex);
2598 }
2599
2600 /***
2601 * Handle the around interceptor init.
2602 *
2603 * @param cv
2604 * @param joinPointInstanceIndex
2605 * @param advisableIndex
2606 */
2607 private void initializeAroundInterceptors(final CodeVisitor cv,
2608 final int joinPointInstanceIndex,
2609 final int advisableIndex) {
2610 cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2611 cv.visitVarInsn(ALOAD, advisableIndex);
2612 cv.visitTypeInsn(CHECKCAST, ADVISABLE_CLASS_NAME);
2613 cv.visitLdcInsn(new Integer(m_joinPointClassName.hashCode()));
2614 cv.visitMethodInsn(
2615 INVOKEINTERFACE,
2616 ADVISABLE_CLASS_NAME,
2617 GET_AROUND_ADVICE_METHOD_NAME,
2618 GET_AROUND_ADVICE_METHOD_SIGNATURE
2619 );
2620 cv.visitFieldInsn(
2621 PUTFIELD,
2622 m_joinPointClassName,
2623 AROUND_INTERCEPTORS_FIELD_NAME,
2624 AROUND_ADVICE_ARRAY_CLASS_SIGNATURE
2625 );
2626
2627 cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2628 cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2629 cv.visitFieldInsn(
2630 GETFIELD,
2631 m_joinPointClassName,
2632 AROUND_INTERCEPTORS_FIELD_NAME,
2633 AROUND_ADVICE_ARRAY_CLASS_SIGNATURE
2634 );
2635 cv.visitInsn(ARRAYLENGTH);
2636 cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AROUND_INTERCEPTORS_FIELD_NAME, I);
2637 }
2638
2639 /***
2640 * Handle the before interceptor init.
2641 *
2642 * @param cv
2643 * @param joinPointInstanceIndex
2644 * @param advisableIndex
2645 */
2646 private void initializeBeforeInterceptors(final CodeVisitor cv,
2647 final int joinPointInstanceIndex,
2648 final int advisableIndex) {
2649 cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2650 cv.visitVarInsn(ALOAD, advisableIndex);
2651 cv.visitTypeInsn(CHECKCAST, ADVISABLE_CLASS_NAME);
2652 cv.visitLdcInsn(new Integer(m_joinPointClassName.hashCode()));
2653 cv.visitMethodInsn(
2654 INVOKEINTERFACE,
2655 ADVISABLE_CLASS_NAME,
2656 GET_BEFORE_ADVICE_METHOD_NAME,
2657 GET_BEFORE_ADVICE_METHOD_SIGNATURE
2658 );
2659 cv.visitFieldInsn(
2660 PUTFIELD,
2661 m_joinPointClassName,
2662 BEFORE_INTERCEPTORS_FIELD_NAME,
2663 BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE
2664 );
2665
2666 cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2667 cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2668 cv.visitFieldInsn(
2669 GETFIELD,
2670 m_joinPointClassName,
2671 BEFORE_INTERCEPTORS_FIELD_NAME,
2672 BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE
2673 );
2674 cv.visitInsn(ARRAYLENGTH);
2675 cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_BEFORE_INTERCEPTORS_FIELD_NAME, I);
2676 }
2677
2678 /***
2679 * Handle the after finally interceptor init.
2680 *
2681 * @param cv
2682 * @param joinPointInstanceIndex
2683 * @param advisableIndex
2684 */
2685 private void initializeAfterInterceptors(final CodeVisitor cv,
2686 final int joinPointInstanceIndex,
2687 final int advisableIndex) {
2688 cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2689 cv.visitVarInsn(ALOAD, advisableIndex);
2690 cv.visitTypeInsn(CHECKCAST, ADVISABLE_CLASS_NAME);
2691 cv.visitLdcInsn(new Integer(m_joinPointClassName.hashCode()));
2692 cv.visitMethodInsn(
2693 INVOKEINTERFACE,
2694 ADVISABLE_CLASS_NAME,
2695 GET_AFTER_ADVICE_METHOD_NAME,
2696 GET_AFTER_ADVICE_METHOD_SIGNATURE
2697 );
2698 cv.visitFieldInsn(
2699 PUTFIELD,
2700 m_joinPointClassName,
2701 AFTER_INTERCEPTORS_FIELD_NAME,
2702 AFTER_ADVICE_ARRAY_CLASS_SIGNATURE
2703 );
2704
2705 cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2706 cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2707 cv.visitFieldInsn(
2708 GETFIELD,
2709 m_joinPointClassName,
2710 AFTER_INTERCEPTORS_FIELD_NAME,
2711 AFTER_ADVICE_ARRAY_CLASS_SIGNATURE
2712 );
2713 cv.visitInsn(ARRAYLENGTH);
2714 cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AFTER_INTERCEPTORS_FIELD_NAME, I);
2715 }
2716
2717 /***
2718 * Handle the after returning interceptor init.
2719 *
2720 * @param cv
2721 * @param joinPointInstanceIndex
2722 * @param advisableIndex
2723 */
2724 private void initializeAfterReturningInterceptors(final CodeVisitor cv,
2725 final int joinPointInstanceIndex,
2726 final int advisableIndex) {
2727 cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2728 cv.visitVarInsn(ALOAD, advisableIndex);
2729 cv.visitTypeInsn(CHECKCAST, ADVISABLE_CLASS_NAME);
2730 cv.visitLdcInsn(new Integer(m_joinPointClassName.hashCode()));
2731 cv.visitMethodInsn(
2732 INVOKEINTERFACE,
2733 ADVISABLE_CLASS_NAME,
2734 GET_AFTER_RETURNING_ADVICE_METHOD_NAME,
2735 GET_AFTER_RETURNING_ADVICE_METHOD_SIGNATURE
2736 );
2737 cv.visitFieldInsn(
2738 PUTFIELD,
2739 m_joinPointClassName,
2740 AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
2741 AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE
2742 );
2743
2744 cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2745 cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2746 cv.visitFieldInsn(
2747 GETFIELD,
2748 m_joinPointClassName,
2749 AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
2750 AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE
2751 );
2752 cv.visitInsn(ARRAYLENGTH);
2753 cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AFTER_RETURNING_INTERCEPTORS_FIELD_NAME, I);
2754 }
2755
2756 /***
2757 * Handle the after throwing interceptor init.
2758 *
2759 * @param cv
2760 * @param joinPointInstanceIndex
2761 * @param advisableIndex
2762 */
2763 private void initializeAfterThrowingInterceptors(final CodeVisitor cv,
2764 final int joinPointInstanceIndex,
2765 final int advisableIndex) {
2766 cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2767 cv.visitVarInsn(ALOAD, advisableIndex);
2768 cv.visitTypeInsn(CHECKCAST, ADVISABLE_CLASS_NAME);
2769 cv.visitLdcInsn(new Integer(m_joinPointClassName.hashCode()));
2770 cv.visitMethodInsn(
2771 INVOKEINTERFACE,
2772 ADVISABLE_CLASS_NAME,
2773 GET_AFTER_THROWING_ADVICE_METHOD_NAME,
2774 GET_AFTER_THROWING_ADVICE_METHOD_SIGNATURE
2775 );
2776 cv.visitFieldInsn(
2777 PUTFIELD,
2778 m_joinPointClassName,
2779 AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
2780 AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE
2781 );
2782
2783 cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2784 cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2785 cv.visitFieldInsn(
2786 GETFIELD,
2787 m_joinPointClassName,
2788 AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
2789 AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE
2790 );
2791 cv.visitInsn(ARRAYLENGTH);
2792 cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, NR_OF_AFTER_THROWING_INTERCEPTORS_FIELD_NAME, I);
2793 }
2794
2795 /***
2796 * Handles the around interceptor invocations.
2797 *
2798 * @param cv
2799 */
2800 private void createAroundInterceptorInvocations(final CodeVisitor cv) {
2801 cv.visitVarInsn(ALOAD, 0);
2802 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
2803 cv.visitInsn(ICONST_M1);
2804 Label ifStatementLabel = new Label();
2805 cv.visitJumpInsn(IF_ICMPEQ, ifStatementLabel);
2806 cv.visitVarInsn(ALOAD, 0);
2807 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
2808 cv.visitVarInsn(ALOAD, 0);
2809 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, NR_OF_AROUND_INTERCEPTORS_FIELD_NAME, I);
2810 cv.visitJumpInsn(IF_ICMPGE, ifStatementLabel);
2811 cv.visitVarInsn(ALOAD, 0);
2812 cv.visitFieldInsn(
2813 GETFIELD,
2814 m_joinPointClassName,
2815 AROUND_INTERCEPTORS_FIELD_NAME,
2816 AROUND_ADVICE_ARRAY_CLASS_SIGNATURE
2817 );
2818 cv.visitVarInsn(ALOAD, 0);
2819 cv.visitInsn(DUP);
2820 cv.visitFieldInsn(GETFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
2821 cv.visitInsn(DUP_X1);
2822 cv.visitInsn(ICONST_1);
2823 cv.visitInsn(IADD);
2824 cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
2825 cv.visitInsn(AALOAD);
2826 cv.visitVarInsn(ALOAD, 0);
2827 cv.visitMethodInsn(
2828 INVOKEINTERFACE,
2829 AROUND_ADVICE_CLASS_NAME,
2830 INTERCEPT_INVOKE_METHOD_NAME,
2831 AROUND_ADVICE_INVOKE_METHOD_SIGNATURE
2832 );
2833 cv.visitInsn(ARETURN);
2834 cv.visitLabel(ifStatementLabel);
2835 }
2836
2837 /***
2838 * Creates invocations fo the before interceptors.
2839 *
2840 * @param cv
2841 * @param joinPointInstanceIndex
2842 * @param registerDepth
2843 */
2844 private void createBeforeInterceptorInvocations(final CodeVisitor cv,
2845 final int joinPointInstanceIndex,
2846 final int registerDepth) {
2847 final int loopIndex = registerDepth + 1;
2848 cv.visitInsn(ICONST_0);
2849 cv.visitVarInsn(ISTORE, loopIndex);
2850 Label loopStartLabel = new Label();
2851 cv.visitLabel(loopStartLabel);
2852 cv.visitVarInsn(ILOAD, loopIndex);
2853 cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2854 cv.visitFieldInsn(
2855 GETFIELD,
2856 m_joinPointClassName,
2857 NR_OF_BEFORE_INTERCEPTORS_FIELD_NAME,
2858 I
2859 );
2860 Label loopCheckCondLabel = new Label();
2861 cv.visitJumpInsn(IF_ICMPGE, loopCheckCondLabel);
2862 cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2863 cv.visitFieldInsn(
2864 GETFIELD,
2865 m_joinPointClassName,
2866 BEFORE_INTERCEPTORS_FIELD_NAME,
2867 BEFORE_ADVICE_ARRAY_CLASS_SIGNATURE
2868 );
2869 cv.visitVarInsn(ILOAD, loopIndex);
2870 cv.visitInsn(AALOAD);
2871 cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2872 cv.visitMethodInsn(
2873 INVOKEINTERFACE,
2874 BEFORE_ADVICE_CLASS_NAME,
2875 INTERCEPT_INVOKE_METHOD_NAME,
2876 BEFORE_ADVICE_INVOKE_METHOD_SIGNATURE
2877 );
2878 cv.visitIincInsn(loopIndex, 1);
2879 cv.visitJumpInsn(GOTO, loopStartLabel);
2880 cv.visitLabel(loopCheckCondLabel);
2881 }
2882
2883 /***
2884 * Creates invocations fo the after finally interceptors.
2885 *
2886 * @param cv
2887 * @param joinPointInstanceIndex
2888 * @param registerDepth
2889 */
2890 private void createAfterInterceptorInvocations(final CodeVisitor cv,
2891 final int joinPointInstanceIndex,
2892 final int registerDepth) {
2893 final int loopIndex = registerDepth + 1;
2894 cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2895 cv.visitFieldInsn(
2896 GETFIELD,
2897 m_joinPointClassName,
2898 NR_OF_AFTER_INTERCEPTORS_FIELD_NAME,
2899 I
2900 );
2901 cv.visitInsn(ICONST_1);
2902 cv.visitInsn(ISUB);
2903 cv.visitVarInsn(ISTORE, loopIndex);
2904 Label loopLabel1 = new Label();
2905 cv.visitLabel(loopLabel1);
2906 cv.visitVarInsn(ILOAD, loopIndex);
2907 Label loopLabel2 = new Label();
2908 cv.visitJumpInsn(IFLT, loopLabel2);
2909 cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2910 cv.visitFieldInsn(
2911 GETFIELD,
2912 m_joinPointClassName,
2913 AFTER_INTERCEPTORS_FIELD_NAME,
2914 AFTER_ADVICE_ARRAY_CLASS_SIGNATURE
2915 );
2916 cv.visitVarInsn(ILOAD, loopIndex);
2917 cv.visitInsn(AALOAD);
2918 cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2919 cv.visitMethodInsn(
2920 INVOKEINTERFACE,
2921 AFTER_ADVICE_CLASS_NAME,
2922 INTERCEPT_INVOKE_METHOD_NAME,
2923 AFTER_ADVICE_INVOKE_METHOD_SIGNATURE
2924 );
2925 cv.visitIincInsn(loopIndex, -1);
2926 cv.visitJumpInsn(GOTO, loopLabel1);
2927 cv.visitLabel(loopLabel2);
2928 }
2929
2930 /***
2931 * Creates invocations fo the after returning interceptors.
2932 *
2933 * @param cv
2934 * @param joinPointInstanceIndex
2935 * @param returnValueInstanceIndex
2936 */
2937 private void createAfterReturningInterceptorInvocations(final CodeVisitor cv,
2938 final int joinPointInstanceIndex,
2939 final int returnValueInstanceIndex) {
2940 final int loopIndex = returnValueInstanceIndex + 1;
2941 cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2942 cv.visitFieldInsn(
2943 GETFIELD,
2944 m_joinPointClassName,
2945 NR_OF_AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
2946 I
2947 );
2948 cv.visitInsn(ICONST_1);
2949 cv.visitInsn(ISUB);
2950 cv.visitVarInsn(ISTORE, loopIndex);
2951 Label loopLabel1 = new Label();
2952 cv.visitLabel(loopLabel1);
2953 cv.visitVarInsn(ILOAD, loopIndex);
2954 Label loopLabel2 = new Label();
2955 cv.visitJumpInsn(IFLT, loopLabel2);
2956 cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2957 cv.visitFieldInsn(
2958 GETFIELD,
2959 m_joinPointClassName,
2960 AFTER_RETURNING_INTERCEPTORS_FIELD_NAME,
2961 AFTER_RETURNING_ADVICE_ARRAY_CLASS_SIGNATURE
2962 );
2963 cv.visitVarInsn(ILOAD, loopIndex);
2964 cv.visitInsn(AALOAD);
2965 cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2966 cv.visitVarInsn(ALOAD, returnValueInstanceIndex);
2967 cv.visitMethodInsn(
2968 INVOKEINTERFACE,
2969 AFTER_RETURNING_ADVICE_CLASS_NAME,
2970 INTERCEPT_INVOKE_METHOD_NAME,
2971 AFTER_RETURNING_ADVICE_INVOKE_METHOD_SIGNATURE
2972 );
2973 cv.visitIincInsn(loopIndex, -1);
2974 cv.visitJumpInsn(GOTO, loopLabel1);
2975 cv.visitLabel(loopLabel2);
2976 }
2977
2978 /***
2979 * Creates invocations fo the after returning interceptors.
2980 *
2981 * @param cv
2982 * @param joinPointInstanceIndex
2983 * @param exceptionInstanceIndex
2984 */
2985 private void createAfterThrowingInterceptorInvocations(final CodeVisitor cv,
2986 final int joinPointInstanceIndex,
2987 final int exceptionInstanceIndex) {
2988 final int loopIndex = exceptionInstanceIndex + 1;
2989 cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
2990 cv.visitFieldInsn(
2991 GETFIELD,
2992 m_joinPointClassName,
2993 NR_OF_AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
2994 I
2995 );
2996 cv.visitInsn(ICONST_1);
2997 cv.visitInsn(ISUB);
2998 cv.visitVarInsn(ISTORE, loopIndex);
2999 Label loopLabel1 = new Label();
3000 cv.visitLabel(loopLabel1);
3001 cv.visitVarInsn(ILOAD, loopIndex);
3002 Label loopLabel2 = new Label();
3003 cv.visitJumpInsn(IFLT, loopLabel2);
3004 cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
3005 cv.visitFieldInsn(
3006 GETFIELD,
3007 m_joinPointClassName,
3008 AFTER_THROWING_INTERCEPTORS_FIELD_NAME,
3009 AFTER_THROWING_ADVICE_ARRAY_CLASS_SIGNATURE
3010 );
3011 cv.visitVarInsn(ILOAD, loopIndex);
3012 cv.visitInsn(AALOAD);
3013 cv.visitVarInsn(ALOAD, joinPointInstanceIndex);
3014 cv.visitVarInsn(ALOAD, exceptionInstanceIndex);
3015 cv.visitMethodInsn(
3016 INVOKEINTERFACE,
3017 AFTER_THROWING_ADVICE_CLASS_NAME,
3018 INTERCEPT_INVOKE_METHOD_NAME,
3019 AFTER_THROWING_ADVICE_INVOKE_METHOD_SIGNATURE
3020 );
3021 cv.visitIincInsn(loopIndex, -1);
3022 cv.visitJumpInsn(GOTO, loopLabel1);
3023 cv.visitLabel(loopLabel2);
3024 }
3025
3026 /***
3027 * Checks if the join point requires a proceed() method.
3028 *
3029 * @return
3030 */
3031 protected boolean requiresProceedMethod() {
3032 return m_hasAroundAdvices || m_isThisAdvisable;
3033 }
3034
3035 private static class CustomProceedMethodStruct {
3036 MethodInfo customProceed;
3037 int[] adviceToTargetArgs;
3038
3039 public CustomProceedMethodStruct(MethodInfo customProceed, int[] adviceToTargetArgs) {
3040 this.customProceed = customProceed;
3041 this.adviceToTargetArgs = adviceToTargetArgs;
3042 }
3043 }
3044 }