private final List<ConcreteTypeMunger> typeMungers;
private final List lateTypeMungers;
+ private List<ShadowMunger>[] indexedShadowMungers;
+ private boolean canMatchBodyShadows = false;
+
private final BcelObjectType ty; // alias of clazz.getType()
private final BcelWorld world; // alias of ty.getWorld()
private final ConstantPool cpg; // alias of clazz.getConstantPoolGen()
private BcelClassWeaver(BcelWorld world, LazyClassGen clazz, List<ShadowMunger> shadowMungers,
List<ConcreteTypeMunger> typeMungers, List lateTypeMungers) {
super();
- // assert world == clazz.getType().getWorld()
this.world = world;
this.clazz = clazz;
this.shadowMungers = shadowMungers;
this.cpg = clazz.getConstantPool();
this.fact = clazz.getFactory();
- fastMatchShadowMungers(shadowMungers);
+ indexShadowMungers();
initializeSuperInitializerMap(ty.getResolvedTypeX());
if (!checkedXsetForLowLevelContextCapturing) {
}
}
- private List<ShadowMunger>[] perKindShadowMungers;
- private boolean canMatchBodyShadows = false;
-
- // private boolean canMatchInitialization = false;
- private void fastMatchShadowMungers(List<ShadowMunger> shadowMungers) {
- // beware the annoying property that SHADOW_KINDS[i].getKey == (i+1) !
-
- perKindShadowMungers = new List[Shadow.MAX_SHADOW_KIND + 1];
- for (int i = 0; i < perKindShadowMungers.length; i++) {
- perKindShadowMungers[i] = new ArrayList<ShadowMunger>(0);
- }
- for (ShadowMunger munger : shadowMungers) {
- int couldMatchKinds = munger.getPointcut().couldMatchKinds();
- for (int i = 0; i < Shadow.SHADOW_KINDS.length; i++) {
- Shadow.Kind kind = Shadow.SHADOW_KINDS[i];
- if (kind.isSet(couldMatchKinds)) {
- perKindShadowMungers[kind.getKey()].add(munger);
- }
- }
-
- // Set couldMatchKinds = munger.getPointcut().couldMatchKinds();
- // for (Iterator kindIterator = couldMatchKinds.iterator();
- // kindIterator.hasNext();) {
- // Shadow.Kind aKind = (Shadow.Kind) kindIterator.next();
- // perKindShadowMungers[aKind.getKey()].add(munger);
- // }
- }
-
- // if (!perKindShadowMungers[Shadow.Initialization.getKey()].isEmpty())
- // canMatchInitialization = true;
-
- for (int i = 0; i < Shadow.SHADOW_KINDS.length; i++) {
- Shadow.Kind kind = Shadow.SHADOW_KINDS[i];
- if (!kind.isEnclosingKind() && !perKindShadowMungers[i + 1].isEmpty()) {
- canMatchBodyShadows = true;
- }
- if (perKindShadowMungers[i + 1].isEmpty()) {
- perKindShadowMungers[i + 1] = null;
- }
- }
- }
-
private boolean canMatch(Shadow.Kind kind) {
- return perKindShadowMungers[kind.getKey()] != null;
+ return indexedShadowMungers[kind.getKey()] != null;
}
// private void fastMatchShadowMungers(List shadowMungers, ArrayList
}
}
+ /**
+ * Process the shadow mungers into array 'buckets', each bucket represents a shadow kind and contains a list of shadowmungers
+ * that could potentially apply at that shadow kind.
+ */
+ private void indexShadowMungers() {
+ // beware the annoying property that SHADOW_KINDS[i].getKey == (i+1) !
+ indexedShadowMungers = new List[Shadow.MAX_SHADOW_KIND + 1];
+ for (ShadowMunger shadowMunger : shadowMungers) {
+ int couldMatchKinds = shadowMunger.getPointcut().couldMatchKinds();
+ for (Shadow.Kind kind : Shadow.SHADOW_KINDS) {
+ if (kind.isSet(couldMatchKinds)) {
+ byte k = kind.getKey();
+ if (indexedShadowMungers[k] == null) {
+ indexedShadowMungers[k] = new ArrayList<ShadowMunger>();
+ if (!kind.isEnclosingKind()) {
+ canMatchBodyShadows = true;
+ }
+ }
+ indexedShadowMungers[k].add(shadowMunger);
+ }
+ }
+ }
+ }
+
private boolean addSuperInitializer(ResolvedType onType) {
if (onType.isRawType() || onType.isParameterizedType()) {
onType = onType.getGenericType();
*
* @param donor the method from which we will copy (and adjust frame and jumps) instructions.
* @param recipient the method the instructions will go into. Used to get the frame size so we can allocate new frame locations
- * for locals in donor.
+ * for locals in donor.
* @param frameEnv an environment to map from donor frame to recipient frame, initially populated with argument locations.
* @param fact an instruction factory for recipient
*/
boolean isMatched = false;
Shadow.Kind shadowKind = shadow.getKind();
- List<ShadowMunger> candidateMungers = perKindShadowMungers[shadowKind.getKey()];
+ List<ShadowMunger> candidateMungers = indexedShadowMungers[shadowKind.getKey()];
// System.out.println("Candidates " + candidateMungers);
if (candidateMungers != null) {
boolean isMatched = false;
Shadow.Kind shadowKind = shadow.getKind();
- List<ShadowMunger> candidateMungers = perKindShadowMungers[shadowKind.getKey()];
+ List<ShadowMunger> candidateMungers = indexedShadowMungers[shadowKind.getKey()];
// System.out.println("Candidates at " + shadowKind + " are " + candidateMungers);
if (candidateMungers != null) {
return clazz;
}
- public List<ShadowMunger> getShadowMungers() {
- return shadowMungers;
- }
-
public BcelWorld getWorld() {
return world;
}
getWorld().getMessageHandler().handleMessage(new Message(messageText, IMessage.ABORT, re, null));
}
} else {
- checkDeclareTypeErrorOrWarning(world, classType);
+ checkDeclareTypeErrorOrWarning(world, classType);
}
// this is very odd return behavior trying to keep everyone happy
/*
zipOutputStream.closeEntry();
}
+ /**
+ * Perform a fast match of the specified list of shadowmungers against the specified type. A subset of those that might match is
+ * returned.
+ *
+ * @param list list of all shadow mungers that might match
+ * @param type the target type
+ * @return a list of shadow mungers that might match with those that cannot (according to fast match rules) removed
+ */
private List<ShadowMunger> fastMatch(List<ShadowMunger> list, ResolvedType type) {
if (list == null) {
return Collections.emptyList();
}
+ boolean isOverweaving = world.isOverWeaving();
+ WeaverStateInfo typeWeaverState = (isOverweaving ? type.getWeaverState() : null);
// here we do the coarsest grained fast match with no kind constraints
// this will remove all obvious non-matches and see if we need to do any
if (world.areInfoMessagesEnabled() && world.isTimingEnabled()) {
for (ShadowMunger munger : list) {
+ if (typeWeaverState != null) { // will only be null if overweaving is ON and there is weaverstate
+ ResolvedType declaringAspect = munger.getDeclaringType();
+ if (typeWeaverState.isAspectAlreadyApplied(declaringAspect)) {
+ continue;
+ }
+ }
Pointcut pointcut = munger.getPointcut();
long starttime = System.nanoTime();
FuzzyBoolean fb = pointcut.fastMatch(info);
}
} else {
for (ShadowMunger munger : list) {
+ if (typeWeaverState != null) { // will only be null if overweaving is ON and there is weaverstate
+ ResolvedType declaringAspect = munger.getDeclaringType();
+ if (typeWeaverState.isAspectAlreadyApplied(declaringAspect)) {
+ continue;
+ }
+ }
Pointcut pointcut = munger.getPointcut();
FuzzyBoolean fb = pointcut.fastMatch(info);
if (fb.maybeTrue()) {