mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Adds class preordering. Fixes concurrency issues
This commit is contained in:
parent
cf6c9b1ba6
commit
04e12562a0
|
@ -2,10 +2,7 @@ package org.teavm.classlibgen;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.teavm.codegen.DefaultAliasProvider;
|
import org.teavm.codegen.DefaultAliasProvider;
|
||||||
import org.teavm.codegen.DefaultNamingStrategy;
|
import org.teavm.codegen.DefaultNamingStrategy;
|
||||||
|
@ -51,9 +48,7 @@ public class ClasslibTestGenerator {
|
||||||
}
|
}
|
||||||
dependencyChecker.checkDependencies();
|
dependencyChecker.checkDependencies();
|
||||||
dependencyChecker.cutUnachievableClasses();
|
dependencyChecker.cutUnachievableClasses();
|
||||||
for (String className : dependencyChecker.getAchievableClasses()) {
|
decompileClasses(dependencyChecker.getAchievableClasses());
|
||||||
decompileClass(className);
|
|
||||||
}
|
|
||||||
renderHead();
|
renderHead();
|
||||||
ClassLoader classLoader = ClasslibTestGenerator.class.getClassLoader();
|
ClassLoader classLoader = ClasslibTestGenerator.class.getClassLoader();
|
||||||
try (InputStream input = classLoader.getResourceAsStream("org/teavm/classlib/junit-support.js")) {
|
try (InputStream input = classLoader.getResourceAsStream("org/teavm/classlib/junit-support.js")) {
|
||||||
|
@ -69,11 +64,12 @@ public class ClasslibTestGenerator {
|
||||||
renderFoot();
|
renderFoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void decompileClass(String className) {
|
private static void decompileClasses(Collection<String> classNames) {
|
||||||
ClassHolder cls = classSource.getClassHolder(className);
|
List<ClassNode> clsNodes = decompiler.decompile(classNames);
|
||||||
ClassNode clsNode = decompiler.decompile(cls);
|
for (ClassNode clsNode : clsNodes) {
|
||||||
renderer.render(clsNode);
|
renderer.render(clsNode);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void renderHead() {
|
private static void renderHead() {
|
||||||
System.out.println("<!DOCTYPE html>");
|
System.out.println("<!DOCTYPE html>");
|
||||||
|
|
|
@ -41,6 +41,7 @@ public class ConcurrentCachedMapper<T, R> implements Mapper<T, R> {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
CountDownLatch latch = oldWrapper.latch;
|
CountDownLatch latch = oldWrapper.latch;
|
||||||
|
wrapper = oldWrapper;
|
||||||
try {
|
try {
|
||||||
latch.await();
|
latch.await();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
|
|
|
@ -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.AtomicReference;
|
||||||
import org.teavm.codegen.ConcurrentCachedMapper;
|
import org.teavm.codegen.ConcurrentCachedMapper;
|
||||||
import org.teavm.codegen.ConcurrentCachedMapper.KeyListener;
|
import org.teavm.codegen.ConcurrentCachedMapper.KeyListener;
|
||||||
import org.teavm.codegen.Mapper;
|
import org.teavm.codegen.Mapper;
|
||||||
|
@ -36,7 +37,7 @@ public class DependencyChecker {
|
||||||
private ConcurrentCachedMapper<FieldReference, DependencyNode> fieldCache;
|
private ConcurrentCachedMapper<FieldReference, DependencyNode> fieldCache;
|
||||||
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 volatile RuntimeException exceptionOccured;
|
private AtomicReference<RuntimeException> exceptionOccured = new AtomicReference<>();
|
||||||
|
|
||||||
public DependencyChecker(ClassHolderSource classSource) {
|
public DependencyChecker(ClassHolderSource classSource) {
|
||||||
this(classSource, Runtime.getRuntime().availableProcessors());
|
this(classSource, Runtime.getRuntime().availableProcessors());
|
||||||
|
@ -99,21 +100,24 @@ public class DependencyChecker {
|
||||||
}
|
}
|
||||||
|
|
||||||
void schedule(final Runnable runnable) {
|
void schedule(final Runnable runnable) {
|
||||||
|
try {
|
||||||
executor.execute(new Runnable() {
|
executor.execute(new Runnable() {
|
||||||
@Override
|
@Override public void run() {
|
||||||
public void run() {
|
|
||||||
try {
|
try {
|
||||||
runnable.run();
|
runnable.run();
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
exceptionOccured = e;
|
exceptionOccured.compareAndSet(null, e);
|
||||||
executor.shutdownNow();
|
executor.shutdownNow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} catch (RejectedExecutionException e) {
|
||||||
|
throw exceptionOccured.get();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkDependencies() {
|
public void checkDependencies() {
|
||||||
exceptionOccured = null;
|
exceptionOccured.set(null);
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
if (executor.getActiveCount() == 0 || executor.awaitTermination(1, TimeUnit.SECONDS)) {
|
if (executor.getActiveCount() == 0 || executor.awaitTermination(1, TimeUnit.SECONDS)) {
|
||||||
|
@ -124,8 +128,9 @@ public class DependencyChecker {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (exceptionOccured != null) {
|
RuntimeException e = exceptionOccured.get();
|
||||||
throw exceptionOccured;
|
if (e != null) {
|
||||||
|
throw exceptionOccured.get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,6 +149,9 @@ public class DependencyChecker {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ClassHolder cls = classSource.getClassHolder(className);
|
ClassHolder cls = classSource.getClassHolder(className);
|
||||||
|
if (cls == null) {
|
||||||
|
throw new RuntimeException("Class not found: " + className);
|
||||||
|
}
|
||||||
if (cls.getMethod(clinitDesc) != null) {
|
if (cls.getMethod(clinitDesc) != null) {
|
||||||
attachMethodGraph(new MethodReference(className, clinitDesc));
|
attachMethodGraph(new MethodReference(className, clinitDesc));
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,6 +81,9 @@ class DependencyGraphBuilder {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
MethodGraph targetGraph = checker.attachMethodGraph(methodRef);
|
MethodGraph targetGraph = checker.attachMethodGraph(methodRef);
|
||||||
|
if (targetGraph == null) {
|
||||||
|
throw new RuntimeException("Method not found: " + methodRef);
|
||||||
|
}
|
||||||
DependencyNode[] targetParams = targetGraph.getVariableNodes();
|
DependencyNode[] targetParams = targetGraph.getVariableNodes();
|
||||||
for (int i = 0; i < parameters.length; ++i) {
|
for (int i = 0; i < parameters.length; ++i) {
|
||||||
parameters[i].connect(targetParams[i]);
|
parameters[i].connect(targetParams[i]);
|
||||||
|
|
|
@ -62,6 +62,36 @@ public class Decompiler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<ClassNode> decompile(Collection<String> classNames) {
|
||||||
|
List<String> sequence = new ArrayList<>();
|
||||||
|
Set<String> visited = new HashSet<>();
|
||||||
|
for (String className : classNames) {
|
||||||
|
orderClasses(className, visited, sequence);
|
||||||
|
}
|
||||||
|
List<ClassNode> result = new ArrayList<>();
|
||||||
|
for (String className : sequence) {
|
||||||
|
result.add(decompile(classSource.getClassHolder(className)));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void orderClasses(String className, Set<String> visited, List<String> order) {
|
||||||
|
if (!visited.add(className)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ClassHolder cls = classSource.getClassHolder(className);
|
||||||
|
if (cls == null) {
|
||||||
|
throw new IllegalArgumentException("Class not found: " + className);
|
||||||
|
}
|
||||||
|
if (cls.getParent() != null) {
|
||||||
|
orderClasses(cls.getParent(), visited, order);
|
||||||
|
}
|
||||||
|
for (String iface : cls.getInterfaces()) {
|
||||||
|
orderClasses(iface, visited, order);
|
||||||
|
}
|
||||||
|
order.add(className);
|
||||||
|
}
|
||||||
|
|
||||||
public ClassNode decompile(ClassHolder cls) {
|
public ClassNode decompile(ClassHolder cls) {
|
||||||
ClassNode clsNode = new ClassNode(cls.getName(), cls.getParent());
|
ClassNode clsNode = new ClassNode(cls.getName(), cls.getParent());
|
||||||
for (FieldHolder field : cls.getFields()) {
|
for (FieldHolder field : cls.getFields()) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user