JS: fix async methods

This commit is contained in:
Alexey Andreev 2021-03-22 13:52:16 +03:00
parent d6780ea637
commit 38cbd7e80b
3 changed files with 16 additions and 10 deletions

View File

@ -330,7 +330,8 @@ public class CTarget implements TeaVMTarget, TeaVMCHost {
@Override @Override
public void analyzeBeforeOptimizations(ListableClassReaderSource classSource) { public void analyzeBeforeOptimizations(ListableClassReaderSource classSource) {
AsyncMethodFinder asyncFinder = new AsyncMethodFinder(controller.getDependencyInfo().getCallGraph()); AsyncMethodFinder asyncFinder = new AsyncMethodFinder(controller.getDependencyInfo().getCallGraph(),
controller.getDependencyInfo());
asyncFinder.find(classSource); asyncFinder.find(classSource);
asyncMethods = new HashSet<>(asyncFinder.getAsyncMethods()); asyncMethods = new HashSet<>(asyncFinder.getAsyncMethods());
asyncMethods.addAll(asyncFinder.getAsyncFamilyMethods()); asyncMethods.addAll(asyncFinder.getAsyncFamilyMethods());

View File

@ -494,7 +494,8 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
} }
private List<PreparedClass> modelToAst(ListableClassHolderSource classes) { private List<PreparedClass> modelToAst(ListableClassHolderSource classes) {
AsyncMethodFinder asyncFinder = new AsyncMethodFinder(controller.getDependencyInfo().getCallGraph()); AsyncMethodFinder asyncFinder = new AsyncMethodFinder(controller.getDependencyInfo().getCallGraph(),
controller.getDependencyInfo());
asyncFinder.find(classes); asyncFinder.find(classes);
asyncMethods.addAll(asyncFinder.getAsyncMethods()); asyncMethods.addAll(asyncFinder.getAsyncMethods());
asyncFamilyMethods.addAll(asyncFinder.getAsyncFamilyMethods()); asyncFamilyMethods.addAll(asyncFinder.getAsyncFamilyMethods());

View File

@ -25,6 +25,7 @@ import java.util.Set;
import org.teavm.callgraph.CallGraph; import org.teavm.callgraph.CallGraph;
import org.teavm.callgraph.CallGraphNode; import org.teavm.callgraph.CallGraphNode;
import org.teavm.callgraph.CallSite; import org.teavm.callgraph.CallSite;
import org.teavm.dependency.DependencyInfo;
import org.teavm.interop.Async; import org.teavm.interop.Async;
import org.teavm.model.ClassReader; import org.teavm.model.ClassReader;
import org.teavm.model.ElementModifier; import org.teavm.model.ElementModifier;
@ -39,6 +40,7 @@ import org.teavm.runtime.Fiber;
public class AsyncMethodFinder { public class AsyncMethodFinder {
private Set<MethodReference> asyncMethods = new HashSet<>(); private Set<MethodReference> asyncMethods = new HashSet<>();
private DependencyInfo dependency;
private Map<MethodReference, Boolean> asyncFamilyMethods = new HashMap<>(); private Map<MethodReference, Boolean> asyncFamilyMethods = new HashMap<>();
private Set<MethodReference> readonlyAsyncMethods = Collections.unmodifiableSet(asyncMethods); private Set<MethodReference> readonlyAsyncMethods = Collections.unmodifiableSet(asyncMethods);
private Set<MethodReference> readonlyAsyncFamilyMethods = Collections.unmodifiableSet(asyncFamilyMethods.keySet()); private Set<MethodReference> readonlyAsyncFamilyMethods = Collections.unmodifiableSet(asyncFamilyMethods.keySet());
@ -46,8 +48,9 @@ public class AsyncMethodFinder {
private ListableClassReaderSource classSource; private ListableClassReaderSource classSource;
private boolean hasAsyncMethods; private boolean hasAsyncMethods;
public AsyncMethodFinder(CallGraph callGraph) { public AsyncMethodFinder(CallGraph callGraph, DependencyInfo dependency) {
this.callGraph = callGraph; this.callGraph = callGraph;
this.dependency = dependency;
} }
public Set<MethodReference> getAsyncMethods() { public Set<MethodReference> getAsyncMethods() {
@ -64,7 +67,8 @@ public class AsyncMethodFinder {
for (String clsName : classSource.getClassNames()) { for (String clsName : classSource.getClassNames()) {
ClassReader cls = classSource.get(clsName); ClassReader cls = classSource.get(clsName);
for (MethodReader method : cls.getMethods()) { for (MethodReader method : cls.getMethods()) {
if (asyncMethods.contains(method.getReference())) { if (!dependency.getReachableMethods().contains(method.getReference())
|| asyncMethods.contains(method.getReference())) {
continue; continue;
} }
if (method.getAnnotations().get(Async.class.getName()) != null) { if (method.getAnnotations().get(Async.class.getName()) != null) {
@ -76,7 +80,8 @@ public class AsyncMethodFinder {
for (String clsName : classSource.getClassNames()) { for (String clsName : classSource.getClassNames()) {
ClassReader cls = classSource.get(clsName); ClassReader cls = classSource.get(clsName);
for (MethodReader method : cls.getMethods()) { for (MethodReader method : cls.getMethods()) {
if (asyncMethods.contains(method.getReference()) || method.getProgram() == null) { if (!dependency.getReachableMethods().contains(method.getReference())
|| asyncMethods.contains(method.getReference()) || method.getProgram() == null) {
continue; continue;
} }
if (hasMonitor(method)) { if (hasMonitor(method)) {
@ -115,9 +120,9 @@ public class AsyncMethodFinder {
} }
} }
} }
ClassReader cls = classSource.get("java.lang.Thread"); boolean hasThreads = dependency.getReachableMethods().contains(new MethodReference(
MethodReader method = cls != null ? cls.getMethod(new MethodDescriptor("start", void.class)) : null; Thread.class, "start", void.class));
return result && method != null; return result && hasThreads;
} }
public boolean hasAsyncMethods() { public boolean hasAsyncMethods() {
@ -161,8 +166,7 @@ public class AsyncMethodFinder {
} }
if (!hasAsyncMethods && methodRef.getClassName().equals("java.lang.Object") if (!hasAsyncMethods && methodRef.getClassName().equals("java.lang.Object")
&& (methodRef.getName().equals("monitorEnter") || methodRef.getName().equals("monitorExit")) && (methodRef.getName().equals("monitorEnter") || methodRef.getName().equals("monitorExit"))) {
&& methodRef.parameterCount() == 0) {
return; return;
} }
for (CallSite callSite : node.getCallerCallSites()) { for (CallSite callSite : node.getCallerCallSites()) {