Most of the elements are in place for monitors to work... something is wrong tough because I get errors when I try to compile files with synchronized sections.

This commit is contained in:
Steve Hannah 2015-02-06 16:47:59 -08:00
parent cca4336a15
commit 2fbc50e76f
25 changed files with 402 additions and 13 deletions

View File

@ -29,6 +29,39 @@ import org.teavm.runtime.Async;
*/
@Superclass("")
public class TObject {
private TThread owner;
private TObject monitorLock;
private int monitorCount=0;
static void monitorEnter(TObject o){
if ( o.monitorLock == null ){
o.monitorLock = new TObject();
}
while (o.owner != null && o.owner != TThread.currentThread() ){
try {
o.monitorLock.wait();
} catch (InterruptedException ex) {
}
}
o.owner = TThread.currentThread();
o.monitorCount++;
}
static void monitorExit(TObject o){
o.owner = null;
o.monitorCount--;
if ( o.monitorLock != null ){
o.monitorLock.notifyAll();
}
}
static boolean holdsLock(TObject o){
return o.owner == TThread.currentThread();
}
@Rename("fakeInit")
public TObject() {
}

View File

@ -112,8 +112,8 @@ public class TThread extends TObject implements TRunnable {
return id;
}
public static boolean holdsLock(@SuppressWarnings("unused") TObject obj) {
return true;
public static boolean holdsLock(TObject obj) {
return TObject.holdsLock(obj);
}
public static void sleep(long millis) throws TInterruptedException {
@ -123,4 +123,6 @@ public class TThread extends TObject implements TRunnable {
@Async
@GeneratedBy(ThreadNativeGenerator.class)
private static native void sleep(double millis) throws TInterruptedException;
}

View File

@ -508,6 +508,16 @@ public class AstIO {
throw new IOExceptionWrapper(e);
}
}
@Override
public void visit(MonitorEnterStatement statement) {
}
@Override
public void visit(MonitorExitStatement statement) {
}
}
private NodeLocation readLocation(DataInput input) throws IOException {

View File

@ -261,6 +261,16 @@ public class DiskRegularMethodNodeCache implements RegularMethodNodeCache {
@Override
public void visit(RestoreAsyncStatement statement) {
}
@Override
public void visit(MonitorEnterStatement statement) {
}
@Override
public void visit(MonitorExitStatement statement) {
}
}
static class Item {

View File

@ -116,4 +116,14 @@ class BreakToContinueReplacer implements StatementVisitor {
@Override
public void visit(RestoreAsyncStatement statement) {
}
@Override
public void visit(MonitorEnterStatement statement) {
}
@Override
public void visit(MonitorExitStatement statement) {
}
}

View File

@ -111,4 +111,14 @@ class CertainBlockCountVisitor implements StatementVisitor {
@Override
public void visit(RestoreAsyncStatement statement) {
}
@Override
public void visit(MonitorEnterStatement statement) {
}
@Override
public void visit(MonitorExitStatement statement) {
}
}

View File

@ -618,4 +618,14 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
public void visit(RestoreAsyncStatement statement) {
resultStmt = statement;
}
@Override
public void visit(MonitorEnterStatement statement) {
resultStmt = statement;
}
@Override
public void visit(MonitorExitStatement statement) {
resultStmt = statement;
}
}

View File

@ -121,4 +121,14 @@ class RedundantLabelEliminator implements StatementVisitor {
@Override
public void visit(RestoreAsyncStatement statement) {
}
@Override
public void visit(MonitorEnterStatement statement) {
}
@Override
public void visit(MonitorExitStatement statement) {
}
}

View File

@ -115,4 +115,14 @@ class ReferenceCountingVisitor implements StatementVisitor {
@Override
public void visit(RestoreAsyncStatement statement) {
}
@Override
public void visit(MonitorEnterStatement statement) {
}
@Override
public void visit(MonitorExitStatement statement) {
}
}

View File

@ -55,6 +55,40 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
private DeferredCallSite prevCallSite;
private boolean async;
@Override
public void visit(MonitorEnterStatement statement) {
if (async){
try {
MethodReference monitorEnterRef = new MethodReference(
Object.class, "monitorEnter", Object.class, void.class);
writer.appendMethodBody(monitorEnterRef).append("(");
statement.acceptVisitor(this);
writer.append(");").softNewLine();
} catch (IOException ex){
throw new RenderingException("IO error occured", ex);
}
}
}
@Override
public void visit(MonitorExitStatement statement) {
if (async){
try {
MethodReference monitorExitRef = new MethodReference(
Object.class, "monitorExit", Object.class, void.class);
writer.appendMethodBody(monitorExitRef).append("(");
statement.acceptVisitor(this);
writer.append(");").softNewLine();
} catch (IOException ex){
throw new RenderingException("IO error occured", ex);
}
}
}
private static class InjectorHolder {
public final Injector injector;

View File

@ -670,10 +670,24 @@ class StatementGenerator implements InstructionVisitor {
@Override
public void visit(MonitorEnterInstruction insn) {
MonitorEnterStatement stmt = new MonitorEnterStatement();
stmt.setLocation(currentLocation);
VariableExpr expr = new VariableExpr();
expr.setIndex(insn.getObjectRef().getIndex());
expr.setLocation(currentLocation);
stmt.setObjectRef(expr);
statements.add(stmt);
}
@Override
public void visit(MonitorExitInstruction insn) {
MonitorExitStatement stmt = new MonitorExitStatement();
stmt.setLocation(currentLocation);
VariableExpr expr = new VariableExpr();
expr.setLocation(currentLocation);
expr.setIndex(insn.getObjectRef().getIndex());
stmt.setObjectRef(expr);
statements.add(stmt);
}
}

View File

@ -114,4 +114,14 @@ class TryCatchFinder implements StatementVisitor {
@Override
public void visit(RestoreAsyncStatement statement) {
}
@Override
public void visit(MonitorEnterStatement statement) {
}
@Override
public void visit(MonitorExitStatement statement) {
}
}

View File

@ -228,4 +228,14 @@ class UnusedVariableEliminator implements ExprVisitor, StatementVisitor {
@Override
public void visit(RestoreAsyncStatement statement) {
}
@Override
public void visit(MonitorEnterStatement statement) {
}
@Override
public void visit(MonitorExitStatement statement) {
}
}

View File

@ -0,0 +1,60 @@
/*
* Copyright 2015 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.javascript.ast;
/**
*
* @author shannah
*/
public class MonitorEnterStatement extends Statement {
private NodeLocation location;
private VariableExpr objectRef;
@Override
public void acceptVisitor(StatementVisitor visitor) {
visitor.visit(this);
}
/**
* @return the location
*/
public NodeLocation getLocation() {
return location;
}
/**
* @param location the location to set
*/
public void setLocation(NodeLocation location) {
this.location = location;
}
/**
* @return the objectRef
*/
public VariableExpr getObjectRef() {
return objectRef;
}
/**
* @param objectRef the objectRef to set
*/
public void setObjectRef(VariableExpr objectRef) {
this.objectRef = objectRef;
}
}

View File

@ -0,0 +1,60 @@
/*
* Copyright 2015 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.javascript.ast;
/**
*
* @author shannah
*/
public class MonitorExitStatement extends Statement {
private NodeLocation location;
private VariableExpr objectRef;
@Override
public void acceptVisitor(StatementVisitor visitor) {
visitor.visit(this);
}
/**
* @return the location
*/
public NodeLocation getLocation() {
return location;
}
/**
* @param location the location to set
*/
public void setLocation(NodeLocation location) {
this.location = location;
}
/**
* @return the objectRef
*/
public VariableExpr getObjectRef() {
return objectRef;
}
/**
* @param objectRef the objectRef to set
*/
public void setObjectRef(VariableExpr objectRef) {
this.objectRef = objectRef;
}
}

View File

@ -198,4 +198,14 @@ public class RenamingVisitor implements StatementVisitor, ExprVisitor {
statement.setReceiver(varNames[statement.getReceiver()]);
}
}
@Override
public void visit(MonitorEnterStatement statement) {
}
@Override
public void visit(MonitorExitStatement statement) {
}
}

View File

@ -45,4 +45,8 @@ public interface StatementVisitor {
void visit(TryCatchStatement statement);
void visit(RestoreAsyncStatement statement);
void visit(MonitorEnterStatement statement);
void visit(MonitorExitStatement statement);
}

View File

@ -16,6 +16,7 @@
package org.teavm.model;
import java.util.*;
import org.teavm.model.instructions.AssignInstruction;
import org.teavm.model.instructions.InstructionReader;
/**
@ -66,7 +67,19 @@ public class BasicBlock implements BasicBlockReader {
@Override
public void add(int index, Instruction e) {
if (e.getBasicBlock() != null) {
throw new IllegalArgumentException("This instruction is in some basic block");
if (e instanceof AssignInstruction){
AssignInstruction ae = (AssignInstruction)e;
System.out.println("Assignment "+ae.getReceiver()+" -> "+ae.getAssignee());
System.out.println(ae.getReceiver().getDebugNames());
System.out.println(ae.getReceiver().getIndex());
System.out.println(ae.getReceiver().getProgram());
System.out.println(ae.getAssignee().getDebugNames());
System.out.println(ae.getAssignee().getIndex());
System.out.println(ae.getAssignee().getProgram());
System.out.println(ae.getBasicBlock().getInstructions());
}
throw new IllegalArgumentException("This instruction is in some basic block "+e+", "+e.getLocation());
}
e.setBasicBlock(BasicBlock.this);
instructions.add(index, e);

View File

@ -231,12 +231,12 @@ public abstract class InstructionVariableMapper implements InstructionVisitor {
@Override
public void visit(MonitorEnterInstruction insn) {
insn.setObjectRef(map(insn.getObjectRef()));
}
@Override
public void visit(MonitorExitInstruction insn) {
insn.setObjectRef(map(insn.getObjectRef()));
}

View File

@ -421,12 +421,14 @@ public class GlobalValueNumbering implements MethodOptimization {
@Override
public void visit(MonitorEnterInstruction insn) {
int val = map[insn.getObjectRef().getIndex()];
insn.setObjectRef(program.variableAt(val));
}
@Override
public void visit(MonitorExitInstruction insn) {
int val = map[insn.getObjectRef().getIndex()];
insn.setObjectRef(program.variableAt(val));
}
};
}

View File

@ -1556,10 +1556,19 @@ public class ProgramParser implements VariableDebugInformation {
nextIndexes = new int[0];
return;
}
case Opcodes.MONITORENTER:
case Opcodes.MONITOREXIT:
popSingle();
case Opcodes.MONITORENTER: {
MonitorEnterInstruction insn = new MonitorEnterInstruction();
insn.setObjectRef(getVariable(popSingle()));
addInstruction(insn);
break;
}
case Opcodes.MONITOREXIT: {
MonitorExitInstruction insn = new MonitorExitInstruction();
insn.setObjectRef(getVariable(popSingle()));
addInstruction(insn);
break;
}
}
}

View File

@ -450,12 +450,12 @@ public class SSATransformer {
@Override
public void visit(MonitorEnterInstruction insn) {
insn.setObjectRef(use(insn.getObjectRef()));
}
@Override
public void visit(MonitorExitInstruction insn) {
insn.setObjectRef(use(insn.getObjectRef()));
}
};
}

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project-shared-configuration>
<!--
This file contains additional configuration written by modules in the NetBeans IDE.
The configuration is intended to be shared among all the users of project and
therefore it is assumed to be part of version control checkout.
Without this configuration present, some functionality in the IDE may be limited or fail altogether.
-->
<properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
<!--
Properties that influence various parts of the IDE, especially code formatting and the like.
You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
That way multiple projects can share the same settings (useful for formatting rules for example).
Any value defined here will override the pom.xml file value but is only applicable to the current project.
-->
<ca-weblite-netbeans-mirah.project_5f_type>maven</ca-weblite-netbeans-mirah.project_5f_type>
<org-netbeans-modules-maven-j2ee.netbeans_2e_hint_2e_deploy_2e_server>gfv3ee6</org-netbeans-modules-maven-j2ee.netbeans_2e_hint_2e_deploy_2e_server>
</properties>
</project-shared-configuration>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<actions>
<action>
<actionName>build</actionName>
<packagings>
<packaging>*</packaging>
</packagings>
<goals>
<goal>install</goal>
</goals>
<properties>
<skipTests>true</skipTests>
<jpda.listen>maven</jpda.listen>
</properties>
</action>
</actions>

View File

@ -48,6 +48,20 @@ public final class AsyncProgram {
}, "Test Thread");
t.start();
Thread t2 = new Thread(new Runnable(){
@Override
public void run() {
try {
doRun(lock);
} catch (InterruptedException ex){
System.out.println(ex.getMessage());
}
}
}, "Test Thread 2");
t2.start();
System.out.println("Should be main -> Current thread is "+Thread.currentThread().getName());
System.out.println("Now trying wait...");
@ -68,6 +82,12 @@ public final class AsyncProgram {
Thread.sleep(5000);
System.out.println("Current thread is "+Thread.currentThread().getName());
System.out.println("Finished another 5 second sleep");
synchronized(lock){
System.out.println("Inside locked section of thread "+Thread.currentThread().getName());
Thread.sleep(2000);
System.out.println("Finished locked section of thread "+Thread.currentThread().getName());
}
}
private static void withoutAsync() {
@ -113,4 +133,6 @@ public final class AsyncProgram {
System.out.println("Thread.yield called");
throw new IllegalStateException();
}
}