From c8ead36f696010fb2783ad889e7df960a83dbd43 Mon Sep 17 00:00:00 2001 From: aclement Date: Sun, 8 Nov 2009 22:56:18 +0000 Subject: [PATCH] fastmatch for execution! --- .../src/org/aspectj/weaver/ReferenceType.java | 1 + .../org/aspectj/weaver/UnresolvedType.java | 5 ++ .../weaver/patterns/FastMatchInfo.java | 3 + .../weaver/patterns/KindedPointcut.java | 87 +++++++++++++++++++ .../weaver/patterns/NotTypePattern.java | 11 +++ .../weaver/patterns/SignaturePattern.java | 26 ++++++ 6 files changed, 133 insertions(+) diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/ReferenceType.java b/org.aspectj.matcher/src/org/aspectj/weaver/ReferenceType.java index caca8f444..e8e7e0b4c 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/ReferenceType.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/ReferenceType.java @@ -609,6 +609,7 @@ public class ReferenceType extends ResolvedType { } ResolvedType[] delegateInterfaces = delegate.getDeclaredInterfaces(); if (newInterfaces != null) { + // OPTIMIZE does this part of the method trigger often? ResolvedType[] extraInterfaces = new ResolvedType[delegateInterfaces.length + newInterfaces.length]; System.arraycopy(delegateInterfaces, 0, extraInterfaces, 0, delegateInterfaces.length); System.arraycopy(newInterfaces, 0, extraInterfaces, delegateInterfaces.length, newInterfaces.length); diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/UnresolvedType.java b/org.aspectj.matcher/src/org/aspectj/weaver/UnresolvedType.java index 722900666..666fed278 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/UnresolvedType.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/UnresolvedType.java @@ -152,6 +152,11 @@ public class UnresolvedType implements Traceable, TypeVariableDeclaringElement { return typeKind == TypeKind.PRIMITIVE; } + public boolean isVoid() { + // OPTIMIZE promote to bitflag? + return signature.equals("V"); + } + public boolean isSimpleType() { return typeKind == TypeKind.SIMPLE; } diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/FastMatchInfo.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/FastMatchInfo.java index d9fddd301..a18830832 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/FastMatchInfo.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/FastMatchInfo.java @@ -17,6 +17,9 @@ import org.aspectj.weaver.Shadow; import org.aspectj.weaver.World; import org.aspectj.weaver.Shadow.Kind; +/** + * Represents a type that pointcuts may match. Fast match for a pointcut should quickly say NO if it can. + */ public class FastMatchInfo { private Kind kind; private ResolvedType type; diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/KindedPointcut.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/KindedPointcut.java index 68d8f05ee..bdfab6714 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/KindedPointcut.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/KindedPointcut.java @@ -12,8 +12,11 @@ package org.aspectj.weaver.patterns; +import static org.aspectj.util.FuzzyBoolean.MAYBE; + import java.io.DataOutputStream; import java.io.IOException; +import java.util.Iterator; import java.util.Map; import org.aspectj.bridge.ISourceLocation; @@ -90,12 +93,96 @@ public class KindedPointcut extends Pointcut { @Override public FuzzyBoolean fastMatch(FastMatchInfo info) { + // info.getKind()==null means all kinds if (info.getKind() != null) { if (info.getKind() != kind) { return FuzzyBoolean.NO; } } + // KindedPointcut represents these join points: + // method-execution/ctor-execution/method-call/ctor-call/field-get/field-set/advice-execution/static-initialization + // initialization/pre-initialization + + // Check if the global fastmatch flag is on - the flag can be removed (and this made default) once it proves stable! + if (info.world.optimizedMatching) { + + // For now, just consider MethodExecution and Initialization + if ((kind == Shadow.MethodExecution || kind == Shadow.Initialization) && info.getKind() == null) { + boolean fastMatchingOnAspect = info.getType().isAspect(); + // an Aspect may define ITDs, and although our signature declaring type pattern may not match on the + // aspect, the ITDs may have a different signature as we iterate through the members of the aspect. Let's not + // try and work through that here and just say MAYBE + if (fastMatchingOnAspect) { + return MAYBE; + } + // Aim here is to do the same test as is done for signature pattern declaring type pattern matching + if (this.getSignature().isExactDeclaringTypePattern()) { + ExactTypePattern typePattern = (ExactTypePattern) this.getSignature().getDeclaringType(); + // Interface checks are more expensive, they could be anywhere... + ResolvedType patternExactType = typePattern.getResolvedExactType(info.world); + if (patternExactType.isInterface()) { + ResolvedType curr = info.getType(); + Iterator hierarchyWalker = curr.getHierarchy(true, true); + boolean found = false; + while (hierarchyWalker.hasNext()) { + curr = hierarchyWalker.next(); + if (typePattern.matchesStatically(curr)) { + found = true; + break; + } + } + if (!found) { + return FuzzyBoolean.NO; + } + } else if (patternExactType.isClass()) { + ResolvedType curr = info.getType(); + do { + if (typePattern.matchesStatically(curr)) { + break; + } + curr = curr.getSuperclass(); + } while (curr != null); + if (curr == null) { + return FuzzyBoolean.NO; + } + } + } else if (this.getSignature().getDeclaringType() instanceof AnyWithAnnotationTypePattern) { + // aim here is to say NO if the annotation is not possible in the hierarchy here + ResolvedType type = info.getType(); + AnnotationTypePattern annotationTypePattern = ((AnyWithAnnotationTypePattern) getSignature().getDeclaringType()) + .getAnnotationPattern(); + if (annotationTypePattern instanceof ExactAnnotationTypePattern) { + ExactAnnotationTypePattern exactAnnotationTypePattern = (ExactAnnotationTypePattern) annotationTypePattern; + if (exactAnnotationTypePattern.getAnnotationValues() == null + || exactAnnotationTypePattern.getAnnotationValues().size() == 0) { + ResolvedType annotationType = exactAnnotationTypePattern.getAnnotationType().resolve(info.world); + if (type.hasAnnotation(annotationType)) { + return FuzzyBoolean.MAYBE; + } + if (annotationType.isInheritedAnnotation()) { + // ok - we may be picking it up from further up the hierarchy (but only a super*class*) + ResolvedType toMatchAgainst = type.getSuperclass(); + boolean found = false; + while (toMatchAgainst != null) { + if (toMatchAgainst.hasAnnotation(annotationType)) { + found = true; + break; + } + toMatchAgainst = toMatchAgainst.getSuperclass(); + } + if (!found) { + return FuzzyBoolean.NO; + } + } else { + return FuzzyBoolean.NO; + } + } + } + } + } + } + return FuzzyBoolean.MAYBE; } diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/NotTypePattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/NotTypePattern.java index 01adce402..14f7dad6d 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/NotTypePattern.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/NotTypePattern.java @@ -34,6 +34,8 @@ import org.aspectj.weaver.World; */ public class NotTypePattern extends TypePattern { private TypePattern negatedPattern; + private boolean isBangVoid = false; // is this '!void' + private boolean checked = false; public NotTypePattern(TypePattern pattern) { super(false, false); // ??? we override all methods that care about includeSubtypes @@ -106,6 +108,15 @@ public class NotTypePattern extends TypePattern { return this; } + @Override + public boolean isBangVoid() { + if (!checked) { + isBangVoid = negatedPattern.getExactType().isVoid(); + checked = true; + } + return isBangVoid; + } + @Override public TypePattern parameterizeWith(Map typeVariableMap, World w) { TypePattern newNegatedPattern = negatedPattern.parameterizeWith(typeVariableMap, w); diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/SignaturePattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/SignaturePattern.java index 51251d9b7..3ca7c2d2f 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/SignaturePattern.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/SignaturePattern.java @@ -419,6 +419,32 @@ public class SignaturePattern extends PatternNode { return FuzzyBoolean.YES; } + /** + * Quickly detect if the joinpoint absolutely cannot match becaused the method parameters at the joinpoint cannot match against + * this signature pattern. + * + * @param methodJoinpoint the joinpoint to quickly match against + * @return true if it is impossible for the joinpoint to match this signature + */ + private boolean parametersCannotMatch(JoinPointSignature methodJoinpoint) { + int patternParameterCount = parameterTypes.size(); + int joinpointParameterCount = methodJoinpoint.getParameterTypes().length; + boolean isVarargs = methodJoinpoint.isVarargsMethod(); + + // Quick rule: pattern specifies zero parameters, and joinpoint has parameters *OR* + if (patternParameterCount == 0 && joinpointParameterCount > 0) { // varargs may allow this... + return true; + } + + // Quick rule: pattern doesn't specify ellipsis and there are a different number of parameters on the + // method join point as compared with the pattern + if (parameterTypes.ellipsisCount == 0 && patternParameterCount != joinpointParameterCount) { + return true; + } + + return false; + } + /** * Matches on name, declaring type, return type, parameter types, throws types */ -- 2.39.5