diff options
author | aclement <aclement> | 2004-08-03 12:31:29 +0000 |
---|---|---|
committer | aclement <aclement> | 2004-08-03 12:31:29 +0000 |
commit | 2982b4cc622a2a95429b16f0aa3c55b7e20d798a (patch) | |
tree | a1453e59e3356d36b7bacaf272298f91f6fa1407 /weaver | |
parent | fe049bdf23ae91b938e64fc2106aebf72be34e3b (diff) | |
download | aspectj-2982b4cc622a2a95429b16f0aa3c55b7e20d798a.tar.gz aspectj-2982b4cc622a2a95429b16f0aa3c55b7e20d798a.zip |
The BIG commit.
- Enhanced structure model support.
- *Incremental* structure model support written and tested (currently switched off, see incModelTests.xml)
- -showWeaveInfo compiler option
- existence of a 'runtimetest' surfaced through relationships
- UI can determine if errors/warnings came from DEOWs.
- Code to enable type mungers to remember source locations written (currently switched off)
Diffstat (limited to 'weaver')
14 files changed, 426 insertions, 22 deletions
diff --git a/weaver/src/org/aspectj/weaver/AsmRelationshipProvider.java b/weaver/src/org/aspectj/weaver/AsmRelationshipProvider.java index a1e1e4a06..b3adcba43 100644 --- a/weaver/src/org/aspectj/weaver/AsmRelationshipProvider.java +++ b/weaver/src/org/aspectj/weaver/AsmRelationshipProvider.java @@ -16,9 +16,11 @@ package org.aspectj.weaver; import java.util.ArrayList; import java.util.Iterator; import org.aspectj.asm.*; +import org.aspectj.asm.internal.AspectJElementHierarchy; import org.aspectj.asm.internal.ProgramElement; import org.aspectj.bridge.ISourceLocation; import org.aspectj.bridge.SourceLocation; +import org.aspectj.weaver.bcel.BcelAdvice; public class AsmRelationshipProvider { @@ -28,6 +30,8 @@ public class AsmRelationshipProvider { public static final String DECLAREDY_BY = "declared by"; public static final String MATCHED_BY = "matched by"; public static final String MATCHES_DECLARE = "matches declare"; + public static final String INTER_TYPE_DECLARES = "declared on"; + public static final String INTER_TYPE_DECLARED_BY = "aspect declarations"; public static void checkerMunger(IHierarchy model, Shadow shadow, Checker checker) { if (shadow.getSourceLocation() == null || checker.getSourceLocation() == null) return; @@ -44,37 +48,116 @@ public class AsmRelationshipProvider { IRelationshipMap mapper = AsmManager.getDefault().getRelationshipMap(); if (sourceHandle != null && targetHandle != null) { - IRelationship foreward = mapper.get(sourceHandle, IRelationship.Kind.DECLARE, MATCHED_BY); - foreward.getTargets().add(targetHandle); + IRelationship foreward = mapper.get(sourceHandle, IRelationship.Kind.DECLARE, MATCHED_BY,false,true); + foreward.addTarget(targetHandle); +// foreward.getTargets().add(targetHandle); - IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE, MATCHES_DECLARE); + IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE, MATCHES_DECLARE,false,true); if (back != null && back.getTargets() != null) { - back.getTargets().add(sourceHandle); + back.addTarget(sourceHandle); + //back.getTargets().add(sourceHandle); } } } + + // For ITDs + public static void addRelationship( + ResolvedTypeX onType, + ResolvedTypeMunger munger, + ResolvedTypeX originatingAspect) { + + String sourceHandle = ""; + if (munger.getSourceLocation()!=null) { + sourceHandle = ProgramElement.createHandleIdentifier( + munger.getSourceLocation().getSourceFile(), + munger.getSourceLocation().getLine(), + munger.getSourceLocation().getColumn()); + } else { + sourceHandle = ProgramElement.createHandleIdentifier( + originatingAspect.getSourceLocation().getSourceFile(), + originatingAspect.getSourceLocation().getLine(), + originatingAspect.getSourceLocation().getColumn()); + } + if (originatingAspect.getSourceLocation() != null) { + + String targetHandle = ProgramElement.createHandleIdentifier( + onType.getSourceLocation().getSourceFile(), + onType.getSourceLocation().getLine(), + onType.getSourceLocation().getColumn()); + + IRelationshipMap mapper = AsmManager.getDefault().getRelationshipMap(); + if (sourceHandle != null && targetHandle != null) { + IRelationship foreward = mapper.get(sourceHandle, IRelationship.Kind.DECLARE_INTER_TYPE, INTER_TYPE_DECLARES,false,true); + foreward.addTarget(targetHandle); +// foreward.getTargets().add(targetHandle); + + IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE_INTER_TYPE, INTER_TYPE_DECLARED_BY,false,true); + back.addTarget(sourceHandle); +// back.getTargets().add(sourceHandle); + } + } + } + + public static void addDeclareParentsRelationship(ISourceLocation decp,ResolvedTypeX targetType) { + + String sourceHandle = ProgramElement.createHandleIdentifier(decp.getSourceFile(),decp.getLine(),decp.getColumn()); + + IProgramElement ipe = AsmManager.getDefault().getHierarchy().findElementForHandle(sourceHandle); + + + String targetHandle = ProgramElement.createHandleIdentifier( + targetType.getSourceLocation().getSourceFile(), + targetType.getSourceLocation().getLine(), + targetType.getSourceLocation().getColumn()); + + IRelationshipMap mapper = AsmManager.getDefault().getRelationshipMap(); + if (sourceHandle != null && targetHandle != null) { + IRelationship foreward = mapper.get(sourceHandle, IRelationship.Kind.DECLARE_INTER_TYPE, INTER_TYPE_DECLARES,false,true); + foreward.addTarget(targetHandle); + + IRelationship back = mapper.get(targetHandle, IRelationship.Kind.DECLARE_INTER_TYPE, INTER_TYPE_DECLARED_BY,false,true); + back.addTarget(sourceHandle); + } + + } public static void adviceMunger(IHierarchy model, Shadow shadow, ShadowMunger munger) { if (munger instanceof Advice) { Advice advice = (Advice)munger; + if (advice.getKind().isPerEntry() || advice.getKind().isCflow()) { // TODO: might want to show these in the future return; } + IRelationshipMap mapper = AsmManager.getDefault().getRelationshipMap(); - IProgramElement targetNode = getNode(AsmManager.getDefault().getHierarchy(), shadow); + IProgramElement targetNode = getNode(AsmManager.getDefault().getHierarchy(), shadow); + boolean runtimeTest = ((BcelAdvice)munger).hasDynamicTests(); + + // Work out extra info to inform interested UIs ! + IProgramElement.ExtraInformation ai = new IProgramElement.ExtraInformation(); + String adviceHandle = advice.getHandle(); + + // What kind of advice is it? + // TODO: Prob a better way to do this but I just want to + // get it into CVS !!! + AdviceKind ak = ((Advice)munger).getKind(); + ai.setExtraAdviceInformation(ak.getName()); + IProgramElement adviceElement = AsmManager.getDefault().getHierarchy().findElementForHandle(adviceHandle); + adviceElement.setExtraInfo(ai); + if (adviceHandle != null && targetNode != null) { if (targetNode != null) { String targetHandle = targetNode.getHandleIdentifier(); - IRelationship foreward = mapper.get(adviceHandle, IRelationship.Kind.ADVICE, ADVISES); - if (foreward != null) foreward.getTargets().add(targetHandle); + IRelationship foreward = mapper.get(adviceHandle, IRelationship.Kind.ADVICE, ADVISES,runtimeTest,true); + if (foreward != null) foreward.addTarget(targetHandle);//foreward.getTargets().add(targetHandle); - IRelationship back = mapper.get(targetHandle, IRelationship.Kind.ADVICE, ADVISED_BY); - if (back != null) back.getTargets().add(adviceHandle); + IRelationship back = mapper.get(targetHandle, IRelationship.Kind.ADVICE, ADVISED_BY,runtimeTest,true); + if (back != null) back.addTarget(adviceHandle);//back.getTargets().add(adviceHandle); } } @@ -102,12 +185,19 @@ public class AsmRelationshipProvider { } } + private static boolean sourceLinesMatch(ISourceLocation loc1,ISourceLocation loc2) { + if (loc1.getLine()!=loc2.getLine()) return false; + return true; + } + + private static IProgramElement findOrCreateCodeNode(IProgramElement enclosingNode, Member shadowSig, Shadow shadow) { for (Iterator it = enclosingNode.getChildren().iterator(); it.hasNext(); ) { IProgramElement node = (IProgramElement)it.next(); if (shadowSig.getName().equals(node.getBytecodeName()) && - shadowSig.getSignature().equals(node.getBytecodeSignature())) + shadowSig.getSignature().equals(node.getBytecodeSignature()) && + sourceLinesMatch(node.getSourceLocation(),shadow.getSourceLocation())) { return node; } diff --git a/weaver/src/org/aspectj/weaver/Checker.java b/weaver/src/org/aspectj/weaver/Checker.java index c87221bfa..e8f5266f7 100644 --- a/weaver/src/org/aspectj/weaver/Checker.java +++ b/weaver/src/org/aspectj/weaver/Checker.java @@ -52,11 +52,15 @@ public class Checker extends ShadowMunger { isError ? IMessage.ERROR : IMessage.WARNING, shadow.getSourceLocation(), null, - new ISourceLocation[]{this.getSourceLocation()}); - world.getMessageHandler().handleMessage(message); + new ISourceLocation[]{this.getSourceLocation()},true); + + world.getMessageHandler().handleMessage(message); if (world.xrefHandler != null) { - world.xrefHandler.addCrossReference(this.getSourceLocation(),shadow.getSourceLocation(),IRelationship.Kind.DECLARE); + world.xrefHandler.addCrossReference(this.getSourceLocation(), + shadow.getSourceLocation(), + (this.isError?IRelationship.Kind.DECLARE_ERROR:IRelationship.Kind.DECLARE_WARNING),false); + } if (world.getModel() != null) { diff --git a/weaver/src/org/aspectj/weaver/ConcreteTypeMunger.java b/weaver/src/org/aspectj/weaver/ConcreteTypeMunger.java index 0ce029a55..0f0ecf022 100644 --- a/weaver/src/org/aspectj/weaver/ConcreteTypeMunger.java +++ b/weaver/src/org/aspectj/weaver/ConcreteTypeMunger.java @@ -44,7 +44,8 @@ public abstract class ConcreteTypeMunger implements PartialOrder.PartialComparab } public ISourceLocation getSourceLocation() { - return null; //XXX + if (munger == null) return null; + return munger.getSourceLocation(); //XXX } public boolean matches(ResolvedTypeX onType) { diff --git a/weaver/src/org/aspectj/weaver/ICrossReferenceHandler.java b/weaver/src/org/aspectj/weaver/ICrossReferenceHandler.java index c0ffeae40..cb2fe93c3 100644 --- a/weaver/src/org/aspectj/weaver/ICrossReferenceHandler.java +++ b/weaver/src/org/aspectj/weaver/ICrossReferenceHandler.java @@ -20,6 +20,10 @@ import org.aspectj.bridge.ISourceLocation; */ public interface ICrossReferenceHandler { - void addCrossReference(ISourceLocation from, ISourceLocation to, IRelationship.Kind kind); + void addCrossReference( + ISourceLocation from, + ISourceLocation to, + IRelationship.Kind kind, + boolean runtimeTest); } diff --git a/weaver/src/org/aspectj/weaver/NewConstructorTypeMunger.java b/weaver/src/org/aspectj/weaver/NewConstructorTypeMunger.java index 0f4ac0fb7..699ed9736 100644 --- a/weaver/src/org/aspectj/weaver/NewConstructorTypeMunger.java +++ b/weaver/src/org/aspectj/weaver/NewConstructorTypeMunger.java @@ -49,14 +49,17 @@ public class NewConstructorTypeMunger extends ResolvedTypeMunger { syntheticConstructor.write(s); explicitConstructor.write(s); writeSuperMethodsCalled(s); + if (ResolvedTypeMunger.persistSourceLocation) writeSourceLocation(s); } public static ResolvedTypeMunger readConstructor(DataInputStream s, ISourceContext context) throws IOException { - return new NewConstructorTypeMunger( + ResolvedTypeMunger munger = new NewConstructorTypeMunger( ResolvedMember.readResolvedMember(s, context), ResolvedMember.readResolvedMember(s, context), ResolvedMember.readResolvedMember(s, context), readSuperMethodsCalled(s)); + if (ResolvedTypeMunger.persistSourceLocation) munger.setSourceLocation(readSourceLocation(s)); + return munger; } public ResolvedMember getExplicitConstructor() { diff --git a/weaver/src/org/aspectj/weaver/NewFieldTypeMunger.java b/weaver/src/org/aspectj/weaver/NewFieldTypeMunger.java index 8733a3b8d..3ef81e57b 100644 --- a/weaver/src/org/aspectj/weaver/NewFieldTypeMunger.java +++ b/weaver/src/org/aspectj/weaver/NewFieldTypeMunger.java @@ -32,12 +32,15 @@ public class NewFieldTypeMunger extends ResolvedTypeMunger { kind.write(s); signature.write(s); writeSuperMethodsCalled(s); + if (ResolvedTypeMunger.persistSourceLocation) writeSourceLocation(s); } public static ResolvedTypeMunger readField(DataInputStream s, ISourceContext context) throws IOException { - return new NewFieldTypeMunger( + ResolvedTypeMunger munger = new NewFieldTypeMunger( ResolvedMember.readResolvedMember(s, context), readSuperMethodsCalled(s)); + if (ResolvedTypeMunger.persistSourceLocation) munger.setSourceLocation(readSourceLocation(s)); + return munger; } public ResolvedMember getMatchingSyntheticMember(Member member, ResolvedTypeX aspectType) { diff --git a/weaver/src/org/aspectj/weaver/NewMethodTypeMunger.java b/weaver/src/org/aspectj/weaver/NewMethodTypeMunger.java index 92fcb2c8e..f42f74458 100644 --- a/weaver/src/org/aspectj/weaver/NewMethodTypeMunger.java +++ b/weaver/src/org/aspectj/weaver/NewMethodTypeMunger.java @@ -37,12 +37,15 @@ public class NewMethodTypeMunger extends ResolvedTypeMunger { kind.write(s); signature.write(s); writeSuperMethodsCalled(s); + if (ResolvedTypeMunger.persistSourceLocation) writeSourceLocation(s); } public static ResolvedTypeMunger readMethod(DataInputStream s, ISourceContext context) throws IOException { - return new NewMethodTypeMunger( + ResolvedTypeMunger munger = new NewMethodTypeMunger( ResolvedMember.readResolvedMember(s, context), readSuperMethodsCalled(s)); + if (ResolvedTypeMunger.persistSourceLocation) munger.setSourceLocation(readSourceLocation(s)); + return munger; } public ResolvedMember getMatchingSyntheticMember(Member member, ResolvedTypeX aspectType) { diff --git a/weaver/src/org/aspectj/weaver/ResolvedTypeMunger.java b/weaver/src/org/aspectj/weaver/ResolvedTypeMunger.java index 55e0a4e3e..aa1ff7223 100644 --- a/weaver/src/org/aspectj/weaver/ResolvedTypeMunger.java +++ b/weaver/src/org/aspectj/weaver/ResolvedTypeMunger.java @@ -15,7 +15,10 @@ package org.aspectj.weaver; import java.io.DataInputStream; import java.io.DataOutputStream; +import java.io.File; import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -23,6 +26,8 @@ import java.util.Iterator; import java.util.List; import java.util.Set; +import org.aspectj.bridge.ISourceLocation; +import org.aspectj.bridge.SourceLocation; import org.aspectj.util.TypeSafeEnum; /** This is an abstraction over method/field introduction. It might not have the chops @@ -33,12 +38,24 @@ public abstract class ResolvedTypeMunger { protected Kind kind; protected ResolvedMember signature; + public static transient boolean persistSourceLocation = false; + private Set /* resolvedMembers */ superMethodsCalled = Collections.EMPTY_SET; + + private ISourceLocation location; // Lost during serialize/deserialize ! public ResolvedTypeMunger(Kind kind, ResolvedMember signature) { this.kind = kind; this.signature = signature; } + + public void setSourceLocation(ISourceLocation isl) { + location = isl; + } + + public ISourceLocation getSourceLocation() { + return location; + } // ---- @@ -95,7 +112,10 @@ public abstract class ResolvedTypeMunger { } } + + protected static Set readSuperMethodsCalled(DataInputStream s) throws IOException { + Set ret = new HashSet(); int n = s.readInt(); for (int i=0; i < n; i++) { @@ -105,6 +125,7 @@ public abstract class ResolvedTypeMunger { } protected void writeSuperMethodsCalled(DataOutputStream s) throws IOException { + if (superMethodsCalled == null) { s.writeInt(0); return; @@ -118,6 +139,40 @@ public abstract class ResolvedTypeMunger { ResolvedMember m = (ResolvedMember)i.next(); m.write(s); } + + } + + protected static ISourceLocation readSourceLocation(DataInputStream s) throws IOException { + if (!persistSourceLocation) return null; + ISourceLocation ret = null; + ObjectInputStream ois = new ObjectInputStream(s); + try { + Boolean validLocation = (Boolean)ois.readObject(); + if (validLocation.booleanValue()) { + File f = (File) ois.readObject(); + Integer ii = (Integer)ois.readObject(); + ret = new SourceLocation(f,ii.intValue()); + } + } catch (IOException ioe) { + // Something went wrong, maybe this is an 'old style' file that doesnt attach locations to mungers + ioe.printStackTrace(); + return null; + } catch (ClassNotFoundException e) { } + ois.close(); + return ret; + } + + protected void writeSourceLocation(DataOutputStream s) throws IOException { + if (!persistSourceLocation) return; + ObjectOutputStream oos = new ObjectOutputStream(s); + // oos.writeObject(location); + oos.writeObject(new Boolean(location!=null)); + if (location !=null) { + oos.writeObject(location.getSourceFile()); + oos.writeObject(new Integer(location.getLine())); + } + oos.flush(); + oos.close(); } diff --git a/weaver/src/org/aspectj/weaver/Shadow.java b/weaver/src/org/aspectj/weaver/Shadow.java index 42e2920e4..b34f62e7e 100644 --- a/weaver/src/org/aspectj/weaver/Shadow.java +++ b/weaver/src/org/aspectj/weaver/Shadow.java @@ -26,6 +26,7 @@ import org.aspectj.lang.JoinPoint; import org.aspectj.util.PartialOrder; import org.aspectj.util.TypeSafeEnum; import org.aspectj.weaver.ast.Var; +import org.aspectj.weaver.bcel.BcelAdvice; /* * The superclass of anything representing a the shadow of a join point. A shadow represents @@ -345,6 +346,89 @@ public abstract class Shadow { protected void prepareForMungers() { throw new RuntimeException("Generic shadows cannot be prepared"); } + + /* + * Ensure we report a nice source location - particular in the case + * where the source info is missing (binary weave). + */ + private String beautifyLocation(ISourceLocation isl) { + StringBuffer nice = new StringBuffer(); + if (isl==null || isl.getSourceFile()==null || isl.getSourceFile().getName().indexOf("no debug info available")!=-1) { + nice.append("no debug info available"); + } else { + nice.append(isl.getSourceFile().getName()); + if (isl.getLine()!=0) nice.append(":").append(isl.getLine()); + } + return nice.toString(); + } + + /* + * Report a message about the advice weave that has occurred. Some messing about + * to make it pretty ! This code is just asking for an NPE to occur ... + */ + private void reportWeavingMessage(ShadowMunger munger) { + Advice advice = (Advice)munger; + AdviceKind aKind = advice.getKind(); + // Only report on interesting advice kinds ... + if (aKind == null || advice.getConcreteAspect()==null) { + // We suspect someone is programmatically driving the weaver + // (e.g. IdWeaveTestCase in the weaver testcases) + return; + } + if (!( aKind.equals(AdviceKind.Before) || + aKind.equals(AdviceKind.After) || + aKind.equals(AdviceKind.AfterReturning) || + aKind.equals(AdviceKind.AfterThrowing) || + aKind.equals(AdviceKind.Around) || + aKind.equals(AdviceKind.Softener))) return; + + String description = advice.getKind().toString(); + String advisedType = this.getEnclosingType().getName(); + String advisingType= advice.getConcreteAspect().getName(); + Message msg = null; + if (advice.getKind().equals(AdviceKind.Softener)) { + msg = WeaveMessage.constructWeavingMessage( + WeaveMessage.WEAVEMESSAGE_SOFTENS, + new String[]{advisedType,beautifyLocation(getSourceLocation()), + advisingType,beautifyLocation(munger.getSourceLocation())}); + } else { + boolean runtimeTest = ((BcelAdvice)advice).hasDynamicTests(); + msg = WeaveMessage.constructWeavingMessage(WeaveMessage.WEAVEMESSAGE_ADVISES, + new String[]{ advisedType, beautifyLocation(getSourceLocation()), + description, + advisingType,beautifyLocation(munger.getSourceLocation()), + (runtimeTest?" [with runtime test]":"")}); + // Boolean.toString(runtimeTest)}); + } + getIWorld().getMessageHandler().handleMessage(msg); + } + + + public IRelationship.Kind determineRelKind(ShadowMunger munger) { + AdviceKind ak = ((Advice)munger).getKind(); + if (ak.getKey()==AdviceKind.Before.getKey()) + return IRelationship.Kind.ADVICE_BEFORE; + else if (ak.getKey()==AdviceKind.After.getKey()) + return IRelationship.Kind.ADVICE_AFTER; + else if (ak.getKey()==AdviceKind.AfterThrowing.getKey()) + return IRelationship.Kind.ADVICE_AFTERTHROWING; + else if (ak.getKey()==AdviceKind.AfterReturning.getKey()) + return IRelationship.Kind.ADVICE_AFTERRETURNING; + else if (ak.getKey()==AdviceKind.Around.getKey()) + return IRelationship.Kind.ADVICE_AROUND; + else if (ak.getKey()==AdviceKind.CflowEntry.getKey() || + ak.getKey()==AdviceKind.CflowBelowEntry.getKey() || + ak.getKey()==AdviceKind.InterInitializer.getKey() || + ak.getKey()==AdviceKind.PerCflowEntry.getKey() || + ak.getKey()==AdviceKind.PerCflowBelowEntry.getKey() || + ak.getKey()==AdviceKind.PerThisEntry.getKey() || + ak.getKey()==AdviceKind.PerTargetEntry.getKey() || + ak.getKey()==AdviceKind.Softener.getKey()) { + System.err.println("Dont want a message about this: "+ak); + return null; + } + throw new RuntimeException("Shadow.determineRelKind: What the hell is it? "+ak); + } /** Actually implement the (non-empty) mungers associated with this shadow */ private void implementMungers() { @@ -354,9 +438,19 @@ public abstract class Shadow { munger.implementOn(this); if (world.xrefHandler != null) { - world.xrefHandler.addCrossReference(munger.getSourceLocation(),this.getSourceLocation(),IRelationship.Kind.ADVICE); + world.xrefHandler.addCrossReference( + munger.getSourceLocation(), // What is being applied + this.getSourceLocation(), // Where is it being applied + determineRelKind(munger), // What kind of advice? + ((BcelAdvice)munger).hasDynamicTests() // Is a runtime test being stuffed in the code? + ); } + // TAG: WeavingMessage + if (!getIWorld().getMessageHandler().isIgnoring(IMessage.WEAVEINFO)) { + reportWeavingMessage(munger); + } + if (world.getModel() != null) { //System.err.println("munger: " + munger + " on " + this); AsmRelationshipProvider.adviceMunger(world.getModel(), this, munger); diff --git a/weaver/src/org/aspectj/weaver/WeaverMetrics.java b/weaver/src/org/aspectj/weaver/WeaverMetrics.java new file mode 100644 index 000000000..113be2943 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/WeaverMetrics.java @@ -0,0 +1,85 @@ +/* ******************************************************************* + * Copyright (c) 2004 IBM Corporation and others. + * 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: + * Andy Clement initial implementation + * ******************************************************************/ +package org.aspectj.weaver; + +import org.aspectj.util.FuzzyBoolean; +import org.aspectj.weaver.patterns.FastMatchInfo; + + +/** + * Records stats about the weaver. Information like 'how many types are dismissed during fast match' that + * may be useful for trying to tune pointcuts. Not publicised. + */ +public class WeaverMetrics { + + // Level 1 of matching is at the type level, which types can be dismissed? + public static int fastMatchOnTypeAttempted = 0; + public static int fastMatchOnTypeTrue = 0; + public static int fastMatchOnTypeFalse = 0; + + // Level 2 of matching is fast matching on the shadows in the remaining types + public static int fastMatchOnShadowsAttempted = 0; + public static int fastMatchOnShadowsTrue = 0; + public static int fastMatchOnShadowsFalse = 0; + + // Level 3 of matching is slow matching on the shadows (more shadows than were fast matched on!) + public static int matchTrue = 0; + public static int matchAttempted = 0; + + + + public static void reset() { + + fastMatchOnShadowsAttempted = 0; + fastMatchOnShadowsTrue = 0; + fastMatchOnShadowsFalse = 0; + + fastMatchOnTypeAttempted = 0; + fastMatchOnTypeTrue = 0; + fastMatchOnTypeFalse = 0; + + matchTrue = 0; + matchAttempted = 0; + } + + + public static void dumpInfo() { + System.err.println("Match summary:"); + int fastMatchOnTypeMaybe = (fastMatchOnTypeAttempted-fastMatchOnTypeTrue-fastMatchOnTypeFalse); + System.err.print("At the type level, we attempted #"+fastMatchOnTypeAttempted+" fast matches:"); + System.err.println(" YES/NO/MAYBE = "+fastMatchOnTypeTrue+"/"+fastMatchOnTypeFalse+"/"+fastMatchOnTypeMaybe); + int fastMatchMaybe = (fastMatchOnShadowsAttempted-fastMatchOnShadowsFalse-fastMatchOnShadowsTrue); + System.err.print("Within those #"+(fastMatchOnTypeTrue+fastMatchOnTypeMaybe)+" possible types, "); + System.err.print("we fast matched on #"+fastMatchOnShadowsAttempted+" shadows:"); + System.err.println(" YES/NO/MAYBE = "+fastMatchOnShadowsTrue+"/"+fastMatchOnShadowsFalse+"/"+fastMatchMaybe); + System.err.println("Shadow (non-fast) matches attempted #"+matchAttempted+" of which "+matchTrue+" successful"); + } + + + public static void recordFastMatchTypeResult(FuzzyBoolean fb) { + fastMatchOnTypeAttempted++; + if (fb.alwaysTrue()) fastMatchOnTypeTrue++; + if (fb.alwaysFalse()) fastMatchOnTypeFalse++; + } + + public static void recordFastMatchResult(FuzzyBoolean fb) { + fastMatchOnShadowsAttempted++; + if (fb.alwaysTrue()) fastMatchOnShadowsTrue++; + if (fb.alwaysFalse()) fastMatchOnShadowsFalse++; + } + + public static void recordMatchResult(boolean b) { + matchAttempted++; + if (b) matchTrue++; + } + +} diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java b/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java index ad561a98e..92e83c874 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelClassWeaver.java @@ -48,6 +48,7 @@ import org.apache.bcel.generic.ReturnInstruction; import org.apache.bcel.generic.Select; import org.apache.bcel.generic.Type; import org.aspectj.bridge.IMessage; +import org.aspectj.util.FuzzyBoolean; import org.aspectj.util.PartialOrder; import org.aspectj.weaver.AjAttribute; import org.aspectj.weaver.AjcMemberMaker; @@ -56,6 +57,7 @@ import org.aspectj.weaver.ConcreteTypeMunger; import org.aspectj.weaver.IClassWeaver; import org.aspectj.weaver.IntMap; import org.aspectj.weaver.Member; +import org.aspectj.weaver.WeaverMetrics; import org.aspectj.weaver.NameMangler; import org.aspectj.weaver.NewFieldTypeMunger; import org.aspectj.weaver.ResolvedMember; @@ -172,7 +174,9 @@ class BcelClassWeaver implements IClassWeaver { FastMatchInfo info = new FastMatchInfo(clazz.getType(), kind); for (Iterator i = shadowMungers.iterator(); i.hasNext();) { ShadowMunger munger = (ShadowMunger) i.next(); - if (munger.getPointcut().fastMatch(info).maybeTrue()) mungers.add(munger); + FuzzyBoolean fb = munger.getPointcut().fastMatch(info); + WeaverMetrics.recordFastMatchResult(fb);// Could pass: munger.getPointcut().toString() + if (fb.maybeTrue()) mungers.add(munger); } } @@ -1120,13 +1124,19 @@ class BcelClassWeaver implements IClassWeaver { for (Iterator i = shadowMungers.iterator(); i.hasNext(); ) { ShadowMunger munger = (ShadowMunger)i.next(); if (munger.match(shadow, world)) { + + WeaverMetrics.recordMatchResult(true);// Could pass: munger shadow.addMunger(munger); isMatched = true; if (shadow.getKind() == Shadow.StaticInitialization) { clazz.warnOnAddedStaticInitializer(shadow,munger.getSourceLocation()); } - } + + } else { + WeaverMetrics.recordMatchResult(false); // Could pass: munger + } } + if (isMatched) shadowAccumulator.add(shadow); return isMatched; } diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java b/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java index 2fef3a0c1..4d031bcb9 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelTypeMunger.java @@ -23,7 +23,10 @@ import org.apache.bcel.generic.InstructionConstants; import org.apache.bcel.generic.InstructionFactory; import org.apache.bcel.generic.InstructionList; import org.apache.bcel.generic.Type; +import org.aspectj.bridge.IMessage; +import org.aspectj.bridge.WeaveMessage; import org.aspectj.weaver.AjcMemberMaker; +import org.aspectj.weaver.AsmRelationshipProvider; import org.aspectj.weaver.ConcreteTypeMunger; import org.aspectj.weaver.Member; import org.aspectj.weaver.NameMangler; @@ -54,6 +57,7 @@ public class BcelTypeMunger extends ConcreteTypeMunger { public boolean munge(BcelClassWeaver weaver) { boolean changed = false; + boolean worthReporting = true; if (munger.getKind() == ResolvedTypeMunger.Field) { changed = mungeNewField(weaver, (NewFieldTypeMunger)munger); @@ -61,8 +65,10 @@ public class BcelTypeMunger extends ConcreteTypeMunger { changed = mungeNewMethod(weaver, (NewMethodTypeMunger)munger); } else if (munger.getKind() == ResolvedTypeMunger.PerObjectInterface) { changed = mungePerObjectInterface(weaver, (PerObjectInterfaceTypeMunger)munger); + worthReporting = false; } else if (munger.getKind() == ResolvedTypeMunger.PrivilegedAccess) { changed = mungePrivilegedAccess(weaver, (PrivilegedAccessMunger)munger); + worthReporting = false; } else if (munger.getKind() == ResolvedTypeMunger.Constructor) { changed = mungeNewConstructor(weaver, (NewConstructorTypeMunger)munger); } else if (munger.getKind() == ResolvedTypeMunger.Parent) { @@ -76,6 +82,43 @@ public class BcelTypeMunger extends ConcreteTypeMunger { weaver.getLazyClassGen().getOrCreateWeaverStateInfo(); info.addConcreteMunger(this); } + // Whilst type mungers aren't persisting their source locations, we add this relationship during + // compilation time (see other reference to ResolvedTypeMunger.persist) + if (ResolvedTypeMunger.persistSourceLocation) { + if (changed) { + if (munger.getKind().equals(ResolvedTypeMunger.Parent)) { + AsmRelationshipProvider.addRelationship(weaver.getLazyClassGen().getType(), munger,getAspectType()); + } else { + AsmRelationshipProvider.addRelationship(weaver.getLazyClassGen().getType(), munger,getAspectType()); + } + } + } + + // TAG: WeavingMessage + if (worthReporting && munger!=null && !weaver.getWorld().getMessageHandler().isIgnoring(IMessage.WEAVEINFO)) { + String tName = weaver.getLazyClassGen().getType().getSourceLocation().getSourceFile().getName(); + if (tName.indexOf("no debug info available")!=-1) tName = "no debug info available"; + String fName = getAspectType().getSourceLocation().getSourceFile().getName(); + if (munger.getKind().equals(ResolvedTypeMunger.Parent)) { + // This message will come out of AjLookupEnvironment.addParent if doing a source + // compilation. + NewParentTypeMunger parentTM = (NewParentTypeMunger)munger; + if (parentTM.getNewParent().isInterface()) { + weaver.getWorld().getMessageHandler().handleMessage(WeaveMessage.constructWeavingMessage(WeaveMessage.WEAVEMESSAGE_DECLAREPARENTSIMPLEMENTS, + new String[]{weaver.getLazyClassGen().getType().getName(), + tName,parentTM.getNewParent().getName(),fName})); + } else { + System.err.println("BANG, you need to fix this. BcelTypeMunger"); + } + } else { + weaver.getWorld().getMessageHandler().handleMessage(WeaveMessage.constructWeavingMessage(WeaveMessage.WEAVEMESSAGE_ITD, + new String[]{weaver.getLazyClassGen().getType().getName(), + tName,munger.getKind().toString().toLowerCase(), + getAspectType().getName(), + fName+":'"+munger.getSignature()+"'"})); + // ??? If only type mungers knew their originating line numbers ... + } + } return changed; } diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java b/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java index 19beb0f62..653510ddd 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java @@ -48,11 +48,13 @@ import org.aspectj.bridge.IProgressListener; import org.aspectj.bridge.Message; import org.aspectj.bridge.SourceLocation; import org.aspectj.util.FileUtil; +import org.aspectj.util.FuzzyBoolean; import org.aspectj.weaver.ConcreteTypeMunger; import org.aspectj.weaver.CrosscuttingMembersSet; import org.aspectj.weaver.IClassFileProvider; import org.aspectj.weaver.IWeaveRequestor; import org.aspectj.weaver.IWeaver; +import org.aspectj.weaver.WeaverMetrics; import org.aspectj.weaver.NewParentTypeMunger; import org.aspectj.weaver.ResolvedTypeMunger; import org.aspectj.weaver.ResolvedTypeX; @@ -75,6 +77,7 @@ public class BcelWeaver implements IWeaver { public BcelWeaver(BcelWorld world) { super(); + WeaverMetrics.reset(); this.world = world; this.xcutSet = world.getCrosscuttingMembersSet(); } @@ -815,7 +818,9 @@ public class BcelWeaver implements IWeaver { Iterator iter = list.iterator(); while (iter.hasNext()) { ShadowMunger munger = (ShadowMunger)iter.next(); - if (munger.getPointcut().fastMatch(info).maybeTrue()) { + FuzzyBoolean fb = munger.getPointcut().fastMatch(info); + WeaverMetrics.recordFastMatchTypeResult(fb); // Could pass: munger.getPointcut().toString(),info + if (fb.maybeTrue()) { result.add(munger); } } diff --git a/weaver/src/org/aspectj/weaver/patterns/FastMatchInfo.java b/weaver/src/org/aspectj/weaver/patterns/FastMatchInfo.java index c2b6121d0..8d5434f27 100644 --- a/weaver/src/org/aspectj/weaver/patterns/FastMatchInfo.java +++ b/weaver/src/org/aspectj/weaver/patterns/FastMatchInfo.java @@ -39,5 +39,9 @@ public class FastMatchInfo { public ResolvedTypeX getType() { return type; } + + public String toString() { + return "FastMatchInfo [type="+type.getName()+"] ["+(kind==null?"AllKinds":"Kind="+kind)+"]"; + } } |