From 62b3c68a5bccafa1816c2de1a57b9254b9dc0394 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Sat, 22 Jun 2019 23:30:05 +0300 Subject: [PATCH] Don't report compile-0time error when there's possible way to reach suspension point. Generate runtime error instead. --- .../org/teavm/classlib/java/lang/TObject.java | 5 -- .../util/concurrent/TArrayBlockingQueue.java | 3 -- .../teavm/model/util/AsyncMethodFinder.java | 18 -------- .../org/teavm/backend/javascript/thread.js | 6 ++- .../org/teavm/interop/SuppressSyncErrors.java | 1 + .../src/main/java/org/teavm/interop/Sync.java | 1 + .../org/teavm/jso/impl/JSClassProcessor.java | 46 ------------------- .../jso/impl/JSObjectClassTransformer.java | 5 -- 8 files changed, 7 insertions(+), 78 deletions(-) diff --git a/classlib/src/main/java/org/teavm/classlib/java/lang/TObject.java b/classlib/src/main/java/org/teavm/classlib/java/lang/TObject.java index 376469c35..e14c0973e 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/lang/TObject.java +++ b/classlib/src/main/java/org/teavm/classlib/java/lang/TObject.java @@ -25,7 +25,6 @@ import org.teavm.interop.NoSideEffects; import org.teavm.interop.Rename; import org.teavm.interop.Structure; import org.teavm.interop.Superclass; -import org.teavm.interop.Sync; import org.teavm.interop.Unmanaged; import org.teavm.jso.browser.TimerHandler; import org.teavm.platform.Platform; @@ -141,12 +140,10 @@ public class TObject { }); } - @Sync static void monitorExit(TObject o) { monitorExit(o, 1); } - @Sync static void monitorExit(TObject o, int count) { if (o.isEmptyMonitor() || o.monitor.owner != TThread.currentThread()) { throw new TIllegalMonitorStateException(); @@ -353,7 +350,6 @@ public class TObject { return copy; } - @Sync @Rename("notify") public final void notify0() { if (!holdsLock(this)) { @@ -379,7 +375,6 @@ public class TObject { } } - @Sync @Rename("notifyAll") public final void notifyAll0() { if (!holdsLock(this)) { diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/concurrent/TArrayBlockingQueue.java b/classlib/src/main/java/org/teavm/classlib/java/util/concurrent/TArrayBlockingQueue.java index 5f552d8bc..80ceb11e7 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/util/concurrent/TArrayBlockingQueue.java +++ b/classlib/src/main/java/org/teavm/classlib/java/util/concurrent/TArrayBlockingQueue.java @@ -29,7 +29,6 @@ import org.teavm.classlib.java.util.TCollection; import org.teavm.classlib.java.util.TIterator; import org.teavm.interop.Async; import org.teavm.interop.AsyncCallback; -import org.teavm.interop.Sync; import org.teavm.platform.Platform; import org.teavm.platform.PlatformQueue; import org.teavm.platform.PlatformRunnable; @@ -392,7 +391,6 @@ public class TArrayBlockingQueue extends TAbstractQueue implements TBlocki } } - @Sync private void addImpl(E e) { array[tail++] = e; if (tail == array.length) { @@ -401,7 +399,6 @@ public class TArrayBlockingQueue extends TAbstractQueue implements TBlocki notifyChange(); } - @Sync private E removeImpl() { @SuppressWarnings("unchecked") E result = (E) array[head]; diff --git a/core/src/main/java/org/teavm/model/util/AsyncMethodFinder.java b/core/src/main/java/org/teavm/model/util/AsyncMethodFinder.java index 03360bdd1..02cd66156 100644 --- a/core/src/main/java/org/teavm/model/util/AsyncMethodFinder.java +++ b/core/src/main/java/org/teavm/model/util/AsyncMethodFinder.java @@ -22,15 +22,11 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; -import org.teavm.backend.javascript.spi.InjectedBy; import org.teavm.callgraph.CallGraph; import org.teavm.callgraph.CallGraphNode; import org.teavm.callgraph.CallSite; import org.teavm.diagnostics.Diagnostics; import org.teavm.interop.Async; -import org.teavm.interop.SuppressSyncErrors; -import org.teavm.interop.Sync; -import org.teavm.model.CallLocation; import org.teavm.model.ClassReader; import org.teavm.model.ElementModifier; import org.teavm.model.ListableClassReaderSource; @@ -162,20 +158,6 @@ public class AsyncMethodFinder { if (method == null) { return; } - if (method.getAnnotations().get(Sync.class.getName()) != null - || method.getAnnotations().get(InjectedBy.class.getName()) != null) { - if (method.getAnnotations().get(SuppressSyncErrors.class.getName()) == null) { - diagnostics.error(new CallLocation(methodRef), "Method {{m0}} is claimed to be " - + "synchronous, but it is has invocations of asynchronous methods:" - + stack.toString(), methodRef); - return; - } else { - diagnostics.warning(new CallLocation(methodRef), "Error as Warning because " - + " Method {{m0}} has @SuppressSyncErrors annotation. Method {{m0}} " - + "is claimed to be synchronous, but it is has invocations of " - + "asynchronous methods:" + stack.toString(), methodRef); - } - } if (!hasAsyncMethods && methodRef.getClassName().equals("java.lang.Object") && (methodRef.getName().equals("monitorEnter") || methodRef.getName().equals("monitorExit"))) { diff --git a/core/src/main/resources/org/teavm/backend/javascript/thread.js b/core/src/main/resources/org/teavm/backend/javascript/thread.js index 8666667b8..d30e9b27a 100644 --- a/core/src/main/resources/org/teavm/backend/javascript/thread.js +++ b/core/src/main/resources/org/teavm/backend/javascript/thread.js @@ -97,7 +97,11 @@ function $rt_resuming() { return thread != null && thread.isResuming(); } function $rt_suspend(callback) { - return $rt_nativeThread().suspend(callback); + var nativeThread = $rt_nativeThread(); + if (nativeThread === null) { + throw new Error("Suspension point reached from non-threading context (perhaps, from native JS method)."); + } + return nativeThread.suspend(callback); } function $rt_startThread(runner, callback) { new TeaVMThread(runner).start(callback); diff --git a/interop/core/src/main/java/org/teavm/interop/SuppressSyncErrors.java b/interop/core/src/main/java/org/teavm/interop/SuppressSyncErrors.java index c20bf710a..cbf7dcfd8 100644 --- a/interop/core/src/main/java/org/teavm/interop/SuppressSyncErrors.java +++ b/interop/core/src/main/java/org/teavm/interop/SuppressSyncErrors.java @@ -23,6 +23,7 @@ import java.lang.annotation.*; */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) +@Deprecated public @interface SuppressSyncErrors { } diff --git a/interop/core/src/main/java/org/teavm/interop/Sync.java b/interop/core/src/main/java/org/teavm/interop/Sync.java index 99afd45f9..35ba03cd9 100644 --- a/interop/core/src/main/java/org/teavm/interop/Sync.java +++ b/interop/core/src/main/java/org/teavm/interop/Sync.java @@ -20,5 +20,6 @@ import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Inherited +@Deprecated public @interface Sync { } diff --git a/jso/impl/src/main/java/org/teavm/jso/impl/JSClassProcessor.java b/jso/impl/src/main/java/org/teavm/jso/impl/JSClassProcessor.java index c111a561b..be89a2651 100644 --- a/jso/impl/src/main/java/org/teavm/jso/impl/JSClassProcessor.java +++ b/jso/impl/src/main/java/org/teavm/jso/impl/JSClassProcessor.java @@ -33,7 +33,6 @@ import org.teavm.backend.javascript.rendering.JSParser; import org.teavm.cache.IncrementalDependencyRegistration; import org.teavm.diagnostics.Diagnostics; import org.teavm.interop.NoSideEffects; -import org.teavm.interop.Sync; import org.teavm.jso.JSBody; import org.teavm.jso.JSByRef; import org.teavm.jso.JSFunctor; @@ -41,7 +40,6 @@ import org.teavm.jso.JSIndexer; import org.teavm.jso.JSMethod; import org.teavm.jso.JSObject; import org.teavm.jso.JSProperty; -import org.teavm.model.AccessLevel; import org.teavm.model.AnnotationContainerReader; import org.teavm.model.AnnotationHolder; import org.teavm.model.AnnotationReader; @@ -191,50 +189,6 @@ class JSClassProcessor { .orElse(null); } - void makeSync(ClassHolder cls) { - Set methods = new HashSet<>(); - findInheritedMethods(cls, methods, new HashSet<>()); - for (MethodHolder method : cls.getMethods()) { - if (methods.contains(method.getDescriptor())) { - makeSync(method); - } - } - } - - static void makeSync(MethodHolder method) { - if (method.getAnnotations().get(Sync.class.getName()) == null) { - AnnotationHolder annot = new AnnotationHolder(Sync.class.getName()); - method.getAnnotations().add(annot); - } - } - - private void findInheritedMethods(ClassReader cls, Set methods, Set visited) { - if (!visited.add(cls.getName())) { - return; - } - if (typeHelper.isJavaScriptClass(cls.getName())) { - for (MethodReader method : cls.getMethods()) { - if (!method.hasModifier(ElementModifier.STATIC) && !method.hasModifier(ElementModifier.FINAL) - && method.getLevel() != AccessLevel.PRIVATE) { - methods.add(method.getDescriptor()); - } - } - } else if (typeHelper.isJavaScriptImplementation(cls.getName())) { - if (cls.getParent() != null) { - ClassReader parentCls = classSource.get(cls.getParent()); - if (parentCls != null) { - findInheritedMethods(parentCls, methods, visited); - } - } - for (String iface : cls.getInterfaces()) { - ClassReader parentCls = classSource.get(iface); - if (parentCls != null) { - findInheritedMethods(parentCls, methods, visited); - } - } - } - } - private static ValueType[] getStaticSignature(MethodReference method) { ValueType[] signature = method.getSignature(); ValueType[] staticSignature = new ValueType[signature.length + 1]; diff --git a/jso/impl/src/main/java/org/teavm/jso/impl/JSObjectClassTransformer.java b/jso/impl/src/main/java/org/teavm/jso/impl/JSObjectClassTransformer.java index 5e4ab6b3d..53de5b5c2 100644 --- a/jso/impl/src/main/java/org/teavm/jso/impl/JSObjectClassTransformer.java +++ b/jso/impl/src/main/java/org/teavm/jso/impl/JSObjectClassTransformer.java @@ -73,9 +73,6 @@ class JSObjectClassTransformer implements ClassHolderTransformer { if (typeHelper.isJavaScriptClass(cls.getName())) { processor.processMemberMethods(cls); } - if (typeHelper.isJavaScriptImplementation(cls.getName())) { - processor.makeSync(cls); - } for (MethodHolder method : cls.getMethods().toArray(new MethodHolder[0])) { if (method.getProgram() != null) { @@ -156,8 +153,6 @@ class JSObjectClassTransformer implements ClassHolderTransformer { basicBlock.add(exit); classHolder.addMethod(exportedMethod); - MethodHolder methodToCall = classHolder.getMethod(method); - JSClassProcessor.makeSync(methodToCall != null ? methodToCall : exportedMethod); String publicAlias = classToExpose.methods.get(method); AnnotationHolder annot = new AnnotationHolder(JSMethodToExpose.class.getName());