mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Improves dependency checking. Adds some core runtime functions
This commit is contained in:
parent
c244c596c9
commit
e32da9316f
|
@ -53,6 +53,9 @@ public class DefaultNamingStrategy implements NamingStrategy {
|
|||
}
|
||||
ClassHolder clsHolder = classSource.getClassHolder(method.getClassName());
|
||||
MethodHolder methodHolder = clsHolder.getMethod(method.getDescriptor());
|
||||
if (methodHolder == null) {
|
||||
throw new RuntimeException("Method not found: " + method);
|
||||
}
|
||||
if (methodHolder.getModifiers().contains(ElementModifier.STATIC) ||
|
||||
method.getDescriptor().getName().equals("<init>") ||
|
||||
methodHolder.getLevel() == AccessLevel.PRIVATE) {
|
||||
|
|
|
@ -33,6 +33,7 @@ public class DependencyChecker {
|
|||
static final boolean shouldLog = System.getProperty("org.teavm.logDependencies", "false").equals("true");
|
||||
private ClassHolderSource classSource;
|
||||
private ScheduledThreadPoolExecutor executor;
|
||||
private ConcurrentMap<MethodReference, Object> abstractMethods = new ConcurrentHashMap<>();
|
||||
private ConcurrentCachedMapper<MethodReference, MethodGraph> methodCache;
|
||||
private ConcurrentCachedMapper<FieldReference, DependencyNode> fieldCache;
|
||||
private ConcurrentMap<String, Object> achievableClasses = new ConcurrentHashMap<>();
|
||||
|
@ -210,6 +211,10 @@ public class DependencyChecker {
|
|||
return methodCache.caches(methodRef);
|
||||
}
|
||||
|
||||
public boolean isAbstractMethodAchievable(MethodReference methodRef) {
|
||||
return abstractMethods.containsKey(methodRef);
|
||||
}
|
||||
|
||||
public Collection<MethodReference> getAchievableMethods() {
|
||||
return methodCache.getCachedPreimages();
|
||||
}
|
||||
|
@ -262,6 +267,24 @@ public class DependencyChecker {
|
|||
plugin.methodAchieved(this, methodRef);
|
||||
}
|
||||
|
||||
public void addAbstractMethod(MethodReference methodRef) {
|
||||
if (abstractMethods.putIfAbsent(methodRef, methodRef) == null) {
|
||||
String className = methodRef.getClassName();
|
||||
while (className != null) {
|
||||
ClassHolder cls = classSource.getClassHolder(className);
|
||||
if (cls == null) {
|
||||
return;
|
||||
}
|
||||
MethodHolder method = cls.getMethod(methodRef.getDescriptor());
|
||||
if (method != null) {
|
||||
abstractMethods.put(methodRef, methodRef);
|
||||
return;
|
||||
}
|
||||
className = cls.getParent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ListableClassHolderSource cutUnachievableClasses() {
|
||||
MutableClassHolderSource cutClasses = new MutableClassHolderSource();
|
||||
for (String className : achievableClasses.keySet()) {
|
||||
|
@ -269,7 +292,12 @@ public class DependencyChecker {
|
|||
for (MethodHolder method : classHolder.getMethods().toArray(new MethodHolder[0])) {
|
||||
MethodReference methodRef = new MethodReference(className, method.getDescriptor());
|
||||
if (!methodCache.getCachedPreimages().contains(methodRef)) {
|
||||
classHolder.removeMethod(method);
|
||||
if (abstractMethods.containsKey(methodRef)) {
|
||||
method.getModifiers().add(ElementModifier.ABSTRACT);
|
||||
method.setProgram(null);
|
||||
} else {
|
||||
classHolder.removeMethod(method);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (FieldHolder field : classHolder.getFields().toArray(new FieldHolder[0])) {
|
||||
|
|
|
@ -156,6 +156,7 @@ class DependencyGraphBuilder {
|
|||
DependencyConsumer listener = new VirtualCallPropagationListener(nodes[insn.getInstance().getIndex()],
|
||||
insn.getMethod().getDescriptor(), dependencyChecker, actualArgs,
|
||||
insn.getReceiver() != null ? nodes[insn.getReceiver().getIndex()] : null);
|
||||
dependencyChecker.addAbstractMethod(insn.getMethod());
|
||||
nodes[insn.getInstance().getIndex()].addConsumer(listener);
|
||||
}
|
||||
|
||||
|
@ -280,6 +281,8 @@ class DependencyGraphBuilder {
|
|||
@Override
|
||||
public void visit(StringConstantInstruction insn) {
|
||||
nodes[insn.getReceiver().getIndex()].propagate("java.lang.String");
|
||||
dependencyChecker.attachMethodGraph(new MethodReference("java.lang.String", new MethodDescriptor(
|
||||
"<init>", ValueType.arrayOf(ValueType.CHARACTER), ValueType.VOID)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -47,6 +47,7 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
|||
|
||||
public void renderRuntime() {
|
||||
renderRuntimeCls();
|
||||
renderRuntimeString();
|
||||
}
|
||||
|
||||
private void renderRuntimeCls() {
|
||||
|
@ -65,6 +66,20 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
|||
writer.outdent().append("}").newLine();
|
||||
}
|
||||
|
||||
private void renderRuntimeString() {
|
||||
String stringClass = "java.lang.String";
|
||||
MethodReference stringCons = new MethodReference(stringClass, new MethodDescriptor("<init>",
|
||||
ValueType.arrayOf(ValueType.CHARACTER), ValueType.VOID));
|
||||
writer.append("$rt_str = function(str) {").indent().newLine();
|
||||
writer.append("var characters = $rt_createNumericArray($rt_charcls(), str.length);").newLine();
|
||||
writer.append("for (var i = 0; i < str.length; i = (i + 1) | 0) {").indent().newLine();
|
||||
writer.append("characters[i] = str.charCodeAt(i);").newLine();
|
||||
writer.outdent().append("}").newLine();
|
||||
writer.append("return $rt_init(").appendClass("java.lang.String").append(", '")
|
||||
.appendMethod(stringCons).append("', characters);").newLine();
|
||||
writer.outdent().append("}").newLine();
|
||||
}
|
||||
|
||||
public void render(ClassNode cls) {
|
||||
writer.appendClass(cls.getName()).append(" = function() {").indent().newLine();
|
||||
for (FieldNode field : cls.getFields()) {
|
||||
|
|
|
@ -116,7 +116,7 @@ public abstract class ValueType {
|
|||
@Override
|
||||
public String toString() {
|
||||
if (reprCache == null) {
|
||||
reprCache = itemType.toString();
|
||||
reprCache = "[" + itemType.toString();
|
||||
}
|
||||
return reprCache;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,20 @@ $rt_createArray = function(cls, sz) {
|
|||
}
|
||||
return arr;
|
||||
}
|
||||
$rt_createNumericArray = function(cls, sz) {
|
||||
var arr = $rt_createArray(cls, sz);
|
||||
for (var i = 0; i < sz; i = (i + 1) | 0) {
|
||||
arr[i] = 0;
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
$rt_createLongArray = function(sz) {
|
||||
var arr = $rt.createArray($rt_longcls(), sz);
|
||||
for (var i = 0; i < sz; i = (i + 1) | 0) {
|
||||
arr[i] = Long.ZERO;
|
||||
}
|
||||
return arr;
|
||||
},
|
||||
$rt_arraycls = function(cls) {
|
||||
if (cls.$array == undefined) {
|
||||
cls.$array = {
|
||||
|
@ -40,6 +54,109 @@ $rt_arraycls = function(cls) {
|
|||
}
|
||||
return cls.$array;
|
||||
}
|
||||
$rt_createcls = function() {
|
||||
return {
|
||||
$meta : {
|
||||
supertypes : []
|
||||
}
|
||||
};
|
||||
}
|
||||
$rt_booleanclsCache = null;
|
||||
$rt_booleancls = function() {
|
||||
if ($rt_booleanclsCache == null) {
|
||||
$rt_booleanclsCache = $rt_createcls();
|
||||
}
|
||||
return $rt_booleanclsCache;
|
||||
}
|
||||
$rt_booleanclsCache = null;
|
||||
$rt_booleancls = function() {
|
||||
if ($rt_booleanclsCache == null) {
|
||||
$rt_booleanclsCache = $rt_createcls();
|
||||
}
|
||||
return $rt_booleanclsCache;
|
||||
}
|
||||
$rt_charclsCache = null;
|
||||
$rt_charcls = function() {
|
||||
if ($rt_charclsCache == null) {
|
||||
$rt_charclsCache = $rt_createcls();
|
||||
}
|
||||
return $rt_charclsCache;
|
||||
}
|
||||
$rt_byteclsCache = null;
|
||||
$rt_bytecls = function() {
|
||||
if ($rt_byteclsCache == null) {
|
||||
$rt_byteclsCache = $rt_createcls();
|
||||
}
|
||||
return $rt_byteclsCache;
|
||||
}
|
||||
$rt_shortclsCache = null;
|
||||
$rt_shortcls = function() {
|
||||
if ($rt_shortclsCache == null) {
|
||||
$rt_shortclsCache = $rt_createcls();
|
||||
}
|
||||
return $rt_shortclsCache;
|
||||
}
|
||||
$rt_intclsCache = null;
|
||||
$rt_intcls = function() {
|
||||
if ($rt_intclsCache == null) {
|
||||
$rt_intclsCache = $rt_createcls();
|
||||
}
|
||||
return $rt_intclsCache;
|
||||
}
|
||||
$rt_longclsCache = null;
|
||||
$rt_longcls = function() {
|
||||
if ($rt_longclsCache == null) {
|
||||
$rt_longclsCache = $rt_createcls();
|
||||
}
|
||||
return $rt_longclsCache;
|
||||
}
|
||||
$rt_floatclsCache = null;
|
||||
$rt_floatcls = function() {
|
||||
if ($rt_floatclsCache == null) {
|
||||
$rt_floatclsCache = $rt_createcls();
|
||||
}
|
||||
return $rt_floatclsCache;
|
||||
}
|
||||
$rt_doubleclsCache = null;
|
||||
$rt_doublecls = function() {
|
||||
if ($rt_doubleclsCache == null) {
|
||||
$rt_doubleclsCache = $rt_createcls();
|
||||
}
|
||||
return $rt_doubleclsCache;
|
||||
}
|
||||
$rt_voidclsCache = null;
|
||||
$rt_voidcls = function() {
|
||||
if ($rt_voidclsCache == null) {
|
||||
$rt_voidclsCache = $rt_createcls();
|
||||
}
|
||||
return $rt_voidclsCache;
|
||||
}
|
||||
$rt_equals = function(a, b) {
|
||||
if (a === b) {
|
||||
return true;
|
||||
}
|
||||
if (a === null || b === null) {
|
||||
return false;
|
||||
}
|
||||
if (typeof(a) == 'object') {
|
||||
return a.equals(b);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$rt_clinit = function(cls) {
|
||||
if (cls.$clinit) {
|
||||
var f = cls.$clinit;
|
||||
delete cls.$clinit;
|
||||
f();
|
||||
}
|
||||
return cls;
|
||||
}
|
||||
$rt_init = function(cls, constructor, args) {
|
||||
var obj = new cls();
|
||||
cls.prototype[constructor].apply(obj, args);
|
||||
return obj;
|
||||
}
|
||||
|
||||
$rt = {
|
||||
createBooleanArray : function(cls, sz) {
|
||||
|
@ -49,20 +166,6 @@ $rt = {
|
|||
}
|
||||
return arr;
|
||||
},
|
||||
createNumericArray : function(cls, sz) {
|
||||
var arr = $rt.createArray(cls, sz);
|
||||
for (var i = 0; i < sz; i = (i + 1) | 0) {
|
||||
arr[i] = 0;
|
||||
}
|
||||
return arr;
|
||||
},
|
||||
createLongArray : function(sz) {
|
||||
var arr = $rt.createArray($rt.longcls(), sz);
|
||||
for (var i = 0; i < sz; i = (i + 1) | 0) {
|
||||
arr[i] = Long.ZERO;
|
||||
}
|
||||
return arr;
|
||||
},
|
||||
createMultiArray : function(cls, dimensions) {
|
||||
for (var i = 1; i < dimensions.length; i = (i + 1) | 0) {
|
||||
cls = $rt.arraycls(cls);
|
||||
|
@ -86,93 +189,6 @@ $rt = {
|
|||
$rt.setId(arr, $rt.lastObjectId++);
|
||||
return arr;
|
||||
},
|
||||
createcls : function() {
|
||||
return {
|
||||
$meta : {
|
||||
supertypes : []
|
||||
}
|
||||
};
|
||||
},
|
||||
booleancls : function() {
|
||||
if ($rt.booleanclsCache == null) {
|
||||
$rt.booleanclsCache = $rt.createcls();
|
||||
}
|
||||
return $rt.booleanclsCache;
|
||||
},
|
||||
charcls : function() {
|
||||
if ($rt.charclsCache == null) {
|
||||
$rt.charclsCache = $rt.createcls();
|
||||
}
|
||||
return $rt.charclsCache;
|
||||
},
|
||||
bytecls : function() {
|
||||
if ($rt.byteclsCache == null) {
|
||||
$rt.byteclsCache = $rt.createcls();
|
||||
}
|
||||
return $rt.byteclsCache;
|
||||
},
|
||||
shortcls : function() {
|
||||
if ($rt.shortclsCache == null) {
|
||||
$rt.shortclsCache = $rt.createcls();
|
||||
}
|
||||
return $rt.shortclsCache;
|
||||
},
|
||||
intcls : function() {
|
||||
if ($rt.intclsCache == null) {
|
||||
$rt.intclsCache = $rt.createcls();
|
||||
}
|
||||
return $rt.intclsCache;
|
||||
},
|
||||
longcls : function() {
|
||||
if ($rt.longclsCache == null) {
|
||||
$rt.longclsCache = $rt.createcls();
|
||||
}
|
||||
return $rt.longclsCache;
|
||||
},
|
||||
floatcls : function() {
|
||||
if ($rt.floatclsCache == null) {
|
||||
$rt.floatclsCache = $rt.createcls();
|
||||
}
|
||||
return $rt.floatclsCache;
|
||||
},
|
||||
doublecls : function() {
|
||||
if ($rt.doubleclsCache == null) {
|
||||
$rt.doubleclsCache = $rt.createcls();
|
||||
}
|
||||
return $rt.doubleclsCache;
|
||||
},
|
||||
voidcls : function() {
|
||||
if ($rt.voidclsCache == null) {
|
||||
$rt.voidclsCache = $rt.createcls();
|
||||
}
|
||||
return $rt.voidclsCache;
|
||||
},
|
||||
equals : function(a, b) {
|
||||
if (a === b) {
|
||||
return true;
|
||||
}
|
||||
if (a === null || b === null) {
|
||||
return false;
|
||||
}
|
||||
if (typeof(a) == 'object') {
|
||||
return a.equals(b);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
clinit : function(cls) {
|
||||
if (cls.$clinit) {
|
||||
var f = cls.$clinit;
|
||||
delete cls.$clinit;
|
||||
f();
|
||||
}
|
||||
return cls;
|
||||
},
|
||||
init : function(cls, constructor, args) {
|
||||
var obj = new cls();
|
||||
cls.prototype[constructor].apply(obj, args);
|
||||
return obj;
|
||||
},
|
||||
assertNotNaN : function(value) {
|
||||
if (typeof value == 'number' && isNaN(value)) {
|
||||
throw "NaN";
|
||||
|
|
Loading…
Reference in New Issue
Block a user