diff --git a/core/src/main/java/org/teavm/dependency/DependencyChecker.java b/core/src/main/java/org/teavm/dependency/DependencyChecker.java index 38585fa2b..45e980e8c 100644 --- a/core/src/main/java/org/teavm/dependency/DependencyChecker.java +++ b/core/src/main/java/org/teavm/dependency/DependencyChecker.java @@ -68,6 +68,7 @@ public class DependencyChecker implements DependencyInfo { private List listeners = new ArrayList<>(); private ServiceRepository services; private Queue tasks = new ArrayDeque<>(); + private Queue deferredTasks = new ArrayDeque<>(); List types = new ArrayList<>(); private Map typeMap = new HashMap<>(); private DependencyCheckerInterruptor interruptor; @@ -199,7 +200,7 @@ public class DependencyChecker implements DependencyInfo { dep.used = false; lock(dep, false); - tasks.add(() -> { + deferredTasks.add(() -> { DependencyGraphBuilder graphBuilder = new DependencyGraphBuilder(DependencyChecker.this); graphBuilder.buildGraph(dep); dep.used = true; @@ -277,7 +278,7 @@ public class DependencyChecker implements DependencyInfo { added = classesAddedByRoot.add(className); } if (!dep.isMissing() && added) { - tasks.add(() -> { + deferredTasks.add(() -> { for (DependencyListener listener : listeners) { listener.classReached(agent, className, callLocation); } @@ -352,7 +353,7 @@ public class DependencyChecker implements DependencyInfo { ClassReader reader = cls.getClassReader(); MethodReader method = reader.getMethod(new MethodDescriptor("", void.class)); if (method != null) { - tasks.add(() -> linkMethod(method.getReference(), callLocation).use()); + deferredTasks.add(() -> linkMethod(method.getReference(), callLocation).use()); } } @@ -385,7 +386,7 @@ public class DependencyChecker implements DependencyInfo { MethodDependency dep = new MethodDependency(this, parameterNodes, paramCount, resultNode, thrown, method, methodRef); if (method != null) { - tasks.add(() -> { + deferredTasks.add(() -> { CallLocation caller = new CallLocation(dep.getMethod().getReference()); linkClass(dep.getMethod().getOwnerName(), caller).initClass(caller); }); @@ -394,7 +395,7 @@ public class DependencyChecker implements DependencyInfo { } void scheduleMethodAnalysis(MethodDependency dep) { - tasks.add(() -> { + deferredTasks.add(() -> { DependencyGraphBuilder graphBuilder = new DependencyGraphBuilder(DependencyChecker.this); graphBuilder.buildGraph(dep); }); @@ -429,7 +430,7 @@ public class DependencyChecker implements DependencyInfo { } FieldDependency dep = fieldCache.map(fieldRef); if (!dep.isMissing()) { - tasks.add(() -> linkClass(fieldRef.getClassName(), location).initClass(location)); + deferredTasks.add(() -> linkClass(fieldRef.getClassName(), location).initClass(location)); } if (!dep.isMissing() && added) { for (DependencyListener listener : listeners) { @@ -508,15 +509,21 @@ public class DependencyChecker implements DependencyInfo { return; } int index = 0; - while (!tasks.isEmpty()) { - tasks.poll().run(); - if (++index == 100) { - if (interruptor != null && !interruptor.shouldContinue()) { - interrupted = true; - break; + while (true) { + while (!tasks.isEmpty()) { + tasks.poll().run(); + if (++index == 100) { + if (interruptor != null && !interruptor.shouldContinue()) { + interrupted = true; + break; + } + index = 0; } - index = 0; } + if (deferredTasks.isEmpty()) { + break; + } + deferredTasks.poll().run(); } } diff --git a/core/src/main/java/org/teavm/dependency/DependencyNode.java b/core/src/main/java/org/teavm/dependency/DependencyNode.java index 48c7e074a..480153ad4 100644 --- a/core/src/main/java/org/teavm/dependency/DependencyNode.java +++ b/core/src/main/java/org/teavm/dependency/DependencyNode.java @@ -153,19 +153,7 @@ public class DependencyNode implements ValueDependencyInfo { } followers.add(consumer); - if (this.types != null) { - List types = new ArrayList<>(); - for (int index = this.types.nextSetBit(0); index >= 0; index = this.types.nextSetBit(index + 1)) { - types.add(dependencyChecker.types.get(index)); - } - dependencyChecker.schedulePropagation(consumer, types.toArray(new DependencyType[types.size()])); - } else if (this.smallTypes != null) { - DependencyType[] types = new DependencyType[smallTypes.length]; - for (int i = 0; i < types.length; ++i) { - types[i] = dependencyChecker.types.get(smallTypes[i]); - } - dependencyChecker.schedulePropagation(consumer, types); - } + propagateTypes(consumer, null); } public void connect(DependencyNode node, DependencyTypeFilter filter) { @@ -192,16 +180,30 @@ public class DependencyNode implements ValueDependencyInfo { System.out.println("Connecting " + tag + " to " + node.tag); } + propagateTypes(transition, filter); + } + + private void propagateTypes(DependencyConsumer transition, DependencyTypeFilter filter) { if (this.types != null) { List types = new ArrayList<>(); for (int index = this.types.nextSetBit(0); index >= 0; index = this.types.nextSetBit(index + 1)) { - types.add(dependencyChecker.types.get(index)); + DependencyType type = dependencyChecker.types.get(index); + if (filter == null || filter.match(type)) { + types.add(type); + } } dependencyChecker.schedulePropagation(transition, types.toArray(new DependencyType[types.size()])); } else if (this.smallTypes != null) { DependencyType[] types = new DependencyType[smallTypes.length]; + int j = 0; for (int i = 0; i < types.length; ++i) { - types[i] = dependencyChecker.types.get(smallTypes[i]); + DependencyType type = dependencyChecker.types.get(smallTypes[i]); + if (filter == null || filter.match(type)) { + types[j++] = type; + } + } + if (j < types.length) { + types = Arrays.copyOf(types, j); } dependencyChecker.schedulePropagation(transition, types); }