mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
First working prototype of new async
This commit is contained in:
parent
56c5fefae4
commit
8fe3876641
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
|
if (timeout) {
|
||||||
|
writer.appendMethodBody(launchRef);
|
||||||
|
} else {
|
||||||
writer.append("$rt_threadStarter(").appendMethodBody(launchRef).append(")");
|
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();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user