Fixes issues with dependency checking

This commit is contained in:
konsoletyper 2014-01-08 17:48:54 +04:00
parent d844d1cc1d
commit 93e2f5d284
2 changed files with 32 additions and 7 deletions

View File

@ -18,6 +18,7 @@ package org.teavm.dependency;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import org.teavm.common.ConcurrentCachedMapper; import org.teavm.common.ConcurrentCachedMapper;
import org.teavm.common.Mapper; import org.teavm.common.Mapper;
@ -40,6 +41,8 @@ public class DependencyChecker {
private ConcurrentMap<String, Object> achievableClasses = new ConcurrentHashMap<>(); private ConcurrentMap<String, Object> achievableClasses = new ConcurrentHashMap<>();
private ConcurrentMap<String, Object> initializedClasses = new ConcurrentHashMap<>(); private ConcurrentMap<String, Object> initializedClasses = new ConcurrentHashMap<>();
private AtomicReference<RuntimeException> exceptionOccured = new AtomicReference<>(); private AtomicReference<RuntimeException> exceptionOccured = new AtomicReference<>();
private AtomicInteger activeTaskCount = new AtomicInteger(0);
private final Object activeTaskMonitor = new Object();
public DependencyChecker(ClassHolderSource classSource, ClassLoader classLoader) { public DependencyChecker(ClassHolderSource classSource, ClassLoader classLoader) {
this(classSource, classLoader, Runtime.getRuntime().availableProcessors()); this(classSource, classLoader, Runtime.getRuntime().availableProcessors());
@ -103,15 +106,22 @@ public class DependencyChecker {
} }
void schedule(final Runnable runnable) { void schedule(final Runnable runnable) {
activeTaskCount.incrementAndGet();
try { try {
executor.execute(new Runnable() { executor.execute(new Runnable() {
@Override public void run() { @Override public void run() {
try { try {
runnable.run(); runnable.run();
} catch (RuntimeException e) { } catch (RuntimeException e) {
activeTaskMonitor.notifyAll();
exceptionOccured.compareAndSet(null, e); exceptionOccured.compareAndSet(null, e);
executor.shutdownNow(); executor.shutdownNow();
} }
if (activeTaskCount.decrementAndGet() == 0) {
synchronized (activeTaskMonitor) {
activeTaskMonitor.notifyAll();
}
}
} }
}); });
} catch (RejectedExecutionException e) { } catch (RejectedExecutionException e) {
@ -120,12 +130,14 @@ public class DependencyChecker {
} }
public void checkDependencies() { public void checkDependencies() {
exceptionOccured.set(null);
while (true) { while (true) {
try { if (activeTaskCount.get() == 0 || exceptionOccured.get() != null) {
if (executor.getActiveCount() == 0 || executor.awaitTermination(2, TimeUnit.MILLISECONDS)) {
break; break;
} }
try {
synchronized (activeTaskMonitor) {
activeTaskMonitor.wait();
}
} catch (InterruptedException e) { } catch (InterruptedException e) {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
break; break;
@ -138,8 +150,8 @@ public class DependencyChecker {
executor.shutdown(); executor.shutdown();
} }
void achieveClass(String className) { boolean achieveClass(String className) {
achievableClasses.put(className, dummyValue); return achievableClasses.putIfAbsent(className, dummyValue) == null;
} }
public MethodGraph attachMethodGraph(MethodReference methodRef) { public MethodGraph attachMethodGraph(MethodReference methodRef) {
@ -152,6 +164,8 @@ public class DependencyChecker {
if (initializedClasses.putIfAbsent(className, clinitDesc) != null) { if (initializedClasses.putIfAbsent(className, clinitDesc) != null) {
break; break;
} }
achieveClass(className);
achieveInterfaces(className);
ClassHolder cls = classSource.getClassHolder(className); ClassHolder cls = classSource.getClassHolder(className);
if (cls == null) { if (cls == null) {
throw new RuntimeException("Class not found: " + className); throw new RuntimeException("Class not found: " + className);
@ -163,6 +177,18 @@ public class DependencyChecker {
} }
} }
private void achieveInterfaces(String className) {
ClassHolder cls = classSource.getClassHolder(className);
if (cls == null) {
throw new RuntimeException("Class not found: " + className);
}
for (String iface : cls.getInterfaces()) {
if (achieveClass(iface)) {
achieveInterfaces(iface);
}
}
}
private MethodGraph createMethodGraph(final MethodReference methodRef) { private MethodGraph createMethodGraph(final MethodReference methodRef) {
initClass(methodRef.getClassName()); initClass(methodRef.getClassName());
ClassHolder cls = classSource.getClassHolder(methodRef.getClassName()); ClassHolder cls = classSource.getClassHolder(methodRef.getClassName());
@ -202,7 +228,6 @@ public class DependencyChecker {
@Override public void run() { @Override public void run() {
DependencyGraphBuilder graphBuilder = new DependencyGraphBuilder(DependencyChecker.this); DependencyGraphBuilder graphBuilder = new DependencyGraphBuilder(DependencyChecker.this);
graphBuilder.buildGraph(currentMethod, graph); graphBuilder.buildGraph(currentMethod, graph);
achieveClass(methodRef.getClassName());
} }
}); });
return graph; return graph;

View File

@ -69,7 +69,6 @@ public class JavascriptBuilder {
} }
public void build(Appendable writer) throws RenderingException { public void build(Appendable writer) throws RenderingException {
Decompiler decompiler = new Decompiler(classSource, classLoader);
AliasProvider aliasProvider = minifying ? new MinifyingAliasProvider() : new DefaultAliasProvider(); AliasProvider aliasProvider = minifying ? new MinifyingAliasProvider() : new DefaultAliasProvider();
DefaultNamingStrategy naming = new DefaultNamingStrategy(aliasProvider, classSource); DefaultNamingStrategy naming = new DefaultNamingStrategy(aliasProvider, classSource);
naming.setMinifying(minifying); naming.setMinifying(minifying);
@ -83,6 +82,7 @@ public class JavascriptBuilder {
ValueType.arrayOf(ValueType.CHARACTER), ValueType.VOID))); ValueType.arrayOf(ValueType.CHARACTER), ValueType.VOID)));
dependencyChecker.checkDependencies(); dependencyChecker.checkDependencies();
ListableClassHolderSource classSet = dependencyChecker.cutUnachievableClasses(); ListableClassHolderSource classSet = dependencyChecker.cutUnachievableClasses();
Decompiler decompiler = new Decompiler(classSet, classLoader);
ClassSetOptimizer optimizer = new ClassSetOptimizer(); ClassSetOptimizer optimizer = new ClassSetOptimizer();
optimizer.optimizeAll(classSet); optimizer.optimizeAll(classSet);
renderer.renderRuntime(); renderer.renderRuntime();