--- /dev/null
+import org.aspectj.lang.*;
+import org.aspectj.lang.reflect.*;
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface Marker {
+ String message();
+}
+
+public class AnnoBinding {
+ public static void main(String []argv) {
+ long stime = System.currentTimeMillis();
+ for (int i=0;i<10000;i++) {
+ runOne();
+ }
+ long etime = System.currentTimeMillis();
+ long manual = (etime-stime);
+ stime = System.currentTimeMillis();
+ for (int i=0;i<10000;i++) {
+ runTwo();
+ }
+ etime = System.currentTimeMillis();
+ long woven = (etime-stime);
+ System.out.println("woven="+woven+" manual="+manual);
+ if (woven>manual) {
+ throw new RuntimeException("woven="+woven+" manual="+manual);
+ }
+ if (X.a!=X.b) {
+ throw new RuntimeException("a="+X.a+" b="+X.b);
+ }
+ }
+
+ @Marker(message="string")
+ public static void runOne() {
+ }
+
+ @Marker(message="string")
+ public static void runTwo() {
+ }
+
+ static Annotation ajc$anno$1;
+}
+
+aspect X {
+
+ pointcut pManual(): execution(@Marker * runOne(..));
+ pointcut pWoven(Marker l): execution(@Marker * runTwo(..)) && @annotation(l);
+
+ public static int a,b;
+
+ before(): pManual() {
+ Marker marker = (Marker) ((MethodSignature) thisJoinPointStaticPart.getSignature()).getMethod().getAnnotation(Marker.class);
+ String s = marker.message();
+ a+=s.length();
+ }
+
+ before(Marker l): pWoven(l) {
+ String s = l.message();
+ b+=s.length();
+ }
+}
+
+//
+//0: invokestatic #96; //Method X.aspectOf:()LX;
+//3: getstatic #108; //Field ajc$anno$0:Ljava/lang/Annotation;
+//6: dup
+//7: ifnonnull 30
+//10: ldc #1; //class AnnoBinding
+//12: ldc #109; //String runTwo
+//14: iconst_0
+//15: anewarray #111; //class java/lang/Class
+//18: invokevirtual #115; //Method java/lang/Class.getDeclaredMethod:(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Me
+//d;
+//21: ldc #104; //class Marker
+//23: invokevirtual #121; //Method java/lang/reflect/Method.getAnnotation:(Ljava/lang/Class;)Ljava/lang/annotation/Annotation;
+//26: dup
+//27: putstatic #108; //Field ajc$anno$0:Ljava/lang/Annotation;
+//30: nop
+//31: checkcast #104; //class Marker
+//34: invokevirtual #125; //Method X.ajc$before$X$2$ea6844ce:(LMarker;)V
+//37: return
\ No newline at end of file
--- /dev/null
+import org.aspectj.lang.*;
+import org.aspectj.lang.reflect.*;
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface Marker {
+ String message();
+}
+
+public class Perf {
+
+ public static void main(String []argv) {
+ run(true);
+ run(false);
+ }
+
+ public static void run(boolean warmup) {
+ long stime = System.currentTimeMillis();
+ for (int i=0;i<1000000;i++) {
+ runOne();
+ }
+ long etime = System.currentTimeMillis();
+
+ long manual = (etime-stime);
+ stime = System.currentTimeMillis();
+ for (int i=0;i<1000000;i++) {
+ runTwo();
+ }
+ etime = System.currentTimeMillis();
+ long woven = (etime-stime);
+
+ stime = System.currentTimeMillis();
+ for (int i=0;i<1000000;i++) {
+ runThree();
+ }
+ etime = System.currentTimeMillis();
+ long optimal = (etime-stime);
+
+ if (!warmup) {
+ System.out.println("Manually fetching annotation with getAnnotation(): "+manual+"ms");
+ System.out.println("Binding annotation with @annotation(Marker): "+woven+"ms");
+ System.out.println("Binding annotation value with @annotation(Marker(message)): "+optimal+"ms");
+ }
+ if (woven>manual) {
+ throw new RuntimeException("woven = "+woven+" manual = "+manual);
+ }
+ if (optimal>woven) {
+ throw new RuntimeException("optimal = "+optimal+" woven = "+woven);
+ }
+ }
+
+ @Marker(message="string")
+ public static void runOne() {
+ }
+
+ @Marker(message="string")
+ public static void runTwo() {
+ }
+
+ @Marker(message="string")
+ public static void runThree() {
+ }
+}
+
+aspect X {
+ public static int a,b,c;
+
+ // CaseOne: annotation fetching is done in the advice:
+ pointcut adviceRetrievesAnnotation(): execution(@Marker * runOne(..));
+ before(): adviceRetrievesAnnotation() {
+ Marker marker = (Marker) ((MethodSignature) thisJoinPointStaticPart.getSignature()).getMethod().getAnnotation(Marker.class);
+ String s = marker.message();
+ a+=s.length();
+ }
+
+ // CaseTwo: annotation binding is done in the pointcut, advice retrieves message
+ pointcut pointcutBindsAnnotation(Marker l): execution(@Marker * runTwo(..)) && @annotation(l);
+ before(Marker l): pointcutBindsAnnotation(l) {
+ String s = l.message();
+ b+=s.length();
+ }
+
+ // CaseThree: annotation binding directly targets the message value in the annotation
+ pointcut pointcutBindsAnnotationValue(String msg): execution(@Marker * runThree(..)) && @annotation(Marker(msg));
+ before(String s): pointcutBindsAnnotationValue(s) {
+ c+=s.length();
+ }
+}
\ No newline at end of file
--- /dev/null
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface Wibble {
+ String message();
+}
+
+public class StringBinding {
+
+ @Wibble(message="hello world")
+ public static void main(String []argv) {
+ }
+}
+
+aspect X {
+ before(String msg): execution(* *(..)) && @annotation(Wibble(msg)) {
+ System.out.println(msg);
+ }
+}
o.a();
}
- @Anno("hello") public void a() {}
+ @Anno(4) public void a() {}
}
@Retention(RetentionPolicy.RUNTIME)
-@interface Anno { String value(); }
+@interface Anno { int value(); }
aspect X {
- before(String l): execution(@Anno * *(..)) && @annotation(Anno(l)) {
+ before(int l): execution(@Anno * *(..)) && @annotation(Anno(l)) {
System.out.println(l);
}
}
<ajc-test dir="features161/optimizedAnnotationBinding" title="case five - not an enum - compiler limitation">
<compile options="-1.5" files="CaseFive.java">
- <message kind="error" line="20" text="The field within the annotation must be an Enum. 'java.lang.String' is not an Enum"/>
+ <message kind="error" line="20" text="The field within the annotation must be an enum or string. 'int' is not"/>
</compile>
</ajc-test>
<ajc-test dir="features161/optimizedAnnotationBinding" title="case thirteen - bug npe">
<compile options="-1.5" files="CaseThirteen.java">
- <message kind="error" line="31" text="The field within the annotation must be an Enum"/>
<message kind="error" line="31" text="No field of type 'java.lang.String'"/>
<message kind="error" line="31" text="When using @annotation"/>
<message kind="error" line="32" text="cannot be resolved"/>
public class Ajc167Tests extends org.aspectj.testing.XMLBasedAjcTestCase {
+ public void testOptimizingAnnotationStringValueBinding() {
+ runTest("optimizing string anno value binding");
+ }
+
+ public void testOptimizingAnnotationBinding() {
+ runTest("optimizing annotation binding");
+ }
+
+ public void testOptimizingAnnotationBindingPerfTest() {
+ runTest("optimizing annotation binding - 2");
+ }
+/*
+ public void testPerThisLTW_295092() {
+ runTest("perthis ltw");
+ }
+*/
+
public void testNpeOnBrokenCode_296054() {
runTest("npe on broken code");
}
-
+
public void testBrokenGeneratedCode_296040() {
runTest("broken generated code");
}
-
+
public void testHierarchyBuilderNPE_pr293457() {
runTest("hierarchy builder npe");
}
-
+
public void testTimers_1() {
runTest("timers - 1");
}
<suite>
+ <ajc-test dir="bugs167/pr296501" title="optimizing string anno value binding">
+ <compile files="StringBinding.java" options="-1.5"/>
+ <run class="StringBinding">
+ <stdout>
+ <line text="hello world"/>
+ </stdout>
+ </run>
+ </ajc-test>
+
+ <ajc-test dir="bugs167/pr296484" title="optimizing annotation binding">
+ <compile files="AnnoBinding.java" options="-1.5"/>
+ <run class="AnnoBinding"/>
+ </ajc-test>
+
+ <ajc-test dir="bugs167/pr296484" title="optimizing annotation binding - 2">
+ <compile files="Perf.java" options="-1.5"/>
+ <run class="Perf"/>
+ </ajc-test>
+
+ <ajc-test dir="bugs167/pr295092" title="perthis ltw">
+ <compile files="AbstractAspect.aj" options="-1.5" outjar="aspects.jar"/>
+ <compile files="Wibble.java"/>
+ <run class="Wibble" ltw="aop.xml" classpath="aspects.jar"/>
+ </ajc-test>
+
<ajc-test dir="bugs167/pr296054" title="npe on broken code">
<compile files="Demo.java AnnotAspect.aj" options="-1.5 -emacssym">
<message kind="error" text="The value for"/>