mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Dependency API supports multiple occurence of reaching events for
different location
This commit is contained in:
parent
cd0664d695
commit
1fff443c36
|
@ -31,12 +31,12 @@ public class ClassLookupDependencySupport implements DependencyListener {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void classAchieved(DependencyAgent agent, String className) {
|
||||
public void classAchieved(DependencyAgent agent, String className, CallLocation location) {
|
||||
allClasses.propagate(agent.getType(className));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void methodAchieved(final DependencyAgent agent, MethodDependency method) {
|
||||
public void methodAchieved(final DependencyAgent agent, MethodDependency method, final CallLocation location) {
|
||||
MethodReference ref = method.getReference();
|
||||
if (ref.getClassName().equals("java.lang.Class") && ref.getName().equals("forNameImpl")) {
|
||||
allClasses.addConsumer(new DependencyConsumer() {
|
||||
|
@ -47,7 +47,7 @@ public class ClassLookupDependencySupport implements DependencyListener {
|
|||
}
|
||||
MethodReader initMethod = cls.getMethod(new MethodDescriptor("<clinit>", ValueType.VOID));
|
||||
if (initMethod != null) {
|
||||
agent.linkMethod(initMethod.getReference(), null).use();
|
||||
agent.linkMethod(initMethod.getReference(), location).use();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -55,6 +55,6 @@ public class ClassLookupDependencySupport implements DependencyListener {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void fieldAchieved(DependencyAgent dependencyChecker, FieldDependency field) {
|
||||
public void fieldAchieved(DependencyAgent dependencyChecker, FieldDependency field, CallLocation location) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
package org.teavm.classlib.impl;
|
||||
|
||||
import org.teavm.dependency.*;
|
||||
import org.teavm.model.CallLocation;
|
||||
import org.teavm.model.ClassReader;
|
||||
import org.teavm.model.MethodDescriptor;
|
||||
import org.teavm.model.MethodReader;
|
||||
|
@ -35,7 +36,7 @@ public class EnumDependencySupport implements DependencyListener {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void classAchieved(DependencyAgent agent, String className) {
|
||||
public void classAchieved(DependencyAgent agent, String className, CallLocation location) {
|
||||
ClassReader cls = agent.getClassSource().get(className);
|
||||
if (cls == null || cls.getParent() == null || !cls.getParent().equals("java.lang.Enum")) {
|
||||
return;
|
||||
|
@ -45,25 +46,25 @@ public class EnumDependencySupport implements DependencyListener {
|
|||
MethodReader method = cls.getMethod(new MethodDescriptor("values",
|
||||
ValueType.arrayOf(ValueType.object(cls.getName()))));
|
||||
if (method != null) {
|
||||
agent.linkMethod(method.getReference(), null).use();
|
||||
agent.linkMethod(method.getReference(), location).use();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void methodAchieved(DependencyAgent agent, MethodDependency method) {
|
||||
public void methodAchieved(DependencyAgent agent, MethodDependency method, CallLocation location) {
|
||||
if (method.getReference().getClassName().equals("java.lang.Class") &&
|
||||
method.getReference().getName().equals("getEnumConstantsImpl")) {
|
||||
unlocked = true;
|
||||
allEnums.connect(method.getResult().getArrayItem());
|
||||
method.getResult().propagate(agent.getType("[java.lang.Enum"));
|
||||
for (String cls : agent.getAchievableClasses()) {
|
||||
classAchieved(agent, cls);
|
||||
classAchieved(agent, cls, location);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fieldAchieved(DependencyAgent agent, FieldDependency field) {
|
||||
public void fieldAchieved(DependencyAgent agent, FieldDependency field, CallLocation location) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ public class NewInstanceDependencySupport implements DependencyListener {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void classAchieved(DependencyAgent agent, String className) {
|
||||
public void classAchieved(DependencyAgent agent, String className, CallLocation location) {
|
||||
ClassReader cls = agent.getClassSource().get(className);
|
||||
if (cls == null) {
|
||||
return;
|
||||
|
@ -46,24 +46,24 @@ public class NewInstanceDependencySupport implements DependencyListener {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void methodAchieved(final DependencyAgent agent, MethodDependency method) {
|
||||
public void methodAchieved(final DependencyAgent agent, MethodDependency method, final CallLocation location) {
|
||||
MethodReader reader = method.getMethod();
|
||||
if (reader.getOwnerName().equals("java.lang.Class") && reader.getName().equals("newInstance")) {
|
||||
allClassesNode.connect(method.getResult());
|
||||
method.getResult().addConsumer(new DependencyConsumer() {
|
||||
@Override public void consume(DependencyAgentType type) {
|
||||
attachConstructor(agent, type.getName());
|
||||
attachConstructor(agent, type.getName(), location);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void attachConstructor(DependencyAgent checker, String type) {
|
||||
private void attachConstructor(DependencyAgent checker, String type, CallLocation location) {
|
||||
MethodReference ref = new MethodReference(type, new MethodDescriptor("<init>", ValueType.VOID));
|
||||
checker.linkMethod(ref, null).use();
|
||||
checker.linkMethod(ref, location).use();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fieldAchieved(DependencyAgent dependencyAgent, FieldDependency field) {
|
||||
public void fieldAchieved(DependencyAgent dependencyAgent, FieldDependency field, CallLocation location) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.teavm.codegen.SourceWriter;
|
|||
import org.teavm.dependency.*;
|
||||
import org.teavm.javascript.ni.Generator;
|
||||
import org.teavm.javascript.ni.GeneratorContext;
|
||||
import org.teavm.model.CallLocation;
|
||||
import org.teavm.model.MethodDescriptor;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.ValueType;
|
||||
|
@ -34,6 +35,7 @@ import org.teavm.model.ValueType;
|
|||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public class ServiceLoaderSupport implements Generator, DependencyListener {
|
||||
private Set<String> achievedClasses;
|
||||
private Map<String, List<String>> serviceMap = new HashMap<>();
|
||||
private DependencyNode allClassesNode;
|
||||
private ClassLoader classLoader;
|
||||
|
@ -82,7 +84,10 @@ public class ServiceLoaderSupport implements Generator, DependencyListener {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void classAchieved(DependencyAgent agent, String className) {
|
||||
public void classAchieved(DependencyAgent agent, String className, CallLocation location) {
|
||||
if (!achievedClasses.add(className)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Enumeration<URL> resources = classLoader.getResources("META-INF/services/" + className);
|
||||
while (resources.hasMoreElements()) {
|
||||
|
@ -118,25 +123,25 @@ public class ServiceLoaderSupport implements Generator, DependencyListener {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void methodAchieved(final DependencyAgent agent, MethodDependency method) {
|
||||
public void methodAchieved(final DependencyAgent agent, MethodDependency method, final CallLocation location) {
|
||||
MethodReference ref = method.getReference();
|
||||
if (ref.getClassName().equals("java.util.ServiceLoader") && ref.getName().equals("loadServices")) {
|
||||
method.getResult().propagate(agent.getType("[java.lang.Object"));
|
||||
allClassesNode.connect(method.getResult().getArrayItem());
|
||||
method.getResult().getArrayItem().addConsumer(new DependencyConsumer() {
|
||||
@Override public void consume(DependencyAgentType type) {
|
||||
initConstructor(agent, type.getName());
|
||||
initConstructor(agent, type.getName(), location);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void initConstructor(DependencyAgent agent, String type) {
|
||||
private void initConstructor(DependencyAgent agent, String type, CallLocation location) {
|
||||
MethodReference ctor = new MethodReference(type, new MethodDescriptor("<init>", ValueType.VOID));
|
||||
agent.linkMethod(ctor, null).use();
|
||||
agent.linkMethod(ctor, location).use();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fieldAchieved(DependencyAgent agent, FieldDependency field) {
|
||||
public void fieldAchieved(DependencyAgent agent, FieldDependency field, CallLocation location) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.teavm.dependency.DependencyPlugin;
|
|||
import org.teavm.dependency.MethodDependency;
|
||||
import org.teavm.javascript.ni.Generator;
|
||||
import org.teavm.javascript.ni.GeneratorContext;
|
||||
import org.teavm.model.CallLocation;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
/**
|
||||
|
@ -52,7 +53,7 @@ public class CharacterNativeGenerator implements Generator, DependencyPlugin {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void methodAchieved(DependencyAgent agent, MethodDependency method) {
|
||||
public void methodAchieved(DependencyAgent agent, MethodDependency method, CallLocation location) {
|
||||
switch (method.getReference().getName()) {
|
||||
case "obtainDigitMapping":
|
||||
case "obtainClasses":
|
||||
|
|
|
@ -186,7 +186,7 @@ public class ClassNativeGenerator implements Generator, Injector, DependencyPlug
|
|||
}
|
||||
|
||||
@Override
|
||||
public void methodAchieved(DependencyAgent agent, MethodDependency graph) {
|
||||
public void methodAchieved(DependencyAgent agent, MethodDependency graph, CallLocation location) {
|
||||
switch (graph.getReference().getName()) {
|
||||
case "voidClass":
|
||||
case "booleanClass":
|
||||
|
@ -205,8 +205,8 @@ public class ClassNativeGenerator implements Generator, Injector, DependencyPlug
|
|||
graph.getResult().propagate(agent.getType("java.lang.Class"));
|
||||
break;
|
||||
case "newInstance":
|
||||
agent.linkMethod(new MethodReference(InstantiationException.class.getName(), "<init>",
|
||||
ValueType.VOID), null).use();
|
||||
agent.linkMethod(new MethodReference(InstantiationException.class, "<init>", void.class),
|
||||
location).use();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.teavm.javascript.ni.Generator;
|
|||
import org.teavm.javascript.ni.GeneratorContext;
|
||||
import org.teavm.javascript.ni.Injector;
|
||||
import org.teavm.javascript.ni.InjectorContext;
|
||||
import org.teavm.model.CallLocation;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
/**
|
||||
|
@ -58,7 +59,7 @@ public class ObjectNativeGenerator implements Generator, Injector, DependencyPlu
|
|||
}
|
||||
|
||||
@Override
|
||||
public void methodAchieved(DependencyAgent agent, MethodDependency method) {
|
||||
public void methodAchieved(DependencyAgent agent, MethodDependency method, CallLocation location) {
|
||||
switch (method.getReference().getName()) {
|
||||
case "clone":
|
||||
method.getVariable(0).connect(method.getResult());
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.teavm.dependency.DependencyPlugin;
|
|||
import org.teavm.dependency.MethodDependency;
|
||||
import org.teavm.javascript.ni.Injector;
|
||||
import org.teavm.javascript.ni.InjectorContext;
|
||||
import org.teavm.model.CallLocation;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
/**
|
||||
|
@ -29,7 +30,7 @@ import org.teavm.model.MethodReference;
|
|||
*/
|
||||
public class StringNativeGenerator implements Injector, DependencyPlugin {
|
||||
@Override
|
||||
public void methodAchieved(DependencyAgent agent, MethodDependency method) {
|
||||
public void methodAchieved(DependencyAgent agent, MethodDependency method, CallLocation location) {
|
||||
switch (method.getReference().getName()) {
|
||||
case "wrap":
|
||||
method.getVariable(1).connect(method.getResult());
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.teavm.codegen.SourceWriter;
|
|||
import org.teavm.dependency.*;
|
||||
import org.teavm.javascript.ni.Generator;
|
||||
import org.teavm.javascript.ni.GeneratorContext;
|
||||
import org.teavm.model.CallLocation;
|
||||
import org.teavm.model.FieldReference;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
|
@ -54,7 +55,7 @@ public class SystemNativeGenerator implements Generator, DependencyPlugin {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void methodAchieved(DependencyAgent agent, MethodDependency method) {
|
||||
public void methodAchieved(DependencyAgent agent, MethodDependency method, CallLocation location) {
|
||||
switch (method.getReference().getName()) {
|
||||
case "doArrayCopy":
|
||||
achieveArrayCopy(method);
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.teavm.codegen.SourceWriter;
|
|||
import org.teavm.dependency.*;
|
||||
import org.teavm.javascript.ni.Generator;
|
||||
import org.teavm.javascript.ni.GeneratorContext;
|
||||
import org.teavm.model.CallLocation;
|
||||
import org.teavm.model.ClassReader;
|
||||
import org.teavm.model.MethodDescriptor;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
@ -38,7 +39,7 @@ public class ArrayNativeGenerator implements Generator, DependencyPlugin {
|
|||
ValueType.INTEGER, ValueType.LONG, ValueType.FLOAT, ValueType.DOUBLE, ValueType.BOOLEAN };
|
||||
|
||||
@Override
|
||||
public void methodAchieved(DependencyAgent agent, MethodDependency method) {
|
||||
public void methodAchieved(DependencyAgent agent, MethodDependency method, CallLocation location) {
|
||||
switch (method.getReference().getName()) {
|
||||
case "getLength":
|
||||
achieveGetLength(agent, method);
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.teavm.dependency.DependencyPlugin;
|
|||
import org.teavm.dependency.MethodDependency;
|
||||
import org.teavm.javascript.ni.Generator;
|
||||
import org.teavm.javascript.ni.GeneratorContext;
|
||||
import org.teavm.model.CallLocation;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
/**
|
||||
|
@ -70,7 +71,7 @@ public class DateNativeGenerator implements Generator, DependencyPlugin {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void methodAchieved(DependencyAgent agent, MethodDependency method) {
|
||||
public void methodAchieved(DependencyAgent agent, MethodDependency method, CallLocation location) {
|
||||
switch (method.getMethod().getName()) {
|
||||
case "toString":
|
||||
case "toLocaleFormat":
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.teavm.dependency.DependencyPlugin;
|
|||
import org.teavm.dependency.MethodDependency;
|
||||
import org.teavm.javascript.ni.Generator;
|
||||
import org.teavm.javascript.ni.GeneratorContext;
|
||||
import org.teavm.model.CallLocation;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
/**
|
||||
|
@ -34,7 +35,7 @@ public class TimerNativeGenerator implements Generator, DependencyPlugin {
|
|||
"performOnce", void.class);
|
||||
|
||||
@Override
|
||||
public void methodAchieved(DependencyAgent agent, MethodDependency method) {
|
||||
public void methodAchieved(DependencyAgent agent, MethodDependency method, CallLocation location) {
|
||||
switch (method.getReference().getName()) {
|
||||
case "scheduleOnce": {
|
||||
MethodDependency performMethod = agent.linkMethod(performOnceRef, null);
|
||||
|
|
|
@ -69,16 +69,19 @@ public class DefaultCallGraphNode implements CallGraphNode {
|
|||
return safeCallersCallSites;
|
||||
}
|
||||
|
||||
public void addCallSite(MethodReference method, InstructionLocation location) {
|
||||
public boolean addCallSite(MethodReference method, InstructionLocation location) {
|
||||
DefaultCallGraphNode callee = graph.getNode(method);
|
||||
DefaultCallSite callSite = new DefaultCallSite(location, callee, this);
|
||||
if (callSites.add(callSite)) {
|
||||
callee.callerCallSites.add(callSite);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void addCallSite(MethodReference method) {
|
||||
addCallSite(method, null);
|
||||
public boolean addCallSite(MethodReference method) {
|
||||
return addCallSite(method, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
package org.teavm.callgraph;
|
||||
|
||||
import java.util.Objects;
|
||||
import org.teavm.model.CallLocation;
|
||||
import org.teavm.model.InstructionLocation;
|
||||
|
||||
/**
|
||||
|
@ -26,11 +27,15 @@ public class DefaultCallSite implements CallSite {
|
|||
private InstructionLocation location;
|
||||
private DefaultCallGraphNode callee;
|
||||
private DefaultCallGraphNode caller;
|
||||
private CallLocation exactLocation;
|
||||
|
||||
DefaultCallSite(InstructionLocation location, DefaultCallGraphNode callee, DefaultCallGraphNode caller) {
|
||||
this.location = location;
|
||||
this.callee = callee;
|
||||
this.caller = caller;
|
||||
if (caller != null) {
|
||||
exactLocation = new CallLocation(caller.getMethod(), location);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -38,6 +43,10 @@ public class DefaultCallSite implements CallSite {
|
|||
return location;
|
||||
}
|
||||
|
||||
public CallLocation getExactLocation() {
|
||||
return exactLocation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultCallGraphNode getCallee() {
|
||||
return callee;
|
||||
|
|
|
@ -26,7 +26,6 @@ import org.teavm.callgraph.CallGraph;
|
|||
import org.teavm.callgraph.DefaultCallGraph;
|
||||
import org.teavm.callgraph.DefaultCallGraphNode;
|
||||
import org.teavm.common.CachedMapper;
|
||||
import org.teavm.common.CachedMapper.KeyListener;
|
||||
import org.teavm.common.Mapper;
|
||||
import org.teavm.common.ServiceRepository;
|
||||
import org.teavm.diagnostics.Diagnostics;
|
||||
|
@ -109,37 +108,6 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
|
|||
return createClassDependency(preimage);
|
||||
}
|
||||
});
|
||||
methodCache.addKeyListener(new KeyListener<MethodReference>() {
|
||||
@Override public void keyAdded(MethodReference key) {
|
||||
MethodDependency graph = methodCache.getKnown(key);
|
||||
if (!graph.isMissing()) {
|
||||
for (DependencyListener listener : listeners) {
|
||||
listener.methodAchieved(DependencyChecker.this, graph);
|
||||
}
|
||||
activateDependencyPlugin(graph);
|
||||
}
|
||||
}
|
||||
});
|
||||
fieldCache.addKeyListener(new KeyListener<FieldReference>() {
|
||||
@Override public void keyAdded(FieldReference key) {
|
||||
FieldDependency fieldDep = fieldCache.getKnown(key);
|
||||
if (!fieldDep.isMissing()) {
|
||||
for (DependencyListener listener : listeners) {
|
||||
listener.fieldAchieved(DependencyChecker.this, fieldDep);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
classCache.addKeyListener(new KeyListener<String>() {
|
||||
@Override public void keyAdded(String key) {
|
||||
ClassDependency classDep = classCache.getKnown(key);
|
||||
if (!classDep.isMissing()) {
|
||||
for (DependencyListener listener : listeners) {
|
||||
listener.classAchieved(DependencyChecker.this, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public DependencyCheckerInterruptor getInterruptor() {
|
||||
|
@ -234,26 +202,33 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
|
|||
@Override
|
||||
public ClassDependency linkClass(String className, CallLocation callLocation) {
|
||||
ClassDependency dep = classCache.map(className);
|
||||
boolean added = true;
|
||||
if (callLocation != null && callLocation.getMethod() != null) {
|
||||
DefaultCallGraphNode callGraphNode = callGraph.getNode(callLocation.getMethod());
|
||||
addClassAccess(callGraphNode, className, callLocation.getSourceLocation());
|
||||
added = addClassAccess(callGraphNode, className, callLocation.getSourceLocation());
|
||||
}
|
||||
if (!dep.isMissing() && added) {
|
||||
for (DependencyListener listener : listeners) {
|
||||
listener.classAchieved(DependencyChecker.this, className, callLocation);
|
||||
}
|
||||
}
|
||||
return dep;
|
||||
}
|
||||
|
||||
private void addClassAccess(DefaultCallGraphNode node, String className, InstructionLocation loc) {
|
||||
private boolean addClassAccess(DefaultCallGraphNode node, String className, InstructionLocation loc) {
|
||||
if (!node.addClassAccess(className, loc)) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
ClassReader cls = classSource.get(className);
|
||||
if (cls != null) {
|
||||
if (cls.getParent() != null && !cls.getParent().equals(cls.getName())) {
|
||||
addClassAccess(node, cls.getParent(), loc);
|
||||
return addClassAccess(node, cls.getParent(), loc);
|
||||
}
|
||||
for (String iface : cls.getInterfaces()) {
|
||||
addClassAccess(node, iface, loc);
|
||||
return addClassAccess(node, iface, loc);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private ClassDependency createClassDependency(String className) {
|
||||
|
@ -276,10 +251,19 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
|
|||
throw new IllegalArgumentException();
|
||||
}
|
||||
callGraph.getNode(methodRef);
|
||||
boolean added = true;
|
||||
if (callLocation != null && callLocation.getMethod() != null) {
|
||||
callGraph.getNode(callLocation.getMethod()).addCallSite(methodRef, callLocation.getSourceLocation());
|
||||
added = callGraph.getNode(callLocation.getMethod()).addCallSite(methodRef,
|
||||
callLocation.getSourceLocation());
|
||||
}
|
||||
return methodCache.map(methodRef);
|
||||
MethodDependency graph = methodCache.map(methodRef);
|
||||
if (!graph.isMissing() && added) {
|
||||
for (DependencyListener listener : listeners) {
|
||||
listener.methodAchieved(this, graph, callLocation);
|
||||
}
|
||||
activateDependencyPlugin(graph, callLocation);
|
||||
}
|
||||
return graph;
|
||||
}
|
||||
|
||||
void initClass(ClassDependency cls, final CallLocation callLocation) {
|
||||
|
@ -404,8 +388,9 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
|
|||
|
||||
@Override
|
||||
public FieldDependency linkField(final FieldReference fieldRef, final CallLocation location) {
|
||||
boolean added = true;
|
||||
if (location != null) {
|
||||
callGraph.getNode(location.getMethod()).addFieldAccess(fieldRef, location.getSourceLocation());
|
||||
added = callGraph.getNode(location.getMethod()).addFieldAccess(fieldRef, location.getSourceLocation());
|
||||
}
|
||||
FieldDependency dep = fieldCache.map(fieldRef);
|
||||
if (!dep.isMissing()) {
|
||||
|
@ -415,6 +400,11 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
|
|||
}
|
||||
});
|
||||
}
|
||||
if (!dep.isMissing() && added) {
|
||||
for (DependencyListener listener : listeners) {
|
||||
listener.fieldAchieved(DependencyChecker.this, dep, location);
|
||||
}
|
||||
}
|
||||
return dep;
|
||||
}
|
||||
|
||||
|
@ -444,7 +434,18 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
|
|||
return dep;
|
||||
}
|
||||
|
||||
private void activateDependencyPlugin(MethodDependency methodDep) {
|
||||
private void activateDependencyPlugin(MethodDependency methodDep, CallLocation location) {
|
||||
attachDependencyPlugin(methodDep);
|
||||
if (methodDep.dependencyPlugin != null) {
|
||||
methodDep.dependencyPlugin.methodAchieved(this, methodDep, location);
|
||||
}
|
||||
}
|
||||
|
||||
private void attachDependencyPlugin(MethodDependency methodDep) {
|
||||
if (methodDep.dependencyPluginAttached) {
|
||||
return;
|
||||
}
|
||||
methodDep.dependencyPluginAttached = true;
|
||||
AnnotationReader depAnnot = methodDep.getMethod().getAnnotations().get(PluggableDependency.class.getName());
|
||||
if (depAnnot == null) {
|
||||
return;
|
||||
|
@ -457,13 +458,11 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
|
|||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException("Dependency plugin not found: " + depClassName, e);
|
||||
}
|
||||
DependencyPlugin plugin;
|
||||
try {
|
||||
plugin = (DependencyPlugin)depClass.newInstance();
|
||||
methodDep.dependencyPlugin = (DependencyPlugin)depClass.newInstance();
|
||||
} catch (IllegalAccessException | InstantiationException e) {
|
||||
throw new RuntimeException("Can't instantiate dependency plugin " + depClassName, e);
|
||||
}
|
||||
plugin.methodAchieved(this, methodDep);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
*/
|
||||
package org.teavm.dependency;
|
||||
|
||||
import org.teavm.model.CallLocation;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
|
@ -22,9 +24,9 @@ package org.teavm.dependency;
|
|||
public interface DependencyListener {
|
||||
void started(DependencyAgent agent);
|
||||
|
||||
void classAchieved(DependencyAgent agent, String className);
|
||||
void classAchieved(DependencyAgent agent, String className, CallLocation location);
|
||||
|
||||
void methodAchieved(DependencyAgent agent, MethodDependency method);
|
||||
void methodAchieved(DependencyAgent agent, MethodDependency method, CallLocation location);
|
||||
|
||||
void fieldAchieved(DependencyAgent agent, FieldDependency field);
|
||||
void fieldAchieved(DependencyAgent agent, FieldDependency field, CallLocation location);
|
||||
}
|
||||
|
|
|
@ -15,10 +15,12 @@
|
|||
*/
|
||||
package org.teavm.dependency;
|
||||
|
||||
import org.teavm.model.CallLocation;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public interface DependencyPlugin {
|
||||
void methodAchieved(DependencyAgent checker, MethodDependency method);
|
||||
void methodAchieved(DependencyAgent checker, MethodDependency method, CallLocation location);
|
||||
}
|
||||
|
|
|
@ -32,6 +32,8 @@ public class MethodDependency implements MethodDependencyInfo {
|
|||
private MethodReader method;
|
||||
private MethodReference reference;
|
||||
private boolean used;
|
||||
DependencyPlugin dependencyPlugin;
|
||||
boolean dependencyPluginAttached;
|
||||
|
||||
MethodDependency(DependencyChecker dependencyChecker, DependencyNode[] variableNodes, int parameterCount,
|
||||
DependencyNode resultNode, DependencyNode thrown, MethodReader method, MethodReference reference) {
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
package org.teavm.tooling;
|
||||
|
||||
import org.teavm.dependency.*;
|
||||
import org.teavm.model.CallLocation;
|
||||
import org.teavm.model.ClassReader;
|
||||
import org.teavm.model.ClassReaderSource;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
@ -35,7 +36,7 @@ class TestExceptionDependency implements DependencyListener {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void classAchieved(DependencyAgent agent, String className) {
|
||||
public void classAchieved(DependencyAgent agent, String className, CallLocation location) {
|
||||
if (isException(agent.getClassSource(), className)) {
|
||||
allClasses.propagate(agent.getType(className));
|
||||
}
|
||||
|
@ -56,13 +57,13 @@ class TestExceptionDependency implements DependencyListener {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void methodAchieved(DependencyAgent agent, MethodDependency method) {
|
||||
public void methodAchieved(DependencyAgent agent, MethodDependency method, CallLocation location) {
|
||||
if (method.getReference().equals(getMessageRef)) {
|
||||
allClasses.connect(method.getVariable(1));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fieldAchieved(DependencyAgent agent, FieldDependency field) {
|
||||
public void fieldAchieved(DependencyAgent agent, FieldDependency field, CallLocation location) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.teavm.codegen.SourceWriter;
|
|||
import org.teavm.dependency.*;
|
||||
import org.teavm.javascript.Renderer;
|
||||
import org.teavm.javascript.RenderingContext;
|
||||
import org.teavm.model.CallLocation;
|
||||
import org.teavm.vm.BuildTarget;
|
||||
import org.teavm.vm.spi.AbstractRendererListener;
|
||||
|
||||
|
@ -74,14 +75,14 @@ public class EntryPointGenerator extends AbstractRendererListener implements Dep
|
|||
}
|
||||
|
||||
@Override
|
||||
public void classAchieved(DependencyAgent agent, String className) {
|
||||
public void classAchieved(DependencyAgent agent, String className, CallLocation location) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void methodAchieved(DependencyAgent agent, MethodDependency method) {
|
||||
public void methodAchieved(DependencyAgent agent, MethodDependency method, CallLocation location) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fieldAchieved(DependencyAgent agent, FieldDependency field) {
|
||||
public void fieldAchieved(DependencyAgent agent, FieldDependency field, CallLocation location) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,9 +15,27 @@
|
|||
*/
|
||||
package org.teavm.html4j;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import net.java.html.js.JavaScriptBody;
|
||||
import org.teavm.dependency.*;
|
||||
import org.teavm.model.*;
|
||||
import org.teavm.dependency.DependencyAgent;
|
||||
import org.teavm.dependency.DependencyAgentType;
|
||||
import org.teavm.dependency.DependencyConsumer;
|
||||
import org.teavm.dependency.DependencyListener;
|
||||
import org.teavm.dependency.DependencyNode;
|
||||
import org.teavm.dependency.FieldDependency;
|
||||
import org.teavm.dependency.MethodDependency;
|
||||
import org.teavm.model.AnnotationReader;
|
||||
import org.teavm.model.AnnotationValue;
|
||||
import org.teavm.model.CallLocation;
|
||||
import org.teavm.model.ClassReader;
|
||||
import org.teavm.model.ClassReaderSource;
|
||||
import org.teavm.model.ElementModifier;
|
||||
import org.teavm.model.MethodDescriptor;
|
||||
import org.teavm.model.MethodReader;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -25,6 +43,7 @@ import org.teavm.model.*;
|
|||
*/
|
||||
public class JavaScriptBodyDependency implements DependencyListener {
|
||||
private DependencyNode allClassesNode;
|
||||
private Map<MethodReference, Set<MethodReference>> achievedMethods = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void started(DependencyAgent agent) {
|
||||
|
@ -43,7 +62,7 @@ public class JavaScriptBodyDependency implements DependencyListener {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void classAchieved(DependencyAgent agent, String className) {
|
||||
public void classAchieved(DependencyAgent agent, String className, CallLocation location) {
|
||||
ClassReader cls = agent.getClassSource().get(className);
|
||||
if (cls != null && !cls.hasModifier(ElementModifier.ABSTRACT) &&
|
||||
!cls.hasModifier(ElementModifier.INTERFACE)) {
|
||||
|
@ -52,13 +71,21 @@ public class JavaScriptBodyDependency implements DependencyListener {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void methodAchieved(DependencyAgent agent, MethodDependency method) {
|
||||
public void methodAchieved(DependencyAgent agent, MethodDependency method, CallLocation location) {
|
||||
Set<MethodReference> methodsToAchieve = achievedMethods.get(method.getReference());
|
||||
if (methodsToAchieve != null) {
|
||||
for (MethodReference methodToAchieve : methodsToAchieve) {
|
||||
agent.linkMethod(methodToAchieve, location);
|
||||
}
|
||||
return;
|
||||
}
|
||||
achievedMethods.put(method.getReference(), new HashSet<MethodReference>());
|
||||
if (method.isMissing()) {
|
||||
return;
|
||||
}
|
||||
AnnotationReader annot = method.getMethod().getAnnotations().get(JavaScriptBody.class.getName());
|
||||
if (annot != null) {
|
||||
includeDefaultDependencies(agent);
|
||||
includeDefaultDependencies(agent, location);
|
||||
AnnotationValue javacall = annot.getValue("javacall");
|
||||
if (method.getResult() != null) {
|
||||
allClassesNode.connect(method.getResult());
|
||||
|
@ -74,26 +101,26 @@ public class JavaScriptBodyDependency implements DependencyListener {
|
|||
}
|
||||
if (javacall != null && javacall.getBoolean()) {
|
||||
String body = annot.getValue("body").getString();
|
||||
new GeneratorJsCallback(agent, method).parse(body);
|
||||
new GeneratorJsCallback(agent, method, location).parse(body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void includeDefaultDependencies(DependencyAgent agent) {
|
||||
agent.linkMethod(JavaScriptConvGenerator.fromJsMethod, null).use();
|
||||
agent.linkMethod(JavaScriptConvGenerator.toJsMethod, null).use();
|
||||
agent.linkMethod(JavaScriptConvGenerator.intValueMethod, null).use();
|
||||
agent.linkMethod(JavaScriptConvGenerator.valueOfIntMethod, null).use();
|
||||
agent.linkMethod(JavaScriptConvGenerator.booleanValueMethod, null).use();
|
||||
agent.linkMethod(JavaScriptConvGenerator.valueOfBooleanMethod, null).use();
|
||||
agent.linkMethod(JavaScriptConvGenerator.doubleValueMethod, null).use();
|
||||
agent.linkMethod(JavaScriptConvGenerator.valueOfDoubleMethod, null).use();
|
||||
agent.linkMethod(JavaScriptConvGenerator.charValueMethod, null).use();
|
||||
agent.linkMethod(JavaScriptConvGenerator.valueOfCharMethod, null).use();
|
||||
private void includeDefaultDependencies(DependencyAgent agent, CallLocation location) {
|
||||
agent.linkMethod(JavaScriptConvGenerator.fromJsMethod, location).use();
|
||||
agent.linkMethod(JavaScriptConvGenerator.toJsMethod, location).use();
|
||||
agent.linkMethod(JavaScriptConvGenerator.intValueMethod, location).use();
|
||||
agent.linkMethod(JavaScriptConvGenerator.valueOfIntMethod, location).use();
|
||||
agent.linkMethod(JavaScriptConvGenerator.booleanValueMethod, location).use();
|
||||
agent.linkMethod(JavaScriptConvGenerator.valueOfBooleanMethod, location).use();
|
||||
agent.linkMethod(JavaScriptConvGenerator.doubleValueMethod, location).use();
|
||||
agent.linkMethod(JavaScriptConvGenerator.valueOfDoubleMethod, location).use();
|
||||
agent.linkMethod(JavaScriptConvGenerator.charValueMethod, location).use();
|
||||
agent.linkMethod(JavaScriptConvGenerator.valueOfCharMethod, location).use();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fieldAchieved(DependencyAgent agent, FieldDependency fieldDep) {
|
||||
public void fieldAchieved(DependencyAgent agent, FieldDependency fieldDep, CallLocation location) {
|
||||
}
|
||||
|
||||
private static MethodReader findMethod(ClassReaderSource classSource, String clsName, MethodDescriptor desc) {
|
||||
|
@ -126,15 +153,18 @@ public class JavaScriptBodyDependency implements DependencyListener {
|
|||
private class GeneratorJsCallback extends JsCallback {
|
||||
private DependencyAgent agent;
|
||||
private MethodDependency caller;
|
||||
public GeneratorJsCallback(DependencyAgent agent, MethodDependency caller) {
|
||||
private CallLocation location;
|
||||
public GeneratorJsCallback(DependencyAgent agent, MethodDependency caller, CallLocation location) {
|
||||
this.agent = agent;
|
||||
this.caller = caller;
|
||||
this.location = location;
|
||||
}
|
||||
@Override protected CharSequence callMethod(String ident, String fqn, String method, String params) {
|
||||
MethodDescriptor desc = MethodDescriptor.parse(method + params + "V");
|
||||
MethodReader reader = findMethod(agent.getClassSource(), fqn, desc);
|
||||
MethodReference ref = reader != null ? reader.getReference() : new MethodReference(fqn, desc);
|
||||
MethodDependency methodDep = agent.linkMethod(ref, null);
|
||||
MethodDependency methodDep = agent.linkMethod(ref, location);
|
||||
achievedMethods.get(caller.getReference()).add(ref);
|
||||
if (!methodDep.isMissing()) {
|
||||
if (reader.hasModifier(ElementModifier.STATIC) || reader.hasModifier(ElementModifier.FINAL)) {
|
||||
methodDep.use();
|
||||
|
@ -154,8 +184,7 @@ public class JavaScriptBodyDependency implements DependencyListener {
|
|||
private MethodReader superMethod;
|
||||
private ClassReader superClass;
|
||||
private MethodDependency caller;
|
||||
public VirtualCallbackConsumer(DependencyAgent agent, MethodReader superMethod,
|
||||
MethodDependency caller) {
|
||||
public VirtualCallbackConsumer(DependencyAgent agent, MethodReader superMethod, MethodDependency caller) {
|
||||
this.agent = agent;
|
||||
this.superMethod = superMethod;
|
||||
this.caller = caller;
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.teavm.javascript.ast.Expr;
|
|||
import org.teavm.javascript.ast.InvocationExpr;
|
||||
import org.teavm.javascript.ni.Injector;
|
||||
import org.teavm.javascript.ni.InjectorContext;
|
||||
import org.teavm.model.CallLocation;
|
||||
import org.teavm.model.ClassReader;
|
||||
import org.teavm.model.MethodReader;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
@ -112,7 +113,8 @@ public class JSNativeGenerator implements Injector, DependencyPlugin {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void methodAchieved(final DependencyAgent agent, final MethodDependency method) {
|
||||
public void methodAchieved(final DependencyAgent agent, final MethodDependency method,
|
||||
final CallLocation location) {
|
||||
switch (method.getReference().getName()) {
|
||||
case "invoke":
|
||||
case "instantiate":
|
||||
|
@ -120,7 +122,7 @@ public class JSNativeGenerator implements Injector, DependencyPlugin {
|
|||
for (int i = 0; i < method.getReference().parameterCount(); ++i) {
|
||||
method.getVariable(i).addConsumer(new DependencyConsumer() {
|
||||
@Override public void consume(DependencyAgentType type) {
|
||||
achieveFunctorMethods(agent, type.getName(), method);
|
||||
achieveFunctorMethods(agent, type.getName(), method, location);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -131,14 +133,15 @@ public class JSNativeGenerator implements Injector, DependencyPlugin {
|
|||
}
|
||||
}
|
||||
|
||||
private void achieveFunctorMethods(DependencyAgent agent, String type, MethodDependency caller) {
|
||||
private void achieveFunctorMethods(DependencyAgent agent, String type, MethodDependency caller,
|
||||
CallLocation location) {
|
||||
if (caller.isMissing()) {
|
||||
return;
|
||||
}
|
||||
ClassReader cls = agent.getClassSource().get(type);
|
||||
if (cls != null) {
|
||||
for (MethodReader method : cls.getMethods()) {
|
||||
agent.linkMethod(method.getReference(), null).use();
|
||||
agent.linkMethod(method.getReference(), location).use();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import org.teavm.dependency.DependencyAgent;
|
|||
import org.teavm.dependency.DependencyListener;
|
||||
import org.teavm.dependency.FieldDependency;
|
||||
import org.teavm.dependency.MethodDependency;
|
||||
import org.teavm.model.CallLocation;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -30,11 +31,11 @@ class ResourceAccessorDependencyListener implements DependencyListener {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void classAchieved(DependencyAgent agent, String className) {
|
||||
public void classAchieved(DependencyAgent agent, String className, CallLocation location) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void methodAchieved(DependencyAgent agent, MethodDependency method) {
|
||||
public void methodAchieved(DependencyAgent agent, MethodDependency method, CallLocation location) {
|
||||
switch (method.getReference().getName()) {
|
||||
case "castToString":
|
||||
method.getResult().propagate(agent.getType("java.lang.String"));
|
||||
|
@ -43,6 +44,6 @@ class ResourceAccessorDependencyListener implements DependencyListener {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void fieldAchieved(DependencyAgent agent, FieldDependency field) {
|
||||
public void fieldAchieved(DependencyAgent agent, FieldDependency field, CallLocation location) {
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user