Index: .classpath =================================================================== RCS file: /home/technology/org.aspectj/modules/weaver/.classpath,v retrieving revision 1.1 diff -u -r1.1 .classpath --- .classpath 16 Dec 2002 18:02:43 -0000 1.1 +++ .classpath 3 Nov 2004 14:24:27 -0000 @@ -1,15 +1,14 @@ - - - - - - - - - - - + + + + + + + + + + + Index: src/org/aspectj/weaver/patterns/AndPointcut.java =================================================================== RCS file: /home/technology/org.aspectj/modules/weaver/src/org/aspectj/weaver/patterns/AndPointcut.java,v retrieving revision 1.8 diff -u -r1.8 AndPointcut.java --- src/org/aspectj/weaver/patterns/AndPointcut.java 8 Jun 2004 15:04:34 -0000 1.8 +++ src/org/aspectj/weaver/patterns/AndPointcut.java 3 Nov 2004 14:24:28 -0000 @@ -27,30 +27,98 @@ public class AndPointcut extends Pointcut { Pointcut left, right; // exposed for testing + + private final boolean evaluateLeftFirst; public AndPointcut(Pointcut left, Pointcut right) { super(); this.left = left; this.right = right; setLocation(left.getSourceContext(), left.getStart(), right.getEnd()); + //if left pc is easier to match, match this one first + this.evaluateLeftFirst = this.left.matchingCosts() < this.right.matchingCosts(); } public FuzzyBoolean fastMatch(FastMatchInfo type) { - return left.fastMatch(type).and(right.fastMatch(type)); + if(!Pointcut.USE_LAZY_EVAL) + return this.left.fastMatch(type).and(this.right.fastMatch(type)); + if(this.evaluateLeftFirst) { + FuzzyBoolean leftValue = left.fastMatch(type); + if(leftValue.maybeTrue()) { + return leftValue.and(right.fastMatch(type)); + } else { + return leftValue; + } + } else { + FuzzyBoolean rightValue = right.fastMatch(type); + if(rightValue.maybeTrue()) { + return rightValue.and(left.fastMatch(type)); + } else { + return rightValue; + } + } } public FuzzyBoolean match(Shadow shadow) { - return left.match(shadow).and(right.match(shadow)); + if(!Pointcut.USE_LAZY_EVAL) + return this.left.match(shadow).and(this.right.match(shadow)); + if(this.evaluateLeftFirst) { + FuzzyBoolean leftValue = left.match(shadow); + if(leftValue.maybeTrue()) { + return leftValue.and(right.match(shadow)); + } else { + return leftValue; + } + } else { + FuzzyBoolean rightValue = right.match(shadow); + if(rightValue.maybeTrue()) { + return rightValue.and(left.match(shadow)); + } else { + return rightValue; + } + } } public FuzzyBoolean match(JoinPoint jp, JoinPoint.StaticPart encJP) { - return left.match(jp,encJP).and(right.match(jp,encJP)); + if(!Pointcut.USE_LAZY_EVAL) + return this.left.match(jp,encJP).and(this.right.match(jp,encJP)); + if(this.evaluateLeftFirst) { + FuzzyBoolean leftValue = left.match(jp,encJP); + if(leftValue.maybeTrue()) { + return leftValue.and(right.match(jp,encJP)); + } else { + return leftValue; + } + } else { + FuzzyBoolean rightValue = right.match(jp,encJP); + if(rightValue.maybeTrue()) { + return rightValue.and(left.match(jp,encJP)); + } else { + return rightValue; + } + } } - + public FuzzyBoolean match(JoinPoint.StaticPart jpsp) { - return left.match(jpsp).and(right.match(jpsp)); + if(!Pointcut.USE_LAZY_EVAL) + return this.left.match(jpsp).and(this.right.match(jpsp)); + if(this.evaluateLeftFirst) { + FuzzyBoolean leftValue = left.match(jpsp); + if(leftValue.maybeTrue()) { + return leftValue.and(right.match(jpsp)); + } else { + return leftValue; + } + } else { + FuzzyBoolean rightValue = right.match(jpsp); + if(rightValue.maybeTrue()) { + return rightValue.and(left.match(jpsp)); + } else { + return rightValue; + } + } } - + public String toString() { return "(" + left.toString() + " && " + right.toString() + ")"; } Index: src/org/aspectj/weaver/patterns/OrPointcut.java =================================================================== RCS file: /home/technology/org.aspectj/modules/weaver/src/org/aspectj/weaver/patterns/OrPointcut.java,v retrieving revision 1.8 diff -u -r1.8 OrPointcut.java --- src/org/aspectj/weaver/patterns/OrPointcut.java 8 Jun 2004 15:04:34 -0000 1.8 +++ src/org/aspectj/weaver/patterns/OrPointcut.java 3 Nov 2004 14:24:28 -0000 @@ -28,28 +28,88 @@ public class OrPointcut extends Pointcut { private Pointcut left, right; + private final boolean evaluateLeftFirst; + public OrPointcut(Pointcut left, Pointcut right) { super(); this.left = left; this.right = right; setLocation(left.getSourceContext(), left.getStart(), right.getEnd()); + //if left pc is easier to match, match this one first + this.evaluateLeftFirst = this.left.matchingCosts() < this.right.matchingCosts(); } public FuzzyBoolean fastMatch(FastMatchInfo type) { - return left.fastMatch(type).or(right.fastMatch(type)); + if(this.evaluateLeftFirst) { + FuzzyBoolean leftValue = left.fastMatch(type); + if(leftValue.maybeFalse()) { + return leftValue.or(right.fastMatch(type)); + } else { + return leftValue; + } + } else { + FuzzyBoolean rightValue = right.fastMatch(type); + if(rightValue.maybeFalse()) { + return rightValue.or(left.fastMatch(type)); + } else { + return rightValue; + } + } } public FuzzyBoolean match(Shadow shadow) { - return left.match(shadow).or(right.match(shadow)); + if(this.evaluateLeftFirst) { + FuzzyBoolean leftValue = left.match(shadow); + if(leftValue.maybeFalse()) { + return leftValue.or(right.match(shadow)); + } else { + return leftValue; + } + } else { + FuzzyBoolean rightValue = right.match(shadow); + if(rightValue.maybeFalse()) { + return rightValue.or(left.match(shadow)); + } else { + return rightValue; + } + } } public FuzzyBoolean match(JoinPoint jp, JoinPoint.StaticPart encJP) { - return left.match(jp,encJP).or(right.match(jp,encJP)); + if(this.evaluateLeftFirst) { + FuzzyBoolean leftValue = left.match(jp,encJP); + if(leftValue.maybeFalse()) { + return leftValue.or(right.match(jp,encJP)); + } else { + return leftValue; + } + } else { + FuzzyBoolean rightValue = right.match(jp,encJP); + if(rightValue.maybeFalse()) { + return rightValue.or(left.match(jp,encJP)); + } else { + return rightValue; + } + } } - + public FuzzyBoolean match(JoinPoint.StaticPart jpsp) { - return left.match(jpsp).or(right.match(jpsp)); + if(this.evaluateLeftFirst) { + FuzzyBoolean leftValue = left.match(jpsp); + if(leftValue.maybeFalse()) { + return leftValue.or(right.match(jpsp)); + } else { + return leftValue; + } + } else { + FuzzyBoolean rightValue = right.match(jpsp); + if(rightValue.maybeFalse()) { + return rightValue.or(left.match(jpsp)); + } else { + return rightValue; + } + } } public String toString() { Index: src/org/aspectj/weaver/patterns/Pointcut.java =================================================================== RCS file: /home/technology/org.aspectj/modules/weaver/src/org/aspectj/weaver/patterns/Pointcut.java,v retrieving revision 1.12 diff -u -r1.12 Pointcut.java --- src/org/aspectj/weaver/patterns/Pointcut.java 28 Jul 2004 15:14:50 -0000 1.12 +++ src/org/aspectj/weaver/patterns/Pointcut.java 3 Nov 2004 14:24:29 -0000 @@ -53,6 +53,7 @@ public State state; + public static boolean USE_LAZY_EVAL; /** * Constructor for Pattern. @@ -62,7 +63,15 @@ this.state = SYMBOLIC; } - + /** + * @return The approximate costs of checking for a match + * of this pointcut. This should in most cases be implemented by subclasses. + */ + public int matchingCosts() { + return 0; + } + + /** * Could I match any shadows in the code defined within this type? */ Index: testsrc/org/aspectj/weaver/patterns/AndOrPerformanceTestCase.java =================================================================== RCS file: testsrc/org/aspectj/weaver/patterns/AndOrPerformanceTestCase.java diff -N testsrc/org/aspectj/weaver/patterns/AndOrPerformanceTestCase.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ testsrc/org/aspectj/weaver/patterns/AndOrPerformanceTestCase.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,97 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * PARC initial implementation + * ******************************************************************/ + + +package org.aspectj.weaver.patterns; + +import junit.framework.TestCase; + +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.Signature; +import org.aspectj.runtime.reflect.Factory; +import org.aspectj.util.FuzzyBoolean; + +/** + * @author Eric Bodden + * + * Runs performance tests measuring lazy evaluation of + * pointcut matching. + */ +public class AndOrPerformanceTestCase extends TestCase { + private static final int INNER_ITERATIONS = 100000; + private static final int GLOBAL_ITERATIONS = 10; + /** + * Constructor for PatternTestCase. + * @param name + */ + public AndOrPerformanceTestCase(String name) { + super(name); + } + + public void testLazyEvalPerformance() { + + Pointcut foo = makePointcut("this(org.aspectj.weaver.patterns.AndOrPerformanceTestCase.Foo)").resolve(); + Pointcut bar = makePointcut("this(org.aspectj.weaver.patterns.AndOrPerformanceTestCase.Bar)").resolve(); + Pointcut c = makePointcut("this(org.aspectj.weaver.patterns.AndOrPerformanceTestCase.C)").resolve(); + + Factory f = new Factory("AndOrNotTestCase.java",AndOrPerformanceTestCase.class); + + Signature methodSig = f.makeMethodSig("void aMethod()"); + JoinPoint.StaticPart jpsp = f.makeSJP(JoinPoint.METHOD_EXECUTION,methodSig,1); + JoinPoint jp = Factory.makeJP(jpsp,new Foo(),new Foo()); + + long speedUp=0; + long timeNonLazy=Long.MAX_VALUE; + + for(int iterations=0; iterations0); + } + + private Pointcut makePointcut(String pattern) { + return new PatternParser(pattern).parsePointcut(); + } + + private void checkMatches(Pointcut p, JoinPoint jp, JoinPoint.StaticPart jpsp, FuzzyBoolean expected) { + assertEquals(expected,p.match(jp,jpsp)); + } + + private static class Foo{}; + private static class Bar{}; + private static class C{}; + +}