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) {
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() {
@Override public void run() {
TThread.setCurrentThread(thread);
@ -118,7 +125,7 @@ public class TObject {
o.monitor.owner = null;
if (!o.monitor.enteringThreads.isEmpty()) {
Platform.startThread(new PlatformRunnable() {
Platform.postpone(new PlatformRunnable() {
@Override public void run() {
if (o.isEmptyMonitor() || o.monitor.owner != null) {
return;
@ -127,7 +134,7 @@ public class TObject {
o.monitor.enteringThreads.remove().run();
}
}
}, false);
});
} else {
o.isEmptyMonitor();
}
@ -203,7 +210,7 @@ public class TObject {
while (!listeners.isEmpty()) {
NotifyListener listener = listeners.remove();
if (!listener.expired()) {
Platform.startThread(listener, false);
Platform.postpone(listener);
break;
}
}
@ -219,7 +226,7 @@ public class TObject {
while (!listeners.isEmpty()) {
NotifyListener listener = listeners.remove();
if (!listener.expired()) {
Platform.startThread(listener, false);
Platform.postpone(listener);
}
}
}
@ -279,7 +286,7 @@ public class TObject {
@Override
public void onTimer() {
if (!expired()) {
Platform.startThread(this, false);
Platform.postpone(this);
}
}

View File

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

View File

@ -204,7 +204,8 @@ public class Decompiler {
AsyncProgramSplitter splitter = new AsyncProgramSplitter(classSource, splitMethods);
splitter.split(method.getProgram());
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);
}
Program program = method.getProgram();
@ -227,7 +228,7 @@ public class Decompiler {
Program program = method.getProgram();
int[] targetBlocks = new int[program.basicBlockCount()];
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) {
methodNode.getVariables().add(program.variableAt(i).getRegister());
}
@ -242,7 +243,7 @@ public class Decompiler {
return methodNode;
}
private AsyncMethodPart getRegularMethodStatement(Program program, int[] targetBlocks) {
private AsyncMethodPart getRegularMethodStatement(Program program, int[] targetBlocks, boolean async) {
AsyncMethodPart result = new AsyncMethodPart();
lastBlockId = 1;
graph = ProgramUtils.buildControlFlowGraph(program);
@ -290,6 +291,7 @@ public class Decompiler {
if (head != -1 && loopSuccessors[head] == next) {
next = head;
}
boolean saved = !async;
if (node >= 0) {
generator.currentBlock = program.basicBlockAt(node);
int tmp = indexer.nodeAt(next);
@ -308,8 +310,9 @@ public class Decompiler {
generator.setCurrentLocation(nodeLocation);
}
insn.acceptVisitor(generator);
if (j == 0 && insn instanceof InvokeInstruction) {
if (insn instanceof InvokeInstruction && !saved) {
generator.statements.add(new SaveStatement());
saved = true;
}
}
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("$ptr").ws().append('=').ws().append("$T.pop();");
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.outdent().append("}").softNewLine();
@ -724,6 +724,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
part.getStatement().acceptVisitor(Renderer.this);
writer.outdent();
}
writer.append("default:").ws().append("throw new Error('Invalid recorded state');").softNewLine();
writer.append("}").softNewLine();
writer.outdent().append("}").softNewLine();
} catch (IOException e) {

View File

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

View File

@ -107,12 +107,16 @@ public final class Platform {
@GeneratedBy(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) {
runnable.run();
}
public static void postpone(PlatformRunnable runnable) {
schedule(runnable, 0);
}
@GeneratedBy(PlatformGenerator.class)
@PluggableDependency(PlatformGenerator.class)
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);
writer.append("var thread").ws().append('=').ws().append("$rt_nativeThread();").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("if").ws().append("(result instanceof Error)").ws().append("{").indent().softNewLine();
writer.append("throw result;").softNewLine();

View File

@ -153,7 +153,11 @@ public class PlatformGenerator implements Generator, Injector, DependencyPlugin
PlatformRunnable.class, void.class);
String runnable = context.getParameterName(1);
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.outdent().append("},").ws().append(timeout ? context.getParameterName(2) : "0")
.append(");").softNewLine();