mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
253b882d3e
|
@ -15,10 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.dependency;
|
package org.teavm.dependency;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import org.teavm.common.*;
|
import org.teavm.common.*;
|
||||||
|
@ -41,6 +38,9 @@ public class DependencyChecker implements DependencyInformation {
|
||||||
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 List<DependencyListener> listeners = new ArrayList<>();
|
private List<DependencyListener> listeners = new ArrayList<>();
|
||||||
|
Set<MethodReference> missingMethods = new HashSet<>();
|
||||||
|
Set<String> missingClasses = new HashSet<>();
|
||||||
|
Set<FieldReference> missingFields = new HashSet<>();
|
||||||
|
|
||||||
public DependencyChecker(ClassHolderSource classSource, ClassLoader classLoader) {
|
public DependencyChecker(ClassHolderSource classSource, ClassLoader classLoader) {
|
||||||
this(classSource, classLoader, new SimpleFiniteExecutor());
|
this(classSource, classLoader, new SimpleFiniteExecutor());
|
||||||
|
@ -144,7 +144,8 @@ public class DependencyChecker implements DependencyInformation {
|
||||||
achieveInterfaces(className);
|
achieveInterfaces(className);
|
||||||
ClassHolder cls = classSource.get(className);
|
ClassHolder cls = classSource.get(className);
|
||||||
if (cls == null) {
|
if (cls == null) {
|
||||||
throw new RuntimeException("Class not found: " + className);
|
missingClasses.add(className);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (cls.getMethod(clinitDesc) != null) {
|
if (cls.getMethod(clinitDesc) != null) {
|
||||||
attachMethodGraph(new MethodReference(className, clinitDesc));
|
attachMethodGraph(new MethodReference(className, clinitDesc));
|
||||||
|
@ -156,7 +157,8 @@ public class DependencyChecker implements DependencyInformation {
|
||||||
private void achieveInterfaces(String className) {
|
private void achieveInterfaces(String className) {
|
||||||
ClassHolder cls = classSource.get(className);
|
ClassHolder cls = classSource.get(className);
|
||||||
if (cls == null) {
|
if (cls == null) {
|
||||||
throw new RuntimeException("Class not found: " + className);
|
missingClasses.add(className);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
for (String iface : cls.getInterfaces()) {
|
for (String iface : cls.getInterfaces()) {
|
||||||
if (achieveClass(iface)) {
|
if (achieveClass(iface)) {
|
||||||
|
@ -168,7 +170,12 @@ public class DependencyChecker implements DependencyInformation {
|
||||||
private MethodGraph createMethodGraph(final MethodReference methodRef) {
|
private MethodGraph createMethodGraph(final MethodReference methodRef) {
|
||||||
initClass(methodRef.getClassName());
|
initClass(methodRef.getClassName());
|
||||||
ClassHolder cls = classSource.get(methodRef.getClassName());
|
ClassHolder cls = classSource.get(methodRef.getClassName());
|
||||||
MethodHolder method = cls.getMethod(methodRef.getDescriptor());
|
MethodHolder method;
|
||||||
|
if (cls == null) {
|
||||||
|
missingClasses.add(methodRef.getClassName());
|
||||||
|
method = null;
|
||||||
|
} else {
|
||||||
|
method = cls.getMethod(methodRef.getDescriptor());
|
||||||
if (method == null) {
|
if (method == null) {
|
||||||
while (cls != null) {
|
while (cls != null) {
|
||||||
method = cls.getMethod(methodRef.getDescriptor());
|
method = cls.getMethod(methodRef.getDescriptor());
|
||||||
|
@ -177,28 +184,30 @@ public class DependencyChecker implements DependencyInformation {
|
||||||
}
|
}
|
||||||
cls = cls.getParent() != null ? classSource.get(cls.getParent()) : null;
|
cls = cls.getParent() != null ? classSource.get(cls.getParent()) : null;
|
||||||
}
|
}
|
||||||
throw new RuntimeException("Method not found: " + methodRef);
|
missingMethods.add(methodRef);
|
||||||
}
|
}
|
||||||
ValueType[] arguments = method.getParameterTypes();
|
}
|
||||||
|
ValueType[] arguments = methodRef.getParameterTypes();
|
||||||
int paramCount = arguments.length + 1;
|
int paramCount = arguments.length + 1;
|
||||||
int varCount = Math.max(paramCount, method.getProgram().variableCount());
|
int varCount = Math.max(paramCount, method != null ? method.getProgram().variableCount() : 0);
|
||||||
DependencyNode[] parameterNodes = new DependencyNode[varCount];
|
DependencyNode[] parameterNodes = new DependencyNode[varCount];
|
||||||
for (int i = 0; i < varCount; ++i) {
|
for (int i = 0; i < varCount; ++i) {
|
||||||
parameterNodes[i] = new DependencyNode(this);
|
parameterNodes[i] = new DependencyNode(this);
|
||||||
if (shouldLog) {
|
if (shouldLog) {
|
||||||
parameterNodes[i].setTag(method.getOwnerName() + "#" + method.getDescriptor() + ":" + i);
|
parameterNodes[i].setTag(methodRef + ":" + i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DependencyNode resultNode;
|
DependencyNode resultNode;
|
||||||
if (method.getResultType() == ValueType.VOID) {
|
if (methodRef.getDescriptor().getResultType() == ValueType.VOID) {
|
||||||
resultNode = null;
|
resultNode = null;
|
||||||
} else {
|
} else {
|
||||||
resultNode = new DependencyNode(this);
|
resultNode = new DependencyNode(this);
|
||||||
if (shouldLog) {
|
if (shouldLog) {
|
||||||
resultNode.setTag(method.getOwnerName() + "#" + method.getDescriptor() + ":RESULT");
|
resultNode.setTag(methodRef + ":RESULT");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final MethodGraph graph = new MethodGraph(parameterNodes, paramCount, resultNode);
|
final MethodGraph graph = new MethodGraph(parameterNodes, paramCount, resultNode);
|
||||||
|
if (method != null) {
|
||||||
final MethodHolder currentMethod = method;
|
final MethodHolder currentMethod = method;
|
||||||
executor.execute(new Runnable() {
|
executor.execute(new Runnable() {
|
||||||
@Override public void run() {
|
@Override public void run() {
|
||||||
|
@ -206,6 +215,7 @@ public class DependencyChecker implements DependencyInformation {
|
||||||
graphBuilder.buildGraph(currentMethod, graph);
|
graphBuilder.buildGraph(currentMethod, graph);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
return graph;
|
return graph;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,8 +251,8 @@ public class DependencyChecker implements DependencyInformation {
|
||||||
initClass(fieldRef.getClassName());
|
initClass(fieldRef.getClassName());
|
||||||
ClassHolder cls = classSource.get(fieldRef.getClassName());
|
ClassHolder cls = classSource.get(fieldRef.getClassName());
|
||||||
if (cls == null) {
|
if (cls == null) {
|
||||||
throw new RuntimeException("Class not found: " + fieldRef.getClassName());
|
missingClasses.add(fieldRef.getClassName());
|
||||||
}
|
} else {
|
||||||
FieldHolder field = cls.getField(fieldRef.getFieldName());
|
FieldHolder field = cls.getField(fieldRef.getFieldName());
|
||||||
if (field == null) {
|
if (field == null) {
|
||||||
while (cls != null) {
|
while (cls != null) {
|
||||||
|
@ -252,7 +262,8 @@ public class DependencyChecker implements DependencyInformation {
|
||||||
}
|
}
|
||||||
cls = cls.getParent() != null ? classSource.get(cls.getParent()) : null;
|
cls = cls.getParent() != null ? classSource.get(cls.getParent()) : null;
|
||||||
}
|
}
|
||||||
throw new RuntimeException("Field not found: " + fieldRef);
|
missingFields.add(fieldRef);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
DependencyNode node = new DependencyNode(this);
|
DependencyNode node = new DependencyNode(this);
|
||||||
if (shouldLog) {
|
if (shouldLog) {
|
||||||
|
@ -263,6 +274,9 @@ public class DependencyChecker implements DependencyInformation {
|
||||||
|
|
||||||
private void activateDependencyPlugin(MethodReference methodRef) {
|
private void activateDependencyPlugin(MethodReference methodRef) {
|
||||||
ClassHolder cls = classSource.get(methodRef.getClassName());
|
ClassHolder cls = classSource.get(methodRef.getClassName());
|
||||||
|
if (cls == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
MethodHolder method = cls.getMethod(methodRef.getDescriptor());
|
MethodHolder method = cls.getMethod(methodRef.getDescriptor());
|
||||||
if (method == null) {
|
if (method == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -336,4 +350,30 @@ public class DependencyChecker implements DependencyInformation {
|
||||||
public DependencyMethodInformation getMethod(MethodReference methodRef) {
|
public DependencyMethodInformation getMethod(MethodReference methodRef) {
|
||||||
return methodCache.getKnown(methodRef);
|
return methodCache.getKnown(methodRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void checkForMissingItems() {
|
||||||
|
if (missingClasses.isEmpty() && missingMethods.isEmpty() && missingFields.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
if (!missingClasses.isEmpty()) {
|
||||||
|
sb.append("Missing classes:\n");
|
||||||
|
for (String cls : missingClasses) {
|
||||||
|
sb.append(" ").append(cls).append("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!missingMethods.isEmpty()) {
|
||||||
|
sb.append("Missing methods:\n");
|
||||||
|
for (MethodReference method : missingMethods) {
|
||||||
|
sb.append(" ").append(method).append("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!missingMethods.isEmpty()) {
|
||||||
|
sb.append("Missing fields:\n");
|
||||||
|
for (FieldReference field : missingFields) {
|
||||||
|
sb.append(" ").append(field).append("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalStateException(sb.toString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,9 +89,6 @@ 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.getVariables();
|
DependencyNode[] targetParams = targetGraph.getVariables();
|
||||||
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]);
|
||||||
|
|
|
@ -121,6 +121,7 @@ public class JavascriptBuilder implements JavascriptBuilderHost {
|
||||||
dependencyChecker.attachMethodGraph(new MethodReference("java.lang.String", new MethodDescriptor("<init>",
|
dependencyChecker.attachMethodGraph(new MethodReference("java.lang.String", new MethodDescriptor("<init>",
|
||||||
ValueType.arrayOf(ValueType.CHARACTER), ValueType.VOID)));
|
ValueType.arrayOf(ValueType.CHARACTER), ValueType.VOID)));
|
||||||
executor.complete();
|
executor.complete();
|
||||||
|
dependencyChecker.checkForMissingItems();
|
||||||
ListableClassHolderSource classSet = dependencyChecker.cutUnachievableClasses();
|
ListableClassHolderSource classSet = dependencyChecker.cutUnachievableClasses();
|
||||||
Decompiler decompiler = new Decompiler(classSet, classLoader, executor);
|
Decompiler decompiler = new Decompiler(classSet, classLoader, executor);
|
||||||
devirtualize(classSet, dependencyChecker);
|
devirtualize(classSet, dependencyChecker);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user