First working prototype of new async

This commit is contained in:
konsoletyper 2015-03-10 22:09:43 +03:00
parent 56c5fefae4
commit 8fe3876641
8 changed files with 46 additions and 28 deletions

View File

@ -91,6 +91,13 @@ public class TObject {
static void monitorEnterWait(final TObject o, final int count, final AsyncCallback<Void> callback) { static void monitorEnterWait(final TObject o, final int count, final AsyncCallback<Void> callback) {
final TThread thread = TThread.currentThread(); final TThread thread = TThread.currentThread();
if (o.monitor == null) {
o.monitor = new Monitor();
TThread.setCurrentThread(thread);
o.monitor.count += count;
callback.complete(null);
return;
}
o.monitor.enteringThreads.add(new PlatformRunnable() { o.monitor.enteringThreads.add(new PlatformRunnable() {
@Override public void run() { @Override public void run() {
TThread.setCurrentThread(thread); TThread.setCurrentThread(thread);
@ -118,7 +125,7 @@ public class TObject {
o.monitor.owner = null; o.monitor.owner = null;
if (!o.monitor.enteringThreads.isEmpty()) { if (!o.monitor.enteringThreads.isEmpty()) {
Platform.startThread(new PlatformRunnable() { Platform.postpone(new PlatformRunnable() {
@Override public void run() { @Override public void run() {
if (o.isEmptyMonitor() || o.monitor.owner != null) { if (o.isEmptyMonitor() || o.monitor.owner != null) {
return; return;
@ -127,7 +134,7 @@ public class TObject {
o.monitor.enteringThreads.remove().run(); o.monitor.enteringThreads.remove().run();
} }
} }
}, false); });
} else { } else {
o.isEmptyMonitor(); o.isEmptyMonitor();
} }
@ -203,7 +210,7 @@ public class TObject {
while (!listeners.isEmpty()) { while (!listeners.isEmpty()) {
NotifyListener listener = listeners.remove(); NotifyListener listener = listeners.remove();
if (!listener.expired()) { if (!listener.expired()) {
Platform.startThread(listener, false); Platform.postpone(listener);
break; break;
} }
} }
@ -219,7 +226,7 @@ public class TObject {
while (!listeners.isEmpty()) { while (!listeners.isEmpty()) {
NotifyListener listener = listeners.remove(); NotifyListener listener = listeners.remove();
if (!listener.expired()) { if (!listener.expired()) {
Platform.startThread(listener, false); Platform.postpone(listener);
} }
} }
} }
@ -279,7 +286,7 @@ public class TObject {
@Override @Override
public void onTimer() { public void onTimer() {
if (!expired()) { if (!expired()) {
Platform.startThread(this, false); Platform.postpone(this);
} }
} }

View File

@ -71,14 +71,14 @@ public class TThread extends TObject implements TRunnable {
setCurrentThread(mainThread); setCurrentThread(mainThread);
} }
} }
}, true); });
} }
static void setCurrentThread(TThread thread) { static void setCurrentThread(TThread thread) {
if (currentThread != thread) { if (currentThread != thread) {
currentThread = thread; currentThread = thread;
currentThread.timeSliceStart = System.currentTimeMillis();
} }
currentThread.timeSliceStart = System.currentTimeMillis();
} }
static TThread getMainThread(){ static TThread getMainThread(){
@ -102,24 +102,20 @@ public class TThread extends TObject implements TRunnable {
public static void yield() { public static void yield() {
if (currentThread.timeSliceStart + 100 < System.currentTimeMillis()) { if (currentThread.timeSliceStart + 100 < System.currentTimeMillis()) {
switchContext(); switchContext(currentThread);
} }
} }
@Async @Async
static native void switchContext(); static native void switchContext(TThread thread);
private static void switchContext(final AsyncCallback<Void> callback) { private static void switchContext(final TThread thread, final AsyncCallback<Void> callback) {
final TThread thread = currentThread(); Platform.postpone(new PlatformRunnable() {
Platform.startThread(new PlatformRunnable() {
@Override public void run() { @Override public void run() {
setCurrentThread(thread); setCurrentThread(thread);
callback.complete(null); callback.complete(null);
} }
}, false); });
}
private static void yieldImpl() {
} }
public void interrupt() { public void interrupt() {

View File

@ -204,7 +204,8 @@ public class Decompiler {
AsyncProgramSplitter splitter = new AsyncProgramSplitter(classSource, splitMethods); AsyncProgramSplitter splitter = new AsyncProgramSplitter(classSource, splitMethods);
splitter.split(method.getProgram()); splitter.split(method.getProgram());
for (int i = 0; i < splitter.size(); ++i) { for (int i = 0; i < splitter.size(); ++i) {
AsyncMethodPart part = getRegularMethodStatement(splitter.getProgram(i), splitter.getBlockSuccessors(i)); AsyncMethodPart part = getRegularMethodStatement(splitter.getProgram(i), splitter.getBlockSuccessors(i),
i > 0);
node.getBody().add(part); node.getBody().add(part);
} }
Program program = method.getProgram(); Program program = method.getProgram();
@ -227,7 +228,7 @@ public class Decompiler {
Program program = method.getProgram(); Program program = method.getProgram();
int[] targetBlocks = new int[program.basicBlockCount()]; int[] targetBlocks = new int[program.basicBlockCount()];
Arrays.fill(targetBlocks, -1); Arrays.fill(targetBlocks, -1);
methodNode.setBody(getRegularMethodStatement(program, targetBlocks).getStatement()); methodNode.setBody(getRegularMethodStatement(program, targetBlocks, false).getStatement());
for (int i = 0; i < program.variableCount(); ++i) { for (int i = 0; i < program.variableCount(); ++i) {
methodNode.getVariables().add(program.variableAt(i).getRegister()); methodNode.getVariables().add(program.variableAt(i).getRegister());
} }
@ -242,7 +243,7 @@ public class Decompiler {
return methodNode; return methodNode;
} }
private AsyncMethodPart getRegularMethodStatement(Program program, int[] targetBlocks) { private AsyncMethodPart getRegularMethodStatement(Program program, int[] targetBlocks, boolean async) {
AsyncMethodPart result = new AsyncMethodPart(); AsyncMethodPart result = new AsyncMethodPart();
lastBlockId = 1; lastBlockId = 1;
graph = ProgramUtils.buildControlFlowGraph(program); graph = ProgramUtils.buildControlFlowGraph(program);
@ -290,6 +291,7 @@ public class Decompiler {
if (head != -1 && loopSuccessors[head] == next) { if (head != -1 && loopSuccessors[head] == next) {
next = head; next = head;
} }
boolean saved = !async;
if (node >= 0) { if (node >= 0) {
generator.currentBlock = program.basicBlockAt(node); generator.currentBlock = program.basicBlockAt(node);
int tmp = indexer.nodeAt(next); int tmp = indexer.nodeAt(next);
@ -308,8 +310,9 @@ public class Decompiler {
generator.setCurrentLocation(nodeLocation); generator.setCurrentLocation(nodeLocation);
} }
insn.acceptVisitor(generator); insn.acceptVisitor(generator);
if (j == 0 && insn instanceof InvokeInstruction) { if (insn instanceof InvokeInstruction && !saved) {
generator.statements.add(new SaveStatement()); generator.statements.add(new SaveStatement());
saved = true;
} }
} }
if (targetBlocks[node] >= 0) { if (targetBlocks[node] >= 0) {

View File

@ -711,7 +711,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
writer.append("var $T").ws().append('=').ws().append("$rt_nativeThread();").softNewLine(); writer.append("var $T").ws().append('=').ws().append("$rt_nativeThread();").softNewLine();
writer.append("$ptr").ws().append('=').ws().append("$T.pop();"); writer.append("$ptr").ws().append('=').ws().append("$T.pop();");
for (int i = variableCount - 1; i > ref.parameterCount(); --i) { for (int i = variableCount - 1; i > ref.parameterCount(); --i) {
writer.append(variableName(i)).ws().append('=').ws().append("T.pop();"); writer.append(variableName(i)).ws().append('=').ws().append("$T.pop();");
} }
writer.softNewLine(); writer.softNewLine();
writer.outdent().append("}").softNewLine(); writer.outdent().append("}").softNewLine();
@ -724,6 +724,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
part.getStatement().acceptVisitor(Renderer.this); part.getStatement().acceptVisitor(Renderer.this);
writer.outdent(); writer.outdent();
} }
writer.append("default:").ws().append("throw new Error('Invalid recorded state');").softNewLine();
writer.append("}").softNewLine(); writer.append("}").softNewLine();
writer.outdent().append("}").softNewLine(); writer.outdent().append("}").softNewLine();
} catch (IOException e) { } catch (IOException e) {

View File

@ -444,17 +444,17 @@ function TeaVMThread(runner) {
this.attribute = null; this.attribute = null;
} }
TeaVMThread.prototype.push = function(value) { TeaVMThread.prototype.push = function(value) {
this.stack.push[value]; this.stack.push(value);
return this; return this;
} }
TeaVMThread.prototype.pop = function() { TeaVMThread.prototype.pop = function() {
return this.stack.pop(); return this.stack.pop();
} }
TeaVMThread.prototype.isResuming = function() { TeaVMThread.prototype.isResuming = function() {
return this.status == 1; return this.status == 2;
} }
TeaVMThread.prototype.isSuspending = function() { TeaVMThread.prototype.isSuspending = function() {
return this.status == 2; return this.status == 1;
} }
TeaVMThread.prototype.suspend = function(callback) { TeaVMThread.prototype.suspend = function(callback) {
this.suspendCallback = callback; this.suspendCallback = callback;
@ -489,10 +489,12 @@ TeaVMThread.prototype.run = function() {
} }
} }
function $rt_suspending() { function $rt_suspending() {
return $rt_nativeThread().isSuspending(); var thread = $rt_nativeThread();
return thread != null && thread.isSuspending();
} }
function $rt_resuming() { function $rt_resuming() {
return $rt_nativeThread().isResuming(); var thread = $rt_nativeThread();
return thread != null && thread.isResuming();
} }
function $rt_suspend(callback) { function $rt_suspend(callback) {
return $rt_nativeThread().suspend(callback); return $rt_nativeThread().suspend(callback);

View File

@ -107,12 +107,16 @@ public final class Platform {
@GeneratedBy(PlatformGenerator.class) @GeneratedBy(PlatformGenerator.class)
@PluggableDependency(PlatformGenerator.class) @PluggableDependency(PlatformGenerator.class)
public static native void startThread(PlatformRunnable runnable, boolean newNativeThread); public static native void startThread(PlatformRunnable runnable);
private static void launchThread(PlatformRunnable runnable) { private static void launchThread(PlatformRunnable runnable) {
runnable.run(); runnable.run();
} }
public static void postpone(PlatformRunnable runnable) {
schedule(runnable, 0);
}
@GeneratedBy(PlatformGenerator.class) @GeneratedBy(PlatformGenerator.class)
@PluggableDependency(PlatformGenerator.class) @PluggableDependency(PlatformGenerator.class)
public static native int schedule(PlatformRunnable runnable, int timeout); public static native int schedule(PlatformRunnable runnable, int timeout);

View File

@ -40,6 +40,7 @@ public class AsyncMethodGenerator implements Generator, DependencyPlugin {
MethodReference asyncRef = getAsyncReference(methodRef); MethodReference asyncRef = getAsyncReference(methodRef);
writer.append("var thread").ws().append('=').ws().append("$rt_nativeThread();").softNewLine(); writer.append("var thread").ws().append('=').ws().append("$rt_nativeThread();").softNewLine();
writer.append("if").ws().append("(thread.isResuming())").ws().append("{").indent().softNewLine(); writer.append("if").ws().append("(thread.isResuming())").ws().append("{").indent().softNewLine();
writer.append("thread.status").ws().append("=").ws().append("0;").softNewLine();
writer.append("var result").ws().append("=").ws().append("thread.attribute;").softNewLine(); writer.append("var result").ws().append("=").ws().append("thread.attribute;").softNewLine();
writer.append("if").ws().append("(result instanceof Error)").ws().append("{").indent().softNewLine(); writer.append("if").ws().append("(result instanceof Error)").ws().append("{").indent().softNewLine();
writer.append("throw result;").softNewLine(); writer.append("throw result;").softNewLine();

View File

@ -153,7 +153,11 @@ public class PlatformGenerator implements Generator, Injector, DependencyPlugin
PlatformRunnable.class, void.class); PlatformRunnable.class, void.class);
String runnable = context.getParameterName(1); String runnable = context.getParameterName(1);
writer.append("return window.setTimeout(function()").ws().append("{").indent().softNewLine(); writer.append("return window.setTimeout(function()").ws().append("{").indent().softNewLine();
writer.append("$rt_threadStarter(").appendMethodBody(launchRef).append(")"); if (timeout) {
writer.appendMethodBody(launchRef);
} else {
writer.append("$rt_threadStarter(").appendMethodBody(launchRef).append(")");
}
writer.append("(").append(runnable).append(");").softNewLine(); writer.append("(").append(runnable).append(");").softNewLine();
writer.outdent().append("},").ws().append(timeout ? context.getParameterName(2) : "0") writer.outdent().append("},").ws().append(timeout ? context.getParameterName(2) : "0")
.append(");").softNewLine(); .append(");").softNewLine();