public boolean forDEBUG_structuralChangesCode = false;
public boolean forDEBUG_bridgingCode = false;
public boolean optimizedMatching = true;
+ protected long timersPerJoinpoint;
+ protected long timersPerType;
- public boolean infoMessagesEnabled = false;
+ public int infoMessagesEnabled = 0; // 0=uninitialized, 1=no, 2=yes
private static Trace trace = TraceFactory.getTraceFactory().getTrace(World.class);
} else {
this.messageHandler = messageHandler;
}
- infoMessagesEnabled = !messageHandler.isIgnoring(IMessage.INFO);
}
/**
}
public boolean areInfoMessagesEnabled() {
- return infoMessagesEnabled;
+ if (infoMessagesEnabled == 0) {
+ infoMessagesEnabled = (messageHandler.isIgnoring(IMessage.INFO) ? 1 : 2);
+ }
+ return infoMessagesEnabled == 2;
}
/**
public final static String xsetFAST_PACK_METHODS = "fastPackMethods"; // default true
public final static String xsetOVERWEAVING = "overWeaving";
public final static String xsetOPTIMIZED_MATCHING = "optimizedMatching";
+ public final static String xsetTIMERS_PER_JOINPOINT = "timersPerJoinpoint";
+ public final static String xsetTIMERS_PER_FASTMATCH_CALL = "timersPerFastMatchCall";
public boolean isInJava5Mode() {
return behaveInJava5Way;
getMessageHandler().handleMessage(MessageUtil.info("[optimizedMatching=false] optimized matching turned off"));
}
+ s = p.getProperty(xsetTIMERS_PER_JOINPOINT, "25000");
+ try {
+ timersPerJoinpoint = Integer.parseInt(s);
+ } catch (Exception e) {
+ getMessageHandler().handleMessage(MessageUtil.error("unable to process timersPerJoinpoint value of " + s));
+ timersPerJoinpoint = 25000;
+ }
+
+ s = p.getProperty(xsetTIMERS_PER_FASTMATCH_CALL, "250");
+ try {
+ timersPerType = Integer.parseInt(s);
+ } catch (Exception e) {
+ getMessageHandler().handleMessage(MessageUtil.error("unable to process timersPerType value of " + s));
+ timersPerType = 250;
+ }
+
}
checkedAdvancedConfiguration = true;
}
*/
public void record(Pointcut pointcut, long timetaken) {
if (timeCollector == null) {
+ ensureAdvancedConfigurationProcessed();
timeCollector = new TimeCollector(this);
}
timeCollector.record(pointcut, timetaken);
*/
public void recordFastMatch(Pointcut pointcut, long timetaken) {
if (timeCollector == null) {
+ ensureAdvancedConfigurationProcessed();
timeCollector = new TimeCollector(this);
}
timeCollector.recordFastMatch(pointcut, timetaken);
long joinpointCount;
long typeCount;
long perJoinpointCount;
+ long perTypes;
Map<String, Long> joinpointsPerPointcut = new HashMap<String, Long>();
Map<String, Long> timePerPointcut = new HashMap<String, Long>();
Map<String, Long> fastMatchTimesPerPointcut = new HashMap<String, Long>();
+ Map<String, Long> fastMatchTypesPerPointcut = new HashMap<String, Long>();
TimeCollector(World world) {
- try {
- this.perJoinpointCount = Integer.parseInt(System.getProperty("org.aspectj.timing.perjoinpoints", "25000"));
- } catch (Throwable t) {
- System.err.println("Problem reading property 'org.aspectj.timing.perjoinpoints':" + t.toString());
- this.perJoinpointCount = 25000;
- }
+ this.perJoinpointCount = world.timersPerJoinpoint;
+ this.perTypes = world.timersPerType;
this.world = world;
this.joinpointCount = 0;
this.typeCount = 0;
totalTime += timePerPointcut.get(p);
}
world.getMessageHandler().handleMessage(
- MessageUtil.info("Pointcut matching cost (total=" + (totalTime / 1000000) + "ms):"));
+ MessageUtil.info("Pointcut matching cost (total=" + (totalTime / 1000000) + "ms for "+joinpointCount+" joinpoint match calls):"));
for (String p : joinpointsPerPointcut.keySet()) {
StringBuffer sb = new StringBuffer();
sb.append("Time:" + (timePerPointcut.get(p) / 1000000) + "ms (jps:#" + joinpointsPerPointcut.get(p)
void recordFastMatch(Pointcut pointcut, long timetakenInNs) {
typeCount++;
String pointcutText = pointcut.toString();
+ Long typecounter = fastMatchTypesPerPointcut.get(pointcutText);
+ if (typecounter == null) {
+ typecounter = 1L;
+ } else {
+ typecounter++;
+ }
+ fastMatchTypesPerPointcut.put(pointcutText, typecounter);
+
Long time = fastMatchTimesPerPointcut.get(pointcutText);
if (time == null) {
time = timetakenInNs;
time += timetakenInNs;
}
fastMatchTimesPerPointcut.put(pointcutText, time);
- if ((typeCount % 250) == 0) {
+ if ((typeCount % perTypes) == 0) {
long totalTime = 0L;
for (String p : fastMatchTimesPerPointcut.keySet()) {
totalTime += fastMatchTimesPerPointcut.get(p);
}
world.getMessageHandler().handleMessage(
- MessageUtil.info("Pointcut fast matching cost (total=" + (totalTime / 1000000) + "ms):"));
+ MessageUtil.info("Pointcut fast matching cost (total=" + (totalTime / 1000000) + "ms for " + typeCount
+ + " fast match calls):"));
for (String p : fastMatchTimesPerPointcut.keySet()) {
StringBuffer sb = new StringBuffer();
- sb.append("Time:" + (fastMatchTimesPerPointcut.get(p) / 1000000) + "ms fast matching against " + p);
+ sb.append("Time:" + (fastMatchTimesPerPointcut.get(p) / 1000000) + "ms (types:#"+fastMatchTypesPerPointcut.get(p)+") fast matching against " + p);
world.getMessageHandler().handleMessage(MessageUtil.info(sb.toString()));
}
world.getMessageHandler().handleMessage(MessageUtil.info("---"));
return this;
}
+ @Override
+ public void setForParameterAnnotationMatch() {
+ }
+
}
\ No newline at end of file
* Contributors
* Andy Clement - extracted from AnnotationTypePattern
* ******************************************************************/
- package org.aspectj.weaver.patterns;
+package org.aspectj.weaver.patterns;
import java.io.DataOutputStream;
import java.io.IOException;
import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.AnnotatedElement;
-import org.aspectj.weaver.World;
import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.World;
public class AnyAnnotationTypePattern extends AnnotationTypePattern {
- public FuzzyBoolean fastMatches(AnnotatedElement annotated) {
- return FuzzyBoolean.YES;
- }
-
+ @Override
+ public FuzzyBoolean fastMatches(AnnotatedElement annotated) {
+ return FuzzyBoolean.YES;
+ }
+
+ @Override
public FuzzyBoolean matches(AnnotatedElement annotated) {
return FuzzyBoolean.YES;
}
-
- public FuzzyBoolean matches(AnnotatedElement annotated,ResolvedType[] parameterAnnotations) {
+
+ @Override
+ public FuzzyBoolean matches(AnnotatedElement annotated, ResolvedType[] parameterAnnotations) {
return FuzzyBoolean.YES;
}
+ @Override
public void write(DataOutputStream s) throws IOException {
s.writeByte(AnnotationTypePattern.ANY_KEY);
}
-
+
+ @Override
public void resolve(World world) {
}
-
- public String toString() { return "@ANY"; }
-
- public Object accept(PatternNodeVisitor visitor, Object data) {
- return visitor.visit(this, data);
- }
-
- public boolean isAny() { return true; }
-
- public AnnotationTypePattern parameterizeWith(Map arg0,World w) {
- return this;
- }
+
+ @Override
+ public String toString() {
+ return "@ANY";
+ }
+
+ @Override
+ public Object accept(PatternNodeVisitor visitor, Object data) {
+ return visitor.visit(this, data);
+ }
+
+ @Override
+ public boolean isAny() {
+ return true;
+ }
+
+ @Override
+ public AnnotationTypePattern parameterizeWith(Map arg0, World w) {
+ return this;
+ }
+
+ @Override
+ public void setForParameterAnnotationMatch() {
+
+ }
}
\ No newline at end of file
private TypePattern declaringType;
private NamePattern name;
private TypePatternList parameterTypes;
+ private int bits = 0x0000;
+ private static final int PARAMETER_ANNOTATION_MATCHING = 0x0001;
+ private static final int CHECKED_FOR_PARAMETER_ANNOTATION_MATCHING = 0x0002;
+
private ThrowsPattern throwsPattern;
private AnnotationTypePattern annotationPattern;
private transient int hashcode = -1;
if (subjectMatch && !throwsPattern.matches(aMethod.getExceptions(), world)) {
return FuzzyBoolean.NO;
}
- if (!declaringType.matchesStatically(aMethod.getDeclaringType().resolve(world))) {
- return FuzzyBoolean.MAYBE;
- }
- if (!returnType.matchesStatically(aMethod.getReturnType().resolve(world))) {
- // looking bad, but there might be parameterization to consider...
- if (!returnType.matchesStatically(aMethod.getGenericReturnType().resolve(world))) {
- // ok, it's bad.
+
+ // '*' trivially matches everything, no need to check further
+ if (!declaringType.isStar()) {
+ if (!declaringType.matchesStatically(aMethod.getDeclaringType().resolve(world))) {
return FuzzyBoolean.MAYBE;
}
}
+
+ // '*' would match any return value
+ if (!returnType.isStar()) {
+ if (!returnType.matchesStatically(aMethod.getReturnType().resolve(world))) {
+ // looking bad, but there might be parameterization to consider...
+ if (!returnType.matchesStatically(aMethod.getGenericReturnType().resolve(world))) {
+ // ok, it's bad.
+ return FuzzyBoolean.MAYBE;
+ }
+ }
+ }
+
+ // The most simple case: pattern is (..) will match anything
+ if (parameterTypes.size() == 1 && parameterTypes.get(0).isEllipsis()) {
+ return FuzzyBoolean.YES;
+ }
+
if (!parameterTypes.canMatchSignatureWithNParameters(aMethod.getParameterTypes().length)) {
return FuzzyBoolean.NO;
}
+
+ // OPTIMIZE both resolution of these types and their annotations should be deferred - just pass down a world and do it lower
+ // down
ResolvedType[] resolvedParameters = world.resolve(aMethod.getParameterTypes());
- ResolvedType[][] parameterAnnotationTypes = aMethod.getParameterAnnotationTypes();
- if (parameterAnnotationTypes == null || parameterAnnotationTypes.length == 0) {
- parameterAnnotationTypes = null;
+
+ // Only fetch the parameter annotations if the pointcut is going to be matching on them
+ ResolvedType[][] parameterAnnotationTypes = null;
+ if (isMatchingParameterAnnotations()) {
+ parameterAnnotationTypes = aMethod.getParameterAnnotationTypes();
+ if (parameterAnnotationTypes != null && parameterAnnotationTypes.length == 0) {
+ parameterAnnotationTypes = null;
+ }
}
+
if (!parameterTypes.matches(resolvedParameters, TypePattern.STATIC, parameterAnnotationTypes).alwaysTrue()) {
// It could still be a match based on the generic sig parameter types of a parameterized type
if (!parameterTypes.matches(world.resolve(aMethod.getGenericParameterTypes()), TypePattern.STATIC,
return FuzzyBoolean.YES;
}
+ /**
+ * Determine if any pattern in the parameter type pattern list is attempting to match on parameter annotations.
+ *
+ * @return true if a parameter type pattern wants to match on a parameter annotation
+ */
+ private boolean isMatchingParameterAnnotations() {
+ if ((bits & CHECKED_FOR_PARAMETER_ANNOTATION_MATCHING) == 0) {
+ bits |= CHECKED_FOR_PARAMETER_ANNOTATION_MATCHING;
+ for (int tp = 0, max = parameterTypes.size(); tp < max; tp++) {
+ TypePattern typePattern = parameterTypes.get(tp);
+ if (isParameterAnnotationMatching(typePattern)) {
+ bits |= PARAMETER_ANNOTATION_MATCHING;
+ }
+ }
+ }
+ return (bits & PARAMETER_ANNOTATION_MATCHING) != 0;
+ }
+
+ /**
+ * Walk the simple structure of a type pattern and determine if any leaf node is involved in parameter annotation matching.
+ */
+ private boolean isParameterAnnotationMatching(TypePattern tp) {
+ if (tp instanceof OrTypePattern) {
+ OrTypePattern orAtp = (OrTypePattern) tp;
+ return (isParameterAnnotationMatching(orAtp.getLeft()) || isParameterAnnotationMatching(orAtp.getRight()));
+ } else if (tp instanceof AndTypePattern) {
+ AndTypePattern andAtp = (AndTypePattern) tp;
+ return (isParameterAnnotationMatching(andAtp.getLeft()) || isParameterAnnotationMatching(andAtp.getRight()));
+ } else if (tp instanceof NotTypePattern) {
+ NotTypePattern notAtp = (NotTypePattern) tp;
+ return (isParameterAnnotationMatching(notAtp.getNegatedPattern()));
+ } else {
+ AnnotationTypePattern atp = tp.getAnnotationPattern();
+ return isParameterAnnotationMatching(atp);
+ }
+ }
+
+ private boolean isParameterAnnotationMatching(AnnotationTypePattern tp) {
+ if (tp instanceof OrAnnotationTypePattern) {
+ OrAnnotationTypePattern orAtp = (OrAnnotationTypePattern) tp;
+ return (isParameterAnnotationMatching(orAtp.getLeft()) || isParameterAnnotationMatching(orAtp.getRight()));
+ } else if (tp instanceof AndAnnotationTypePattern) {
+ AndAnnotationTypePattern andAtp = (AndAnnotationTypePattern) tp;
+ return (isParameterAnnotationMatching(andAtp.getLeft()) || isParameterAnnotationMatching(andAtp.getRight()));
+ } else if (tp instanceof NotAnnotationTypePattern) {
+ NotAnnotationTypePattern notAtp = (NotAnnotationTypePattern) tp;
+ return (isParameterAnnotationMatching(notAtp.negatedPattern));
+ } else {
+ return tp.isForParameterAnnotationMatch();
+ }
+ }
+
private ResolvedType[] getResolvedParameters(World world, UnresolvedType[] unresolvedParams) {
return world.resolve(unresolvedParams);
}