mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Outline of upcoming improvements of continuations
This commit is contained in:
parent
7f33f64d25
commit
93e43456d1
|
@ -72,10 +72,7 @@ public class TObject {
|
|||
monitorEnter(o, 1);
|
||||
}
|
||||
|
||||
@Async
|
||||
static native void monitorEnter(TObject o, int count);
|
||||
|
||||
static void monitorEnter(final TObject o, final int count, final AsyncCallback<Void> callback) {
|
||||
static void monitorEnter(TObject o, int count) {
|
||||
if (o.monitor == null) {
|
||||
o.monitor = new Monitor();
|
||||
}
|
||||
|
@ -83,21 +80,27 @@ public class TObject {
|
|||
o.monitor.owner = TThread.currentThread();
|
||||
}
|
||||
if (o.monitor.owner != TThread.currentThread()) {
|
||||
final TThread thread = TThread.currentThread();
|
||||
o.monitor.enteringThreads.add(new PlatformRunnable() {
|
||||
@Override public void run() {
|
||||
TThread.setCurrentThread(thread);
|
||||
o.monitor.owner = thread;
|
||||
o.monitor.count += count;
|
||||
callback.complete(null);
|
||||
}
|
||||
});
|
||||
monitorEnterWait(o, count);
|
||||
} else {
|
||||
o.monitor.count += count;
|
||||
callback.complete(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Async
|
||||
static native void monitorEnterWait(TObject o, int count);
|
||||
|
||||
static void monitorEnterWait(final TObject o, final int count, final AsyncCallback<Void> callback) {
|
||||
final TThread thread = TThread.currentThread();
|
||||
o.monitor.enteringThreads.add(new PlatformRunnable() {
|
||||
@Override public void run() {
|
||||
TThread.setCurrentThread(thread);
|
||||
o.monitor.owner = thread;
|
||||
o.monitor.count += count;
|
||||
callback.complete(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Sync
|
||||
static void monitorExit(final TObject o) {
|
||||
monitorExit(o, 1);
|
||||
|
@ -230,15 +233,18 @@ public class TObject {
|
|||
}
|
||||
}
|
||||
|
||||
@Async
|
||||
@Rename("wait")
|
||||
private native final void wait0(long timeout, int nanos) throws TInterruptedException;
|
||||
|
||||
@Rename("wait")
|
||||
public final void wait0(long timeout, int nanos, final AsyncCallback<Void> callback) {
|
||||
private final void wait0(long timeout, int nanos) throws TInterruptedException {
|
||||
if (!holdsLock(this)) {
|
||||
throw new TIllegalMonitorStateException();
|
||||
}
|
||||
waitImpl(timeout, nanos);
|
||||
}
|
||||
|
||||
@Async
|
||||
private native final void waitImpl(long timeout, int nanos) throws TInterruptedException;
|
||||
|
||||
public final void waitImpl(long timeout, int nanos, final AsyncCallback<Void> callback) {
|
||||
final NotifyListenerImpl listener = new NotifyListenerImpl(this, callback, monitor.count);
|
||||
monitor.notifyListeners.add(listener);
|
||||
if (timeout > 0 || nanos > 0) {
|
||||
|
@ -288,7 +294,7 @@ public class TObject {
|
|||
timerId = -1;
|
||||
}
|
||||
TThread.setCurrentThread(currentThread);
|
||||
monitorEnter(obj, lockCount, callback);
|
||||
monitorEnterWait(obj, lockCount, callback);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@ import org.teavm.platform.Platform;
|
|||
import org.teavm.platform.PlatformRunnable;
|
||||
import org.teavm.platform.async.AsyncCallback;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
|
@ -36,6 +35,7 @@ public class TThread extends TObject implements TRunnable {
|
|||
private static int activeCount = 1;
|
||||
private long id;
|
||||
private int priority = 0;
|
||||
private long timeSliceStart;
|
||||
|
||||
private TString name;
|
||||
TRunnable target;
|
||||
|
@ -55,10 +55,10 @@ public class TThread extends TObject implements TRunnable {
|
|||
public TThread(TRunnable target, TString name ) {
|
||||
this.name = name;
|
||||
this.target = target;
|
||||
id=nextId++;
|
||||
id = nextId++;
|
||||
}
|
||||
|
||||
public void start(){
|
||||
public void start() {
|
||||
Platform.startThread(new PlatformRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
@ -74,8 +74,11 @@ public class TThread extends TObject implements TRunnable {
|
|||
});
|
||||
}
|
||||
|
||||
static void setCurrentThread(TThread thread){
|
||||
currentThread = thread;
|
||||
static void setCurrentThread(TThread thread) {
|
||||
if (currentThread != thread) {
|
||||
currentThread = thread;
|
||||
currentThread.timeSliceStart = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
static TThread getMainThread(){
|
||||
return mainThread;
|
||||
|
@ -96,11 +99,26 @@ public class TThread extends TObject implements TRunnable {
|
|||
return name;
|
||||
}
|
||||
|
||||
@Async
|
||||
public static native void yield();
|
||||
public static void yield() {
|
||||
if (currentThread.timeSliceStart + 100 < System.currentTimeMillis()) {
|
||||
switchContext();
|
||||
}
|
||||
}
|
||||
|
||||
private static void yield(final AsyncCallback<Void> callback) {
|
||||
callback.complete(null);
|
||||
@Async
|
||||
static native void switchContext();
|
||||
|
||||
private static void switchContext(final AsyncCallback<Void> callback) {
|
||||
final TThread thread = currentThread();
|
||||
Platform.startThread(new PlatformRunnable() {
|
||||
@Override public void run() {
|
||||
setCurrentThread(thread);
|
||||
callback.complete(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void yieldImpl() {
|
||||
}
|
||||
|
||||
public void interrupt() {
|
||||
|
@ -138,11 +156,11 @@ public class TThread extends TObject implements TRunnable {
|
|||
}
|
||||
}, millis);
|
||||
}
|
||||
|
||||
|
||||
public final void setPriority(int newPriority){
|
||||
this.priority = newPriority;
|
||||
}
|
||||
|
||||
|
||||
public final int getPriority(){
|
||||
return this.priority;
|
||||
}
|
||||
|
|
|
@ -58,12 +58,7 @@ public class DefaultNamingStrategy implements NamingStrategy {
|
|||
|
||||
@Override
|
||||
public String getNameFor(MethodDescriptor method) {
|
||||
return getNameFor(method, 'S');
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNameForAsync(MethodDescriptor method) throws NamingException {
|
||||
return getNameFor(method, 'A');
|
||||
return getNameFor(method, 'M');
|
||||
}
|
||||
|
||||
private String getNameFor(MethodDescriptor method, char classifier) {
|
||||
|
@ -78,12 +73,7 @@ public class DefaultNamingStrategy implements NamingStrategy {
|
|||
|
||||
@Override
|
||||
public String getFullNameFor(MethodReference method) throws NamingException {
|
||||
return getFullNameFor(method, 'S');
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFullNameForAsync(MethodReference method) throws NamingException {
|
||||
return getFullNameFor(method, 'A');
|
||||
return getFullNameFor(method, 'M');
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -26,14 +26,10 @@ import org.teavm.model.MethodReference;
|
|||
public interface NameFrequencyConsumer {
|
||||
void consume(MethodReference method);
|
||||
|
||||
void consumeAsync(MethodReference method);
|
||||
|
||||
void consumeInit(MethodReference method);
|
||||
|
||||
void consume(MethodDescriptor method);
|
||||
|
||||
void consumeAsync(MethodDescriptor method);
|
||||
|
||||
void consume(String className);
|
||||
|
||||
void consume(FieldReference field);
|
||||
|
|
|
@ -43,21 +43,6 @@ public class NamingOrderer implements NameFrequencyConsumer {
|
|||
entry.frequency++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void consumeAsync(final MethodReference method) {
|
||||
String key = "A:" + method;
|
||||
Entry entry = entries.get(key);
|
||||
if (entry == null) {
|
||||
entry = new Entry();
|
||||
entry.operation = new NamingOperation() {
|
||||
@Override public void perform(NamingStrategy naming) {
|
||||
naming.getFullNameForAsync(method);
|
||||
}
|
||||
};
|
||||
entries.put(key, entry);
|
||||
}
|
||||
entry.frequency++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void consumeInit(final MethodReference method) {
|
||||
|
@ -91,22 +76,6 @@ public class NamingOrderer implements NameFrequencyConsumer {
|
|||
entry.frequency++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void consumeAsync(final MethodDescriptor method) {
|
||||
String key = "a:" + method;
|
||||
Entry entry = entries.get(key);
|
||||
if (entry == null) {
|
||||
entry = new Entry();
|
||||
entry.operation = new NamingOperation() {
|
||||
@Override public void perform(NamingStrategy naming) {
|
||||
naming.getNameForAsync(method);
|
||||
}
|
||||
};
|
||||
entries.put(key, entry);
|
||||
}
|
||||
entry.frequency++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void consume(final String className) {
|
||||
String key = "c:" + className;
|
||||
|
|
|
@ -28,14 +28,10 @@ public interface NamingStrategy {
|
|||
|
||||
String getNameFor(MethodDescriptor method) throws NamingException;
|
||||
|
||||
String getNameForAsync(MethodDescriptor method) throws NamingException;
|
||||
|
||||
String getNameForInit(MethodReference method) throws NamingException;
|
||||
|
||||
String getFullNameFor(MethodReference method) throws NamingException;
|
||||
|
||||
String getFullNameForAsync(MethodReference method) throws NamingException;
|
||||
|
||||
String getNameFor(FieldReference field) throws NamingException;
|
||||
|
||||
String getNameForFunction(String name) throws NamingException;
|
||||
|
|
|
@ -63,38 +63,17 @@ public class NameFrequencyEstimator implements StatementVisitor, ExprVisitor, Me
|
|||
MethodReader clinit = classSource.get(cls.getName()).getMethod(
|
||||
new MethodDescriptor("<clinit>", ValueType.VOID));
|
||||
for (MethodNode method : cls.getMethods()) {
|
||||
if (method.isAsync()) {
|
||||
consumer.consumeAsync(method.getReference());
|
||||
} else {
|
||||
consumer.consume(method.getReference());
|
||||
if (asyncFamilyMethods.contains(method.getReference())) {
|
||||
consumer.consume(method.getReference());
|
||||
if (asyncFamilyMethods.contains(method.getReference())) {
|
||||
consumer.consume(method.getReference());
|
||||
consumer.consumeAsync(method.getReference());
|
||||
consumer.consumeFunction("$rt_asyncError");
|
||||
consumer.consumeFunction("$rt_asyncResult");
|
||||
}
|
||||
}
|
||||
if (clinit != null && (method.getModifiers().contains(NodeModifier.STATIC) ||
|
||||
method.getReference().getName().equals("<init>"))) {
|
||||
if (!method.isAsync()) {
|
||||
consumer.consume(method.getReference());
|
||||
}
|
||||
if (asyncFamilyMethods.contains(method.getReference())) {
|
||||
consumer.consumeAsync(method.getReference());
|
||||
}
|
||||
method.getReference().getName().equals("<init>"))) {
|
||||
consumer.consume(method.getReference());
|
||||
}
|
||||
if (!method.getModifiers().contains(NodeModifier.STATIC)) {
|
||||
if (method.isAsync()) {
|
||||
consumer.consumeAsync(method.getReference().getDescriptor());
|
||||
consumer.consumeAsync(method.getReference());
|
||||
} else {
|
||||
consumer.consume(method.getReference().getDescriptor());
|
||||
consumer.consume(method.getReference());
|
||||
if (asyncFamilyMethods.contains(method.getReference())) {
|
||||
consumer.consumeAsync(method.getReference().getDescriptor());
|
||||
consumer.consumeAsync(method.getReference());
|
||||
}
|
||||
}
|
||||
consumer.consume(method.getReference().getDescriptor());
|
||||
consumer.consume(method.getReference());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -217,7 +196,7 @@ public class NameFrequencyEstimator implements StatementVisitor, ExprVisitor, Me
|
|||
if (async) {
|
||||
MethodReference monitorEnterRef = new MethodReference(
|
||||
Object.class, "monitorEnter", Object.class, void.class);
|
||||
consumer.consumeAsync(monitorEnterRef);
|
||||
consumer.consume(monitorEnterRef);
|
||||
} else {
|
||||
MethodReference monitorEnterRef = new MethodReference(
|
||||
Object.class, "monitorEnterSync", Object.class, void.class);
|
||||
|
@ -230,7 +209,7 @@ public class NameFrequencyEstimator implements StatementVisitor, ExprVisitor, Me
|
|||
if (async) {
|
||||
MethodReference monitorEnterRef = new MethodReference(
|
||||
Object.class, "monitorExit", Object.class, void.class);
|
||||
consumer.consumeAsync(monitorEnterRef);
|
||||
consumer.consume(monitorEnterRef);
|
||||
} else {
|
||||
MethodReference monitorEnterRef = new MethodReference(
|
||||
Object.class, "monitorExitSync", Object.class, void.class);
|
||||
|
@ -308,30 +287,18 @@ public class NameFrequencyEstimator implements StatementVisitor, ExprVisitor, Me
|
|||
if (injectedMethods.contains(expr.getMethod())) {
|
||||
return;
|
||||
}
|
||||
boolean asyncCall = expr.getAsyncTarget() != null;
|
||||
switch (expr.getType()) {
|
||||
case SPECIAL:
|
||||
case STATIC:
|
||||
if (asyncCall) {
|
||||
consumer.consumeAsync(expr.getMethod());
|
||||
} else {
|
||||
consumer.consume(expr.getMethod());
|
||||
}
|
||||
consumer.consume(expr.getMethod());
|
||||
break;
|
||||
case CONSTRUCTOR:
|
||||
consumer.consumeInit(expr.getMethod());
|
||||
break;
|
||||
case DYNAMIC:
|
||||
if (asyncCall) {
|
||||
consumer.consumeAsync(expr.getMethod().getDescriptor());
|
||||
} else {
|
||||
consumer.consume(expr.getMethod().getDescriptor());
|
||||
}
|
||||
consumer.consume(expr.getMethod().getDescriptor());
|
||||
break;
|
||||
}
|
||||
if (asyncCall) {
|
||||
consumer.consumeFunction("$rt_continue");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -452,12 +452,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
|||
for (MethodNode method : cls.getMethods()) {
|
||||
if (clinit != null && (method.getModifiers().contains(NodeModifier.STATIC) ||
|
||||
method.getReference().getName().equals("<init>"))) {
|
||||
if (!method.isAsync()) {
|
||||
stubNames.add(naming.getFullNameFor(method.getReference()));
|
||||
}
|
||||
if (asyncFamilyMethods.contains(method.getReference())) {
|
||||
stubNames.add(naming.getFullNameForAsync(method.getReference()));
|
||||
}
|
||||
stubNames.add(naming.getFullNameFor(method.getReference()));
|
||||
}
|
||||
if (!method.getModifiers().contains(NodeModifier.STATIC)) {
|
||||
virtualMethods.add(method);
|
||||
|
@ -546,32 +541,20 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
|||
writer.append(",").ws();
|
||||
}
|
||||
first = false;
|
||||
if (method.isAsync()) {
|
||||
emitVirtualDeclaration(ref, true);
|
||||
} else {
|
||||
emitVirtualDeclaration(ref, false);
|
||||
if (asyncFamilyMethods.contains(ref)) {
|
||||
writer.append(",").ws();
|
||||
emitVirtualDeclaration(ref, true);
|
||||
}
|
||||
}
|
||||
emitVirtualDeclaration(ref);
|
||||
debugEmitter.emitMethod(null);
|
||||
}
|
||||
writer.append("]");
|
||||
}
|
||||
|
||||
private void emitVirtualDeclaration(MethodReference ref, boolean async) throws IOException {
|
||||
String methodName = async ? naming.getNameForAsync(ref.getDescriptor()) :
|
||||
naming.getNameFor(ref.getDescriptor());
|
||||
private void emitVirtualDeclaration(MethodReference ref) throws IOException {
|
||||
String methodName = naming.getNameFor(ref.getDescriptor());
|
||||
writer.append("\"").append(methodName).append("\"");
|
||||
writer.append(",").ws().append("function(");
|
||||
List<String> args = new ArrayList<>();
|
||||
for (int i = 1; i <= ref.parameterCount(); ++i) {
|
||||
args.add(variableName(i));
|
||||
}
|
||||
if (async) {
|
||||
args.add(getReturnVariable());
|
||||
}
|
||||
for (int i = 0; i < args.size(); ++i) {
|
||||
if (i > 0) {
|
||||
writer.append(",").ws();
|
||||
|
@ -582,7 +565,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
|||
if (ref.getDescriptor().getResultType() != ValueType.VOID) {
|
||||
writer.append("return ");
|
||||
}
|
||||
writer.append(async ? naming.getFullNameForAsync(ref) : naming.getFullNameFor(ref)).append("(");
|
||||
writer.appendMethodBody(ref).append("(");
|
||||
writer.append("this");
|
||||
for (int i = 0; i < args.size(); ++i) {
|
||||
writer.append(",").ws().append(args.get(i));
|
||||
|
@ -590,23 +573,11 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
|||
writer.append(");").ws().append("}");
|
||||
}
|
||||
|
||||
private String getPartVariable(int index) {
|
||||
if (minifying) {
|
||||
return "$p" + indexToId(index);
|
||||
} else {
|
||||
return "$part_" + index;
|
||||
}
|
||||
}
|
||||
|
||||
private String getReturnVariable() {
|
||||
return minifying ? "$r" : "$return";
|
||||
}
|
||||
|
||||
public void renderBody(MethodNode method, boolean inner) throws IOException {
|
||||
blockIdMap.clear();
|
||||
MethodReference ref = method.getReference();
|
||||
debugEmitter.emitMethod(ref.getDescriptor());
|
||||
String name = method.isAsync() ? naming.getFullNameForAsync(ref) : naming.getFullNameFor(ref);
|
||||
String name = naming.getFullNameFor(ref);
|
||||
if (inner) {
|
||||
writer.append(name).ws().append("=").ws().append("function(");
|
||||
} else {
|
||||
|
@ -622,12 +593,6 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
|||
}
|
||||
writer.append(variableName(i));
|
||||
}
|
||||
if (method.isAsync()) {
|
||||
if (startParam < ref.parameterCount() + 1) {
|
||||
writer.append(',').ws();
|
||||
}
|
||||
writer.append(getReturnVariable());
|
||||
}
|
||||
writer.append(")").ws().append("{").softNewLine().indent();
|
||||
method.acceptVisitor(new MethodBodyRenderer());
|
||||
writer.outdent().append("}");
|
||||
|
@ -635,42 +600,6 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
|||
writer.append(';');
|
||||
}
|
||||
writer.newLine();
|
||||
|
||||
if (!method.isAsync() && asyncFamilyMethods.contains(method.getReference())) {
|
||||
if (inner) {
|
||||
writer.append(naming.getFullNameForAsync(ref)).ws().append("=").ws().append("function(");
|
||||
} else {
|
||||
writer.append("function ").append(naming.getFullNameForAsync(ref)).append("(");
|
||||
}
|
||||
for (int i = startParam; i <= ref.parameterCount(); ++i) {
|
||||
writer.append(variableName(i));
|
||||
writer.append(",").ws();
|
||||
}
|
||||
writer.append(getReturnVariable()).append(")").ws().append("{").softNewLine().indent();
|
||||
|
||||
writer.append("var $x;").softNewLine();
|
||||
writer.append("try").ws().append('{').indent().softNewLine();
|
||||
writer.append("$x").ws().append("=").ws().appendMethodBody(ref).append('(');
|
||||
for (int i = startParam; i <= ref.parameterCount(); ++i) {
|
||||
if (i > startParam) {
|
||||
writer.append(",").ws();
|
||||
}
|
||||
writer.append(variableName(i));
|
||||
}
|
||||
writer.append(");").softNewLine();
|
||||
writer.outdent().append("}").ws().append("catch").ws().append("($e)").ws()
|
||||
.append("{").indent().softNewLine();
|
||||
writer.append("return ").append(getReturnVariable()).append("(").appendFunction("$rt_asyncError")
|
||||
.append("($e));").softNewLine();
|
||||
writer.outdent().append("}");
|
||||
writer.append(getReturnVariable()).append("(").appendFunction("$rt_asyncResult").append("($x));")
|
||||
.softNewLine();
|
||||
writer.outdent().append("}");
|
||||
if (inner) {
|
||||
writer.append(';');
|
||||
}
|
||||
writer.newLine();
|
||||
}
|
||||
debugEmitter.emitMethod(null);
|
||||
}
|
||||
|
||||
|
@ -756,6 +685,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
|||
if (hasTryCatch) {
|
||||
variableNames.add("$je");
|
||||
}
|
||||
variableNames.add("$ptr");
|
||||
if (!variableNames.isEmpty()) {
|
||||
writer.append("var ");
|
||||
for (int i = 0; i < variableNames.size(); ++i) {
|
||||
|
@ -766,18 +696,34 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
|||
}
|
||||
writer.append(";").softNewLine();
|
||||
}
|
||||
|
||||
writer.append("function $save()").ws().append("{").indent().softNewLine();
|
||||
writer.append("var $").ws().append('=').ws().append("$rt_stack();").softNewLine();
|
||||
for (int i = ref.parameterCount() + 1; i < variableCount; ++i) {
|
||||
writer.append("$.push(").append(variableName(i)).append(");");
|
||||
}
|
||||
writer.append("$.push($ptr)");
|
||||
writer.softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
|
||||
writer.append("$ptr").ws().append('=').ws().append("0;").softNewLine();
|
||||
writer.append("if").ws().append("($rt_isRestoring())").ws().append("{").indent().softNewLine();
|
||||
writer.append("var $s").ws().append('=').ws().append("$rt_stack();").softNewLine();
|
||||
writer.append("var $ptr").ws().append('=').append("$s.pop();");
|
||||
for (int i = variableCount - 1; i > ref.parameterCount(); --i) {
|
||||
writer.append(variableName(i)).ws().append('=').ws().append("$.pop();");
|
||||
}
|
||||
writer.softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
|
||||
writer.append("$main: switch").ws().append("($ptr)").ws().append('{').softNewLine();
|
||||
for (int i = 0; i < methodNode.getBody().size(); ++i) {
|
||||
writer.append("var ").append(getPartVariable(i)).ws().append("=").ws()
|
||||
.appendFunction("$rt_guardAsync").append("(function(");
|
||||
if (i > 0) {
|
||||
writer.append("$restore");
|
||||
}
|
||||
writer.append(")").ws().append("{").indent().softNewLine();
|
||||
writer.append("case ").append(i).append(":").indent().softNewLine();
|
||||
AsyncMethodPart part = methodNode.getBody().get(i);
|
||||
part.getStatement().acceptVisitor(Renderer.this);
|
||||
writer.outdent().append("},").ws().append(getReturnVariable()).append(");").softNewLine();
|
||||
writer.outdent();
|
||||
}
|
||||
writer.append("return ").append(getPartVariable(0)).append("();").softNewLine();
|
||||
writer.append("}").softNewLine();
|
||||
} catch (IOException e) {
|
||||
throw new RenderingException("IO error occured", e);
|
||||
}
|
||||
|
@ -823,11 +769,6 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
|||
return asyncFamilyMethods.contains(method);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCompleteContinuation() {
|
||||
return getReturnVariable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Diagnostics getDiagnostics() {
|
||||
return diagnostics;
|
||||
|
@ -1097,23 +1038,14 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
|||
pushLocation(statement.getLocation());
|
||||
}
|
||||
writer.append("return");
|
||||
if (async) {
|
||||
writer.append(' ').append(getReturnVariable()).append("(").appendFunction("$rt_asyncResult")
|
||||
.append("(");
|
||||
}
|
||||
if (statement.getResult() != null) {
|
||||
if (!async) {
|
||||
writer.append(' ');
|
||||
}
|
||||
writer.append(' ');
|
||||
prevCallSite = debugEmitter.emitCallSite();
|
||||
priority = Priority.COMMA;
|
||||
associativity = Associativity.NONE;
|
||||
statement.getResult().acceptVisitor(this);
|
||||
debugEmitter.emitCallSite();
|
||||
}
|
||||
if (async) {
|
||||
writer.append("))");
|
||||
}
|
||||
writer.append(";").softNewLine();
|
||||
if (statement.getLocation() != null) {
|
||||
popLocation();
|
||||
|
@ -1693,43 +1625,33 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
|||
if (injector != null) {
|
||||
injector.generate(new InjectorContextImpl(expr.getArguments()), expr.getMethod());
|
||||
} else {
|
||||
boolean asyncCall = expr.getAsyncTarget() != null;
|
||||
if (asyncCall) {
|
||||
writer.append("return ");
|
||||
}
|
||||
if (expr.getType() == InvocationType.DYNAMIC) {
|
||||
expr.getArguments().get(0).acceptVisitor(this);
|
||||
}
|
||||
MethodReference method = expr.getMethod();
|
||||
String name = asyncCall ? naming.getNameForAsync(method.getDescriptor()) :
|
||||
naming.getNameFor(method.getDescriptor());
|
||||
String name = naming.getNameFor(method.getDescriptor());
|
||||
DeferredCallSite callSite = prevCallSite;
|
||||
boolean shouldEraseCallSite = lastCallSite == null;
|
||||
if (lastCallSite == null) {
|
||||
lastCallSite = callSite;
|
||||
}
|
||||
boolean virtual = false;
|
||||
boolean hasParams = false;
|
||||
enterPriority(Priority.COMMA, Associativity.NONE, false);
|
||||
switch (expr.getType()) {
|
||||
case STATIC:
|
||||
writer.append(asyncCall ? naming.getFullNameForAsync(method) :
|
||||
naming.getFullNameFor(method)).append("(");
|
||||
writer.append(naming.getFullNameFor(method)).append("(");
|
||||
prevCallSite = debugEmitter.emitCallSite();
|
||||
for (int i = 0; i < expr.getArguments().size(); ++i) {
|
||||
if (i > 0) {
|
||||
writer.append(",").ws();
|
||||
}
|
||||
expr.getArguments().get(i).acceptVisitor(this);
|
||||
hasParams = true;
|
||||
}
|
||||
break;
|
||||
case SPECIAL:
|
||||
writer.append(asyncCall ? naming.getFullNameForAsync(method) :
|
||||
naming.getFullNameFor(method)).append("(");
|
||||
writer.append(naming.getFullNameFor(method)).append("(");
|
||||
prevCallSite = debugEmitter.emitCallSite();
|
||||
expr.getArguments().get(0).acceptVisitor(this);
|
||||
hasParams = true;
|
||||
for (int i = 1; i < expr.getArguments().size(); ++i) {
|
||||
writer.append(",").ws();
|
||||
expr.getArguments().get(i).acceptVisitor(this);
|
||||
|
@ -1742,7 +1664,6 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
|||
if (i > 1) {
|
||||
writer.append(",").ws();
|
||||
}
|
||||
hasParams = true;
|
||||
expr.getArguments().get(i).acceptVisitor(this);
|
||||
}
|
||||
virtual = true;
|
||||
|
@ -1754,20 +1675,21 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
|||
if (i > 0) {
|
||||
writer.append(",").ws();
|
||||
}
|
||||
hasParams = true;
|
||||
expr.getArguments().get(i).acceptVisitor(this);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (expr.getAsyncTarget() != null) {
|
||||
if (hasParams) {
|
||||
writer.append(',').ws();
|
||||
}
|
||||
writer.appendFunction("$rt_continue").append("(").append(getPartVariable(expr.getAsyncTarget()))
|
||||
.append(')');
|
||||
}
|
||||
writer.append(')');
|
||||
exitPriority();
|
||||
if (expr.getAsyncTarget() != null) {
|
||||
writer.append(';').softNewLine();
|
||||
writer.append("$ptr").ws().append("=").ws().append(expr.getAsyncTarget()).append(";")
|
||||
.softNewLine();
|
||||
writer.append("if").ws().append("($rt_suspending())").ws().append("{").indent();
|
||||
writer.append("return $save();").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
writer.append("break $main;").softNewLine();
|
||||
}
|
||||
if (lastCallSite != null) {
|
||||
if (virtual) {
|
||||
lastCallSite.setVirtualMethod(expr.getMethod());
|
||||
|
@ -2061,11 +1983,8 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
|||
if (async) {
|
||||
MethodReference monitorEnterRef = new MethodReference(
|
||||
Object.class, "monitorEnter", Object.class, void.class);
|
||||
writer.append("return ").append(naming.getFullNameForAsync(monitorEnterRef)).append("(");
|
||||
writer.appendMethodBody(monitorEnterRef).append("(");
|
||||
statement.getObjectRef().acceptVisitor(this);
|
||||
writer.append(",").ws();
|
||||
writer.appendFunction("$rt_continue").append("(").append(getPartVariable(statement.getAsyncTarget()))
|
||||
.append(')');
|
||||
writer.append(");").softNewLine();
|
||||
} else {
|
||||
MethodReference monitorEnterRef = new MethodReference(
|
||||
|
|
|
@ -36,8 +36,6 @@ public interface GeneratorContext extends ServiceRepository {
|
|||
|
||||
boolean isAsync();
|
||||
|
||||
String getCompleteContinuation();
|
||||
|
||||
boolean isAsync(MethodReference method);
|
||||
|
||||
boolean isAsyncFamily(MethodReference method);
|
||||
|
|
|
@ -437,13 +437,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
|||
for (Map.Entry<String, TeaVMEntryPoint> entry : entryPoints.entrySet()) {
|
||||
sourceWriter.append("var ").append(entry.getKey()).ws().append("=").ws();
|
||||
MethodReference ref = entry.getValue().reference;
|
||||
boolean asyncMethod = asyncMethods.contains(ref);
|
||||
boolean wrapAsync = !asyncMethod && entry.getValue().isAsync();
|
||||
if (wrapAsync) {
|
||||
sourceWriter.append("$rt_staticAsyncAdapter(").appendMethodBody(ref).append(')');
|
||||
} else {
|
||||
sourceWriter.append(asyncMethod ? naming.getFullNameForAsync(ref) : naming.getFullNameFor(ref));
|
||||
}
|
||||
sourceWriter.append(naming.getFullNameFor(ref));
|
||||
sourceWriter.append(";").newLine();
|
||||
}
|
||||
for (Map.Entry<String, String> entry : exportedClasses.entrySet()) {
|
||||
|
|
|
@ -517,6 +517,57 @@ function $rt_guardAsync(f, continuation) {
|
|||
}
|
||||
}
|
||||
}
|
||||
function TeaVMThread(runner) {
|
||||
this.status = 3;
|
||||
this.stack = [];
|
||||
this.suspendCallback = null;
|
||||
this.runner = runner;
|
||||
}
|
||||
TeaVMThread.push = function(value) {
|
||||
this.stack.push[value];
|
||||
}
|
||||
TeaVMThread.isResuming = function() {
|
||||
return this.status == 1;
|
||||
}
|
||||
TeaVMThread.isSuspending = function() {
|
||||
return this.status == 2;
|
||||
}
|
||||
TeaVMThread.suspend(callback) {
|
||||
this.suspendCallback = callback;
|
||||
this.status = 1;
|
||||
}
|
||||
TeaVMThread.start = function() {
|
||||
if (this.status != 3) {
|
||||
throw new Error("Thread already started");
|
||||
}
|
||||
this.status = 0;
|
||||
this.run();
|
||||
}
|
||||
TeaVMThread.resume = function() {
|
||||
this.status = 2;
|
||||
this.run();
|
||||
}
|
||||
TeaVMThread.run = function() {
|
||||
this.runner();
|
||||
if (this.suspendCallback !== null) {
|
||||
var self = this;
|
||||
this.suspendCallback(function() {
|
||||
self.resume();
|
||||
});
|
||||
}
|
||||
}
|
||||
function $rt_nativeThread(thread) {
|
||||
if (!thread.hasNativeProperty("$teavm_thread")) {
|
||||
thread.$teavm_thread = new TeaVMThread();
|
||||
}
|
||||
}
|
||||
function $rt_suspending() {
|
||||
return $rt_nativeThread($rt_getThread()).isSuspending();
|
||||
}
|
||||
function $rt_resuming() {
|
||||
return $rt_nativeThread($rt_getThread()).isResuming();
|
||||
}
|
||||
|
||||
function TeaVMAsyncError(cause) {
|
||||
this.message = "Async error occured";
|
||||
this.cause = cause;
|
||||
|
|
Loading…
Reference in New Issue
Block a user