From 0dbc68a5cc2df113c22a72c78c39dedd1e1cb714 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Fri, 10 Aug 2012 18:30:35 +0200 Subject: Added an optimization to javac: Don't force new resolution rounds if none of the handlers in the next priority level need it. --- src/core/lombok/javac/apt/Processor.java | 68 +++++++++++++++++++------------- 1 file changed, 41 insertions(+), 27 deletions(-) (limited to 'src/core/lombok/javac/apt') diff --git a/src/core/lombok/javac/apt/Processor.java b/src/core/lombok/javac/apt/Processor.java index 190a369b..94e0e644 100644 --- a/src/core/lombok/javac/apt/Processor.java +++ b/src/core/lombok/javac/apt/Processor.java @@ -29,6 +29,7 @@ import java.lang.reflect.Method; import java.net.URL; import java.util.ArrayList; import java.util.Enumeration; +import java.util.HashSet; import java.util.IdentityHashMap; import java.util.List; import java.util.Map; @@ -85,10 +86,12 @@ public class Processor extends AbstractProcessor { SortedSet p = transformer.getPriorities(); if (p.isEmpty()) { this.priorityLevels = new long[] {0L}; + this.priorityLevelsRequiringResolutionReset = new HashSet(); } else { this.priorityLevels = new long[p.size()]; int i = 0; for (Long prio : p) this.priorityLevels[i++] = prio; + this.priorityLevelsRequiringResolutionReset = transformer.getPrioritiesRequiringResolutionReset(); } } @@ -216,6 +219,7 @@ public class Processor extends AbstractProcessor { private final IdentityHashMap roots = new IdentityHashMap(); private long[] priorityLevels; + private Set priorityLevelsRequiringResolutionReset; /** {@inheritDoc} */ @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { @@ -232,37 +236,47 @@ public class Processor extends AbstractProcessor { roots.put(unit, priorityLevels[0]); } - // Step 2: For all CUs (in the map, not the roundEnv!), run them across all handlers at their current prio level. - - for (long prio : priorityLevels) { - List cusForThisRound = new ArrayList(); - for (Map.Entry entry : roots.entrySet()) { - Long prioOfCu = entry.getValue(); - if (prioOfCu == null || prioOfCu != prio) continue; - cusForThisRound.add(entry.getKey()); + while (true) { + // Step 2: For all CUs (in the map, not the roundEnv!), run them across all handlers at their current prio level. + + for (long prio : priorityLevels) { + List cusForThisRound = new ArrayList(); + for (Map.Entry entry : roots.entrySet()) { + Long prioOfCu = entry.getValue(); + if (prioOfCu == null || prioOfCu != prio) continue; + cusForThisRound.add(entry.getKey()); + } + transformer.transform(prio, processingEnv.getContext(), cusForThisRound); } - transformer.transform(prio, processingEnv.getContext(), cusForThisRound); - } - - // Step 3: Push up all CUs to the next level. Set level to null if there is no next level. - - boolean nextRoundNeeded = false; - for (int i = priorityLevels.length - 1; i >= 0; i--) { - Long curLevel = priorityLevels[i]; - Long nextLevel = (i == priorityLevels.length - 1) ? null : priorityLevels[i + 1]; - for (Map.Entry entry : roots.entrySet()) { - if (curLevel.equals(entry.getValue())) { - entry.setValue(nextLevel); - if (nextLevel != null) nextRoundNeeded = true; + + // Step 3: Push up all CUs to the next level. Set level to null if there is no next level. + + Set newLevels = new HashSet(); + for (int i = priorityLevels.length - 1; i >= 0; i--) { + Long curLevel = priorityLevels[i]; + Long nextLevel = (i == priorityLevels.length - 1) ? null : priorityLevels[i + 1]; + for (Map.Entry entry : roots.entrySet()) { + if (curLevel.equals(entry.getValue())) { + entry.setValue(nextLevel); + newLevels.add(nextLevel); + } } } + newLevels.remove(null); + + // Step 4: If ALL values are null, quit. Else, either do another loop right now or force a resolution reset by forcing a new round in the annotation processor. + + if (newLevels.isEmpty()) return false; + newLevels.retainAll(priorityLevelsRequiringResolutionReset); + if (newLevels.isEmpty()) { + // None of the new levels need resolution, so just keep going. + continue; + } else { + // Force a new round to reset resolution. The next round will cause this method (process) to be called again. + forceNewRound((JavacFiler) processingEnv.getFiler()); + return false; + } } - - // Step 4: If ALL values are null, quit. Else, force new round. - - if (nextRoundNeeded) forceNewRound((JavacFiler) processingEnv.getFiler()); - - return false; } private int dummyCount = 0; -- cgit