diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TObject.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TObject.java index 8e11c9aff..71526720b 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TObject.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TObject.java @@ -124,7 +124,8 @@ public class TObject { } @Rename("notify") - public final void notify0(){ + public final void notify0() { + TThread thread = TThread.currentThread(); if (notifyListeners != null) { while (notifyListeners.getLength() > 0 && notifyListeners.shift().handleNotify()) { // repeat loop @@ -133,6 +134,7 @@ public class TObject { notifyListeners = null; } } + TThread.setCurrentThread(thread); } @Rename("notifyAll") @@ -167,8 +169,7 @@ public class TObject { if (notifyListeners == null) { notifyListeners = window.newArray(); } - final TThread currentThread = TThread.currentThread(); - final NotifyListenerImpl listener = new NotifyListenerImpl(callback, currentThread); + final NotifyListenerImpl listener = new NotifyListenerImpl(callback); notifyListeners.push(listener); if (timeout == 0 && nanos == 0) { return; @@ -178,13 +179,12 @@ public class TObject { private static class NotifyListenerImpl implements NotifyListener, TimerHandler { final AsyncCallback callback; - final TThread currentThread; + final TThread currentThread = TThread.currentThread(); int timerId = -1; boolean finished; - public NotifyListenerImpl(AsyncCallback callback, TThread currentThread) { + public NotifyListenerImpl(AsyncCallback callback) { this.callback = callback; - this.currentThread = currentThread; } @Override diff --git a/teavm-core/src/main/java/org/teavm/tooling/TeaVMTool.java b/teavm-core/src/main/java/org/teavm/tooling/TeaVMTool.java index 2e432347b..846b94f33 100644 --- a/teavm-core/src/main/java/org/teavm/tooling/TeaVMTool.java +++ b/teavm-core/src/main/java/org/teavm/tooling/TeaVMTool.java @@ -264,7 +264,9 @@ public class TeaVMTool { if (mainClass != null) { MethodDescriptor mainMethodDesc = new MethodDescriptor("main", String[].class, void.class); vm.entryPoint("main", new MethodReference(mainClass, mainMethodDesc)) - .withValue(1, "java.lang.String").async(); + .withValue(1, "[java.lang.String") + .withArrayValue(1, "java.lang.String") + .async(); } for (ClassAlias alias : classAliases) { vm.exportType(alias.getAlias(), alias.getClassName()); @@ -300,7 +302,7 @@ public class TeaVMTool { return; } if (mainClass != null) { - writer.append("main = $rt_rootInvocationAdapter(main);\n"); + writer.append("main = $rt_mainWrapper(main);\n"); } ProblemProvider problemProvider = vm.getProblemProvider(); if (problemProvider.getProblems().isEmpty()) { diff --git a/teavm-core/src/main/java/org/teavm/vm/TeaVM.java b/teavm-core/src/main/java/org/teavm/vm/TeaVM.java index 8b8258e59..d451337b7 100644 --- a/teavm-core/src/main/java/org/teavm/vm/TeaVM.java +++ b/teavm-core/src/main/java/org/teavm/vm/TeaVM.java @@ -431,28 +431,6 @@ public class TeaVM implements TeaVMHost, ServiceRepository { listener.begin(renderer, target); } sourceWriter.append("\"use strict\";").newLine(); - - - // Keep track of current running thread by overriding setTimeout - sourceWriter.append("function $rt_setTimeout(f,interval){").indent().softNewLine(); - MethodReference currentThreadRef = new MethodReference( - Thread.class, "currentThread", Thread.class); - MethodReference setCurrentThreadRef = new MethodReference( - Thread.class, "setCurrentThread", Thread.class, void.class); - MethodReference getMainThreadRef = new MethodReference(Thread.class, "getMainThread", Thread.class); - - sourceWriter.append("var currThread = ").appendMethodBody(currentThreadRef).append("();").softNewLine(); - sourceWriter.append("var callback = function(){").indent().softNewLine(); - sourceWriter.appendMethodBody(setCurrentThreadRef).append("(currThread);").softNewLine(); - sourceWriter.append("try{f();} finally {").softNewLine(); - sourceWriter.appendMethodBody(setCurrentThreadRef).append("("). - appendMethodBody(getMainThreadRef).append("());}").softNewLine(); - sourceWriter.outdent().append("};").softNewLine(); - sourceWriter.append("setTimeout(callback, interval);").softNewLine(); - sourceWriter.outdent().append("};").softNewLine(); - - // END Thread stuff - renderer.renderRuntime(); renderer.render(clsNodes); renderer.renderStringPool(); diff --git a/teavm-core/src/main/java/org/teavm/vm/TeaVMEntryPoint.java b/teavm-core/src/main/java/org/teavm/vm/TeaVMEntryPoint.java index bcd0cf12e..70375fafa 100644 --- a/teavm-core/src/main/java/org/teavm/vm/TeaVMEntryPoint.java +++ b/teavm-core/src/main/java/org/teavm/vm/TeaVMEntryPoint.java @@ -97,6 +97,14 @@ public class TeaVMEntryPoint { return this; } + public TeaVMEntryPoint withArrayValue(int argument, String type) { + if (argument > reference.parameterCount()) { + throw new IllegalArgumentException("Illegal argument #" + argument + " of " + reference.parameterCount()); + } + method.getVariable(argument).getArrayItem().propagate(method.getDependencyAgent().getType(type)); + return this; + } + public TeaVMEntryPoint async() { this.async = true; return this; diff --git a/teavm-core/src/main/resources/org/teavm/javascript/runtime.js b/teavm-core/src/main/resources/org/teavm/javascript/runtime.js index 66c7691ee..35544d4de 100644 --- a/teavm-core/src/main/resources/org/teavm/javascript/runtime.js +++ b/teavm-core/src/main/resources/org/teavm/javascript/runtime.js @@ -481,6 +481,18 @@ function $rt_rootInvocationAdapter(f) { return f.apply(this, args); } } +function $rt_mainWrapper(f) { + return function(args) { + if (!args) { + args = []; + } + var javaArgs = $rt_createArray($rt_objcls(), args.length); + for (var i = 0; i < args.length; ++i) { + javaArgs.data[i] = $rt_str(args[i]); + } + $rt_rootInvocationAdapter(f)(javaArgs); + }; +} var $rt_stringPool_instance; function $rt_stringPool(strings) { $rt_stringPool_instance = new Array(strings.length); diff --git a/teavm-samples/teavm-samples-async/nb-configuration.xml b/teavm-samples/teavm-samples-async/nb-configuration.xml deleted file mode 100644 index 792bc673f..000000000 --- a/teavm-samples/teavm-samples-async/nb-configuration.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - maven - gfv3ee6 - - diff --git a/teavm-samples/teavm-samples-async/nbactions.xml b/teavm-samples/teavm-samples-async/nbactions.xml deleted file mode 100644 index 35d636f69..000000000 --- a/teavm-samples/teavm-samples-async/nbactions.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - build - - * - - - install - - - true - maven - - - - diff --git a/teavm-samples/teavm-samples-async/src/main/java/org/teavm/samples/async/AsyncProgram.java b/teavm-samples/teavm-samples-async/src/main/java/org/teavm/samples/async/AsyncProgram.java index 955129369..8264ea2e6 100644 --- a/teavm-samples/teavm-samples-async/src/main/java/org/teavm/samples/async/AsyncProgram.java +++ b/teavm-samples/teavm-samples-async/src/main/java/org/teavm/samples/async/AsyncProgram.java @@ -15,20 +15,25 @@ */ package org.teavm.samples.async; +import java.util.Arrays; + /** * * @author Alexey Andreev */ public final class AsyncProgram { + private static long start = System.currentTimeMillis(); + private AsyncProgram() { } public static void main(String[] args) throws InterruptedException { + report(Arrays.toString(args)); withoutAsync(); - System.out.println(); + report(""); withAsync(); - System.out.println(); + report(""); final Object lock = new Object(); Thread t = new Thread(new Runnable() { @Override @@ -36,7 +41,7 @@ public final class AsyncProgram { try { doRun(lock); } catch (InterruptedException ex) { - System.out.println(ex.getMessage()); + report("Exception caught: " + ex.getMessage()); } } @@ -49,82 +54,87 @@ public final class AsyncProgram { try { doRun(lock); } catch (InterruptedException ex) { - System.out.println(ex.getMessage()); + report("Exception caught: " + ex.getMessage()); } } }, "Test Thread 2"); t2.start(); - System.out.println("Should be main -> Current thread is " + Thread.currentThread().getName()); - System.out.println("Now trying wait..."); + report("Should be main"); + report("Now trying wait..."); - lock.wait(20000); - System.out.println("Finished waiting"); + synchronized (lock) { + lock.wait(20000); + } + report("Finished main thread"); + } + private static void report(String message) { + long current = System.currentTimeMillis() - start; + System.out.println("[" + Thread.currentThread().getName() + "]/" + current + ": " + message); } private static void doRun(Object lock) throws InterruptedException { - System.out.println("Current thread is " + Thread.currentThread().getName()); - System.out.println("Executing timer task"); + report("Executing timer task"); Thread.sleep(2000); - System.out.println("Current thread is " + Thread.currentThread().getName()); - System.out.println("Calling lock.notify()"); - lock.notify(); - System.out.println("Current thread is " + Thread.currentThread().getName()); - System.out.println("Finished calling lock.notify()"); + report("Calling lock.notify()"); + synchronized (lock) { + lock.notify(); + } + report("Finished calling lock.notify()"); + report("Waiting 5 seconds"); Thread.sleep(5000); - System.out.println("Current thread is " + Thread.currentThread().getName()); - System.out.println("Finished another 5 second sleep"); + report("Finished another 5 second sleep"); synchronized (lock) { - System.out.println("Inside locked section of thread " + Thread.currentThread().getName()); + report("Sleep inside locked section"); Thread.sleep(2000); - System.out.println("Finished locked section of thread " + Thread.currentThread().getName()); + report("Finished locked section"); } } private static void withoutAsync() { - System.out.println("Start sync"); + report("Start sync"); for (int i = 0; i < 20; ++i) { + StringBuilder sb = new StringBuilder(); for (int j = 0; j <= i; ++j) { - System.out.print(j); - System.out.print(' '); + sb.append(j); + sb.append(' '); } - System.out.println(); + report(sb.toString()); } - System.out.println("Complete sync"); + report("Complete sync"); } private static void withAsync() throws InterruptedException { - System.out.println("Start async"); + report("Start async"); for (int i = 0; i < 20; ++i) { + StringBuilder sb = new StringBuilder(); for (int j = 0; j <= i; ++j) { - System.out.print(j); - System.out.print(' '); + sb.append(j); + sb.append(' '); } - System.out.println(); + report(sb.toString()); if (i % 3 == 0) { - System.out.println("Suspend for a second"); + report("Suspend for a second"); Thread.sleep(1000); } } - System.out.println("2nd Thread.sleep in same method"); + report("2nd Thread.sleep in same method"); Thread.sleep(1000); - System.out.println("Complete async"); - - System.out.println("Throwing exception"); + report("Throwing exception"); try { throwException(); } catch (IllegalStateException e) { - System.out.println("Exception caught"); + report("Exception caught"); } + report("Complete async"); } private static void throwException() { Thread.yield(); - System.out.println("Thread.yield called"); + report("Thread.yield called"); throw new IllegalStateException(); } - } diff --git a/teavm-samples/teavm-samples-async/src/main/webapp/index.html b/teavm-samples/teavm-samples-async/src/main/webapp/index.html index 9f7151523..96817c4a0 100644 --- a/teavm-samples/teavm-samples-async/src/main/webapp/index.html +++ b/teavm-samples/teavm-samples-async/src/main/webapp/index.html @@ -21,7 +21,7 @@ - +

Please, open developer's console to view program's output

\ No newline at end of file