mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Fix monitorenter
This commit is contained in:
parent
f35f06097c
commit
f93b35ce80
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.classlib.java.lang;
|
package org.teavm.classlib.java.lang;
|
||||||
|
|
||||||
|
import org.teavm.dom.browser.TimerHandler;
|
||||||
import org.teavm.dom.browser.Window;
|
import org.teavm.dom.browser.Window;
|
||||||
import org.teavm.javascript.spi.Async;
|
import org.teavm.javascript.spi.Async;
|
||||||
import org.teavm.javascript.spi.Rename;
|
import org.teavm.javascript.spi.Rename;
|
||||||
|
@ -32,40 +33,50 @@ import org.teavm.platform.async.AsyncCallback;
|
||||||
@Superclass("")
|
@Superclass("")
|
||||||
public class TObject {
|
public class TObject {
|
||||||
private static final Window window = (Window)JS.getGlobal();
|
private static final Window window = (Window)JS.getGlobal();
|
||||||
private TThread owner;
|
|
||||||
private TObject monitorLock;
|
|
||||||
private int monitorCount;
|
|
||||||
private JSArray<NotifyListener> notifyListeners;
|
private JSArray<NotifyListener> notifyListeners;
|
||||||
|
private Lock lock;
|
||||||
|
|
||||||
|
private static class Lock {
|
||||||
|
TThread owner;
|
||||||
|
int count;
|
||||||
|
|
||||||
|
public Lock() {
|
||||||
|
this.owner = TThread.currentThread();
|
||||||
|
count = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
interface NotifyListener extends JSObject {
|
interface NotifyListener extends JSObject {
|
||||||
void handleNotify();
|
boolean handleNotify();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void monitorEnter(TObject o){
|
static void monitorEnter(TObject o) {
|
||||||
if (o.monitorLock == null ){
|
if (o.lock == null) {
|
||||||
o.monitorLock = new TObject();
|
o.lock = new Lock();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
while (o.owner != null && o.owner != TThread.currentThread()) {
|
if (o.lock.owner != TThread.currentThread()) {
|
||||||
|
while (o.lock != null) {
|
||||||
try {
|
try {
|
||||||
o.monitorLock.wait();
|
o.lock.wait();
|
||||||
} catch (InterruptedException ex) {
|
} catch (InterruptedException ex) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
o.owner = TThread.currentThread();
|
o.lock = new Lock();
|
||||||
o.monitorCount++;
|
} else {
|
||||||
|
o.lock.count++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void monitorExit(TObject o){
|
static void monitorExit(TObject o){
|
||||||
o.monitorCount--;
|
if (o.lock != null && o.lock.count-- == 0) {
|
||||||
if (o.monitorCount == 0 && o.monitorLock != null) {
|
o.lock.notifyAll();
|
||||||
o.owner = null;
|
o.lock = null;
|
||||||
o.monitorLock.notifyAll();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean holdsLock(TObject o){
|
static boolean holdsLock(TObject o){
|
||||||
return o.owner == TThread.currentThread();
|
return o.lock != null && o.lock.owner == TThread.currentThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Rename("fakeInit")
|
@Rename("fakeInit")
|
||||||
|
@ -114,11 +125,15 @@ public class TObject {
|
||||||
|
|
||||||
@Rename("notify")
|
@Rename("notify")
|
||||||
public final void notify0(){
|
public final void notify0(){
|
||||||
if (notifyListeners != null && notifyListeners.getLength() > 0){
|
if (notifyListeners != null) {
|
||||||
notifyListeners.shift().handleNotify();
|
while (notifyListeners.getLength() > 0 && notifyListeners.shift().handleNotify()) {
|
||||||
|
// repeat loop
|
||||||
|
}
|
||||||
|
if (notifyListeners.getLength() == 0) {
|
||||||
|
notifyListeners = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Rename("notifyAll")
|
@Rename("notifyAll")
|
||||||
public final void notifyAll0(){
|
public final void notifyAll0(){
|
||||||
|
@ -127,6 +142,7 @@ public class TObject {
|
||||||
while (notifyListeners.getLength() > 0) {
|
while (notifyListeners.getLength() > 0) {
|
||||||
listeners.push(notifyListeners.shift());
|
listeners.push(notifyListeners.shift());
|
||||||
}
|
}
|
||||||
|
notifyListeners = null;
|
||||||
while (listeners.getLength() > 0) {
|
while (listeners.getLength() > 0) {
|
||||||
listeners.shift().handleNotify();
|
listeners.shift().handleNotify();
|
||||||
}
|
}
|
||||||
|
@ -144,7 +160,7 @@ public class TObject {
|
||||||
|
|
||||||
@Async
|
@Async
|
||||||
@Rename("wait")
|
@Rename("wait")
|
||||||
public native final void wait0(long timeout, int nanos) throws TInterruptedException;
|
private native final void wait0(long timeout, int nanos) throws TInterruptedException;
|
||||||
|
|
||||||
@Rename("wait")
|
@Rename("wait")
|
||||||
public final void wait0(long timeout, int nanos, final AsyncCallback<Void> callback) {
|
public final void wait0(long timeout, int nanos, final AsyncCallback<Void> callback) {
|
||||||
|
@ -152,24 +168,55 @@ public class TObject {
|
||||||
notifyListeners = window.newArray();
|
notifyListeners = window.newArray();
|
||||||
}
|
}
|
||||||
final TThread currentThread = TThread.currentThread();
|
final TThread currentThread = TThread.currentThread();
|
||||||
notifyListeners.push(new NotifyListener() {
|
final NotifyListenerImpl listener = new NotifyListenerImpl(callback, currentThread);
|
||||||
|
notifyListeners.push(listener);
|
||||||
|
if (timeout == 0 && nanos == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
listener.timerId = window.setTimeout(listener, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class NotifyListenerImpl implements NotifyListener, TimerHandler {
|
||||||
|
final AsyncCallback<Void> callback;
|
||||||
|
final TThread currentThread;
|
||||||
|
int timerId = -1;
|
||||||
|
boolean finished;
|
||||||
|
|
||||||
|
public NotifyListenerImpl(AsyncCallback<Void> callback, TThread currentThread) {
|
||||||
|
this.callback = callback;
|
||||||
|
this.currentThread = currentThread;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleNotify() {
|
public boolean handleNotify() {
|
||||||
|
if (finished) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
TThread.setCurrentThread(currentThread);
|
TThread.setCurrentThread(currentThread);
|
||||||
|
if (timerId >= 0) {
|
||||||
|
window.clearTimeout(timerId);
|
||||||
|
timerId = -1;
|
||||||
|
}
|
||||||
|
finished = true;
|
||||||
try {
|
try {
|
||||||
callback.complete(null);
|
callback.complete(null);
|
||||||
} finally {
|
} finally {
|
||||||
TThread.setCurrentThread(TThread.getMainThread());
|
TThread.setCurrentThread(TThread.getMainThread());
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTimer() {
|
||||||
|
handleNotify();
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Rename("wait")
|
@Rename("wait")
|
||||||
public final void wait0() throws TInterruptedException {
|
public final void wait0() throws TInterruptedException {
|
||||||
try {
|
try {
|
||||||
wait(0l);
|
wait(0l);
|
||||||
} catch ( InterruptedException ex){
|
} catch (InterruptedException ex) {
|
||||||
throw new TInterruptedException();
|
throw new TInterruptedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,22 +73,21 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(MonitorEnterStatement statement) {
|
public void visit(MonitorEnterStatement statement) {
|
||||||
if (async){
|
|
||||||
try {
|
try {
|
||||||
MethodReference monitorEnterRef = new MethodReference(
|
MethodReference monitorEnterRef = new MethodReference(
|
||||||
Object.class, "monitorEnter", Object.class, void.class);
|
Object.class, "monitorEnter", Object.class, void.class);
|
||||||
writer.appendMethodBody(monitorEnterRef).append("(");
|
writer.appendMethodBody(monitorEnterRef).append("(");
|
||||||
statement.getObjectRef().acceptVisitor(this);
|
statement.getObjectRef().acceptVisitor(this);
|
||||||
|
writer.append(",").ws();
|
||||||
|
writer.append("$rt_continue($part_").append(statement.getAsyncTarget()).append(')');
|
||||||
writer.append(");").softNewLine();
|
writer.append(");").softNewLine();
|
||||||
} catch (IOException ex){
|
} catch (IOException ex){
|
||||||
throw new RenderingException("IO error occured", ex);
|
throw new RenderingException("IO error occured", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(MonitorExitStatement statement) {
|
public void visit(MonitorExitStatement statement) {
|
||||||
if (async){
|
|
||||||
try {
|
try {
|
||||||
MethodReference monitorExitRef = new MethodReference(
|
MethodReference monitorExitRef = new MethodReference(
|
||||||
Object.class, "monitorExit", Object.class, void.class);
|
Object.class, "monitorExit", Object.class, void.class);
|
||||||
|
@ -99,7 +98,6 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
||||||
throw new RenderingException("IO error occured", ex);
|
throw new RenderingException("IO error occured", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static class InjectorHolder {
|
private static class InjectorHolder {
|
||||||
public final Injector injector;
|
public final Injector injector;
|
||||||
|
@ -938,7 +936,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
int index = blockIdMap.size();
|
int index = blockIdMap.size();
|
||||||
do {
|
do {
|
||||||
sb.append(variablePartNames.charAt(index % variableNames.length()));
|
sb.append(variablePartNames.charAt(index % variablePartNames.length()));
|
||||||
index /= variablePartNames.length();
|
index /= variablePartNames.length();
|
||||||
} while (index > 0);
|
} while (index > 0);
|
||||||
name = "$b" + sb;
|
name = "$b" + sb;
|
||||||
|
|
|
@ -669,11 +669,10 @@ class StatementGenerator implements InstructionVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(MonitorEnterInstruction insn) {
|
public void visit(MonitorEnterInstruction insn) {
|
||||||
|
|
||||||
MonitorEnterStatement stmt = new MonitorEnterStatement();
|
MonitorEnterStatement stmt = new MonitorEnterStatement();
|
||||||
stmt.setLocation(currentLocation);
|
stmt.setLocation(currentLocation);
|
||||||
|
|
||||||
stmt.setObjectRef(Expr.var(insn.getObjectRef().getIndex()));
|
stmt.setObjectRef(Expr.var(insn.getObjectRef().getIndex()));
|
||||||
|
stmt.setAsyncTarget(asyncTarget);
|
||||||
statements.add(stmt);
|
statements.add(stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -681,7 +680,6 @@ class StatementGenerator implements InstructionVisitor {
|
||||||
public void visit(MonitorExitInstruction insn) {
|
public void visit(MonitorExitInstruction insn) {
|
||||||
MonitorExitStatement stmt = new MonitorExitStatement();
|
MonitorExitStatement stmt = new MonitorExitStatement();
|
||||||
stmt.setLocation(currentLocation);
|
stmt.setLocation(currentLocation);
|
||||||
|
|
||||||
stmt.setObjectRef(Expr.var(insn.getObjectRef().getIndex()));
|
stmt.setObjectRef(Expr.var(insn.getObjectRef().getIndex()));
|
||||||
statements.add(stmt);
|
statements.add(stmt);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,41 +20,36 @@ package org.teavm.javascript.ast;
|
||||||
* @author shannah
|
* @author shannah
|
||||||
*/
|
*/
|
||||||
public class MonitorEnterStatement extends Statement {
|
public class MonitorEnterStatement extends Statement {
|
||||||
|
|
||||||
private NodeLocation location;
|
private NodeLocation location;
|
||||||
private Expr objectRef;
|
private Expr objectRef;
|
||||||
|
private Integer asyncTarget;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void acceptVisitor(StatementVisitor visitor) {
|
public void acceptVisitor(StatementVisitor visitor) {
|
||||||
visitor.visit(this);
|
visitor.visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the location
|
|
||||||
*/
|
|
||||||
public NodeLocation getLocation() {
|
public NodeLocation getLocation() {
|
||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param location the location to set
|
|
||||||
*/
|
|
||||||
public void setLocation(NodeLocation location) {
|
public void setLocation(NodeLocation location) {
|
||||||
this.location = location;
|
this.location = location;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the objectRef
|
|
||||||
*/
|
|
||||||
public Expr getObjectRef() {
|
public Expr getObjectRef() {
|
||||||
return objectRef;
|
return objectRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param objectRef the objectRef to set
|
|
||||||
*/
|
|
||||||
public void setObjectRef(Expr objectRef) {
|
public void setObjectRef(Expr objectRef) {
|
||||||
this.objectRef = objectRef;
|
this.objectRef = objectRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer getAsyncTarget() {
|
||||||
|
return asyncTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAsyncTarget(Integer asyncTarget) {
|
||||||
|
this.asyncTarget = asyncTarget;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,41 +20,28 @@ package org.teavm.javascript.ast;
|
||||||
* @author shannah
|
* @author shannah
|
||||||
*/
|
*/
|
||||||
public class MonitorExitStatement extends Statement {
|
public class MonitorExitStatement extends Statement {
|
||||||
|
|
||||||
private NodeLocation location;
|
private NodeLocation location;
|
||||||
private Expr objectRef;
|
private Expr objectRef;
|
||||||
|
private Integer asyncTarget;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void acceptVisitor(StatementVisitor visitor) {
|
public void acceptVisitor(StatementVisitor visitor) {
|
||||||
visitor.visit(this);
|
visitor.visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the location
|
|
||||||
*/
|
|
||||||
public NodeLocation getLocation() {
|
public NodeLocation getLocation() {
|
||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param location the location to set
|
|
||||||
*/
|
|
||||||
public void setLocation(NodeLocation location) {
|
public void setLocation(NodeLocation location) {
|
||||||
this.location = location;
|
this.location = location;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the objectRef
|
|
||||||
*/
|
|
||||||
public Expr getObjectRef() {
|
public Expr getObjectRef() {
|
||||||
return objectRef;
|
return objectRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param objectRef the objectRef to set
|
|
||||||
*/
|
|
||||||
public void setObjectRef(Expr objectRef) {
|
public void setObjectRef(Expr objectRef) {
|
||||||
this.objectRef = objectRef;
|
this.objectRef = objectRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import org.teavm.javascript.spi.Async;
|
||||||
import org.teavm.javascript.spi.InjectedBy;
|
import org.teavm.javascript.spi.InjectedBy;
|
||||||
import org.teavm.javascript.spi.Sync;
|
import org.teavm.javascript.spi.Sync;
|
||||||
import org.teavm.model.*;
|
import org.teavm.model.*;
|
||||||
|
import org.teavm.model.instructions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -61,6 +62,17 @@ public class AsyncMethodFinder {
|
||||||
}
|
}
|
||||||
if (method.getAnnotations().get(Async.class.getName()) != null) {
|
if (method.getAnnotations().get(Async.class.getName()) != null) {
|
||||||
add(method.getReference());
|
add(method.getReference());
|
||||||
|
} else if (method.getProgram() != null) {
|
||||||
|
ProgramReader program = method.getProgram();
|
||||||
|
AsyncInstructionFinder insnFinder = new AsyncInstructionFinder();
|
||||||
|
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||||
|
BasicBlockReader block = program.basicBlockAt(i);
|
||||||
|
block.readAllInstructions(insnFinder);
|
||||||
|
if (insnFinder.hasAsync) {
|
||||||
|
add(method.getReference());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -174,4 +186,166 @@ public class AsyncMethodFinder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class AsyncInstructionFinder implements InstructionReader {
|
||||||
|
boolean hasAsync;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void location(InstructionLocation location) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void nop() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void classConstant(VariableReader receiver, ValueType cst) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void nullConstant(VariableReader receiver) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void integerConstant(VariableReader receiver, int cst) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void longConstant(VariableReader receiver, long cst) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void floatConstant(VariableReader receiver, float cst) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doubleConstant(VariableReader receiver, double cst) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stringConstant(VariableReader receiver, String cst) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void binary(BinaryOperation op, VariableReader receiver, VariableReader first, VariableReader second,
|
||||||
|
NumericOperandType type) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void negate(VariableReader receiver, VariableReader operand, NumericOperandType type) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void assign(VariableReader receiver, VariableReader assignee) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cast(VariableReader receiver, VariableReader value, ValueType targetType) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cast(VariableReader receiver, VariableReader value, NumericOperandType sourceType,
|
||||||
|
NumericOperandType targetType) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cast(VariableReader receiver, VariableReader value, IntegerSubtype type,
|
||||||
|
CastIntegerDirection targetType) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void jumpIf(BranchingCondition cond, VariableReader operand, BasicBlockReader consequent,
|
||||||
|
BasicBlockReader alternative) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void jumpIf(BinaryBranchingCondition cond, VariableReader first, VariableReader second,
|
||||||
|
BasicBlockReader consequent, BasicBlockReader alternative) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void jump(BasicBlockReader target) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void choose(VariableReader condition, List<? extends SwitchTableEntryReader> table,
|
||||||
|
BasicBlockReader defaultTarget) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exit(VariableReader valueToReturn) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void raise(VariableReader exception) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void createArray(VariableReader receiver, ValueType itemType, VariableReader size) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void createArray(VariableReader receiver, ValueType itemType,
|
||||||
|
List<? extends VariableReader> dimensions) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void create(VariableReader receiver, String type) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void getField(VariableReader receiver, VariableReader instance, FieldReference field,
|
||||||
|
ValueType fieldType) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void putField(VariableReader instance, FieldReference field, VariableReader value) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void arrayLength(VariableReader receiver, VariableReader array) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cloneArray(VariableReader receiver, VariableReader array) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unwrapArray(VariableReader receiver, VariableReader array, ArrayElementType elementType) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void getElement(VariableReader receiver, VariableReader array, VariableReader index) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void putElement(VariableReader array, VariableReader index, VariableReader value) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invoke(VariableReader receiver, VariableReader instance, MethodReference method,
|
||||||
|
List<? extends VariableReader> arguments, InvocationType type) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void isInstance(VariableReader receiver, VariableReader value, ValueType type) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initClass(String className) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void nullCheck(VariableReader receiver, VariableReader value) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void monitorEnter(VariableReader objectRef) {
|
||||||
|
hasAsync = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void monitorExit(VariableReader objectRef) {
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import java.util.*;
|
||||||
import org.teavm.model.*;
|
import org.teavm.model.*;
|
||||||
import org.teavm.model.instructions.InvokeInstruction;
|
import org.teavm.model.instructions.InvokeInstruction;
|
||||||
import org.teavm.model.instructions.JumpInstruction;
|
import org.teavm.model.instructions.JumpInstruction;
|
||||||
|
import org.teavm.model.instructions.MonitorEnterInstruction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -58,14 +59,21 @@ public class AsyncProgramSplitter {
|
||||||
int last = 0;
|
int last = 0;
|
||||||
for (int i = 0; i < sourceBlock.getInstructions().size(); ++i) {
|
for (int i = 0; i < sourceBlock.getInstructions().size(); ++i) {
|
||||||
Instruction insn = sourceBlock.getInstructions().get(i);
|
Instruction insn = sourceBlock.getInstructions().get(i);
|
||||||
|
Integer receiver;
|
||||||
if (insn instanceof InvokeInstruction) {
|
if (insn instanceof InvokeInstruction) {
|
||||||
InvokeInstruction invoke = (InvokeInstruction)insn;
|
InvokeInstruction invoke = (InvokeInstruction)insn;
|
||||||
if (!asyncMethods.contains(invoke.getMethod())) {
|
if (!asyncMethods.contains(invoke.getMethod())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
receiver = invoke.getReceiver() != null ? invoke.getReceiver().getIndex() : null;
|
||||||
|
} else if (insn instanceof MonitorEnterInstruction) {
|
||||||
|
receiver = null;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// If we met asynchronous invocation...
|
// If we met asynchronous invocation...
|
||||||
// Copy portion of current block from last occurence (or from start) to i'th instruction.
|
// Copy portion of current block from last occurrence (or from start) to i'th instruction.
|
||||||
targetBlock.getInstructions().addAll(ProgramUtils.copyInstructions(sourceBlock,
|
targetBlock.getInstructions().addAll(ProgramUtils.copyInstructions(sourceBlock,
|
||||||
last, i + 1, targetBlock.getProgram()));
|
last, i + 1, targetBlock.getProgram()));
|
||||||
targetBlock.getTryCatchBlocks().addAll(ProgramUtils.copyTryCatches(sourceBlock,
|
targetBlock.getTryCatchBlocks().addAll(ProgramUtils.copyTryCatches(sourceBlock,
|
||||||
|
@ -91,7 +99,7 @@ public class AsyncProgramSplitter {
|
||||||
// Create a new part
|
// Create a new part
|
||||||
Program nextProgram = createStubCopy(program);
|
Program nextProgram = createStubCopy(program);
|
||||||
Part part = new Part();
|
Part part = new Part();
|
||||||
part.input = invoke.getReceiver() != null ? invoke.getReceiver().getIndex() : null;
|
part.input = receiver;
|
||||||
part.program = nextProgram;
|
part.program = nextProgram;
|
||||||
int partId = parts.size();
|
int partId = parts.size();
|
||||||
parts.add(part);
|
parts.add(part);
|
||||||
|
@ -113,7 +121,6 @@ public class AsyncProgramSplitter {
|
||||||
}
|
}
|
||||||
step.targetPart = part;
|
step.targetPart = part;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
targetBlock.getInstructions().addAll(ProgramUtils.copyInstructions(sourceBlock,
|
targetBlock.getInstructions().addAll(ProgramUtils.copyInstructions(sourceBlock,
|
||||||
last, sourceBlock.getInstructions().size(), targetBlock.getProgram()));
|
last, sourceBlock.getInstructions().size(), targetBlock.getProgram()));
|
||||||
targetBlock.getTryCatchBlocks().addAll(ProgramUtils.copyTryCatches(sourceBlock, targetBlock.getProgram()));
|
targetBlock.getTryCatchBlocks().addAll(ProgramUtils.copyTryCatches(sourceBlock, targetBlock.getProgram()));
|
||||||
|
|
|
@ -313,12 +313,10 @@ public class MissingItemsProcessor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(MonitorEnterInstruction insn) {
|
public void visit(MonitorEnterInstruction insn) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(MonitorExitInstruction insn) {
|
public void visit(MonitorExitInstruction insn) {
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,6 +214,6 @@ public class UsageExtractor implements InstructionVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(MonitorExitInstruction insn) {
|
public void visit(MonitorExitInstruction insn) {
|
||||||
usedVariables = new Variable[] {insn.getObjectRef()};
|
usedVariables = new Variable[] {insn.getObjectRef() };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -574,12 +574,10 @@ public class LoopInvariantMotion implements MethodOptimization {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(MonitorEnterInstruction insn) {
|
public void visit(MonitorEnterInstruction insn) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(MonitorExitInstruction insn) {
|
public void visit(MonitorExitInstruction insn) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -207,12 +207,12 @@ public final class VariableEscapeAnalyzer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(MonitorEnterInstruction insn) {
|
public void visit(MonitorEnterInstruction insn) {
|
||||||
|
escaping[insn.getObjectRef().getIndex()] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(MonitorExitInstruction insn) {
|
public void visit(MonitorExitInstruction insn) {
|
||||||
|
escaping[insn.getObjectRef().getIndex()] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user