diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TObject.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TObject.java index 57cb9e0cc..0ee0a8189 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TObject.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TObject.java @@ -50,6 +50,24 @@ public class TObject { boolean expired(); } + static void monitorEnterSync(TObject o) { + if (o.monitor == null) { + o.monitor = new Monitor(); + } + if (o.monitor.owner == null) { + o.monitor.owner = TThread.currentThread(); + } + o.monitor.count++; + } + + static void monitorExitSync(TObject o) { + if (o.isEmptyMonitor() || o.monitor.owner != TThread.currentThread()) { + throw new TIllegalMonitorStateException(); + } + --o.monitor.count; + o.isEmptyMonitor(); + } + static void monitorEnter(TObject o) { monitorEnter(o, 1); } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TTimer.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TTimer.java index 9b1d12049..500afd299 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TTimer.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TTimer.java @@ -18,8 +18,8 @@ package org.teavm.classlib.java.util; import org.teavm.classlib.java.lang.TIllegalStateException; import org.teavm.classlib.java.lang.TObject; import org.teavm.classlib.java.lang.TString; -import org.teavm.dependency.PluggableDependency; -import org.teavm.javascript.spi.GeneratedBy; +import org.teavm.platform.Platform; +import org.teavm.platform.PlatformRunnable; /** * @@ -53,7 +53,11 @@ public class TTimer extends TObject { task.nativeTimerId = scheduleOnce(task, (int)delay); } - @GeneratedBy(TimerNativeGenerator.class) - @PluggableDependency(TimerNativeGenerator.class) - private static native int scheduleOnce(TTimerTask task, int delay); + private static int scheduleOnce(final TTimerTask task, int delay) { + return Platform.schedule(new PlatformRunnable() { + @Override public void run() { + TTimerTask.performOnce(task); + } + }, delay); + } } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TTimerTask.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TTimerTask.java index 1271e3e20..088ac45e0 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TTimerTask.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TTimerTask.java @@ -34,11 +34,11 @@ public abstract class TTimerTask extends TObject implements TRunnable { return true; } - void performOnce() { - if (timer != null) { - run(); - timer.tasks.remove(this); - timer = null; + static void performOnce(TTimerTask task) { + if (task.timer != null) { + task.run(); + task.timer.tasks.remove(task); + task.timer = null; } } } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TimerNativeGenerator.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TimerNativeGenerator.java deleted file mode 100644 index 3a376cd1d..000000000 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TimerNativeGenerator.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2014 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.classlib.java.util; - -import java.io.IOException; -import java.util.TimerTask; -import org.teavm.codegen.SourceWriter; -import org.teavm.dependency.DependencyAgent; -import org.teavm.dependency.DependencyPlugin; -import org.teavm.dependency.MethodDependency; -import org.teavm.javascript.spi.Generator; -import org.teavm.javascript.spi.GeneratorContext; -import org.teavm.model.CallLocation; -import org.teavm.model.MethodReference; - -/** - * - * @author Alexey Andreev - */ -public class TimerNativeGenerator implements Generator, DependencyPlugin { - private static final MethodReference performOnceRef = new MethodReference(TimerTask.class, - "performOnce", void.class); - - @Override - public void methodAchieved(DependencyAgent agent, MethodDependency method, CallLocation location) { - switch (method.getReference().getName()) { - case "scheduleOnce": { - MethodDependency performMethod = agent.linkMethod(performOnceRef, null); - performMethod.use(); - method.getVariable(1).connect(performMethod.getVariable(1)); - break; - } - } - } - - @Override - public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException { - switch (methodRef.getName()) { - case "scheduleOnce": - generateScheduleNative(context, writer); - break; - } - } - - private void generateScheduleNative(GeneratorContext context, SourceWriter writer) throws IOException { - writer.append("return setTimeout(function() {").indent().softNewLine(); - writer.append(context.getParameterName(1)).append(".").appendMethod(performOnceRef) - .append("();").softNewLine(); - writer.outdent().append("},").ws().append(context.getParameterName(2)).append(");").softNewLine(); - } -} diff --git a/teavm-core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java b/teavm-core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java index 82f3a23a5..5302b9007 100644 --- a/teavm-core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java +++ b/teavm-core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java @@ -499,6 +499,11 @@ class DependencyGraphBuilder { new MethodReference(Object.class, "monitorEnter", Object.class, void.class), null); nodes[objectRef.getIndex()].connect(methodDep.getVariable(1)); methodDep.use(); + + methodDep = dependencyChecker.linkMethod( + new MethodReference(Object.class, "monitorEnterSync", Object.class, void.class), null); + nodes[objectRef.getIndex()].connect(methodDep.getVariable(1)); + methodDep.use(); } @Override @@ -507,6 +512,11 @@ class DependencyGraphBuilder { new MethodReference(Object.class, "monitorExit", Object.class, void.class), null); nodes[objectRef.getIndex()].connect(methodDep.getVariable(1)); methodDep.use(); + + methodDep = dependencyChecker.linkMethod( + new MethodReference(Object.class, "monitorExitSync", Object.class, void.class), null); + nodes[objectRef.getIndex()].connect(methodDep.getVariable(1)); + methodDep.use(); } }; } diff --git a/teavm-core/src/main/java/org/teavm/javascript/Renderer.java b/teavm-core/src/main/java/org/teavm/javascript/Renderer.java index 1a27916e3..7c02724c7 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/Renderer.java +++ b/teavm-core/src/main/java/org/teavm/javascript/Renderer.java @@ -2001,17 +2001,22 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext @Override public void visit(MonitorEnterStatement statement) { - if (!async) { - return; - } try { - MethodReference monitorEnterRef = new MethodReference( - Object.class, "monitorEnter", Object.class, void.class); - writer.append("return ").append(naming.getFullNameForAsync(monitorEnterRef)).append("("); - statement.getObjectRef().acceptVisitor(this); - writer.append(",").ws(); - writer.append("$rt_continue($part_").append(statement.getAsyncTarget()).append(')'); - writer.append(");").softNewLine(); + if (async) { + MethodReference monitorEnterRef = new MethodReference( + Object.class, "monitorEnter", Object.class, void.class); + writer.append("return ").append(naming.getFullNameForAsync(monitorEnterRef)).append("("); + statement.getObjectRef().acceptVisitor(this); + writer.append(",").ws(); + writer.append("$rt_continue($part_").append(statement.getAsyncTarget()).append(')'); + writer.append(");").softNewLine(); + } else { + MethodReference monitorEnterRef = new MethodReference( + Object.class, "monitorEnterSync", Object.class, void.class); + writer.appendMethodBody(monitorEnterRef).append('('); + statement.getObjectRef().acceptVisitor(this); + writer.append(");").softNewLine(); + } } catch (IOException ex){ throw new RenderingException("IO error occured", ex); } @@ -2019,15 +2024,20 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext @Override public void visit(MonitorExitStatement statement) { - if (!async) { - return; - } try { - MethodReference monitorExitRef = new MethodReference( - Object.class, "monitorExit", Object.class, void.class); - writer.appendMethodBody(monitorExitRef).append("("); - statement.getObjectRef().acceptVisitor(this); - writer.append(");").softNewLine(); + if (async) { + MethodReference monitorExitRef = new MethodReference( + Object.class, "monitorExit", Object.class, void.class); + writer.appendMethodBody(monitorExitRef).append("("); + statement.getObjectRef().acceptVisitor(this); + writer.append(");").softNewLine(); + } else { + MethodReference monitorEnterRef = new MethodReference( + Object.class, "monitorExitSync", Object.class, void.class); + writer.appendMethodBody(monitorEnterRef).append('('); + statement.getObjectRef().acceptVisitor(this); + writer.append(");").softNewLine(); + } } catch (IOException ex){ throw new RenderingException("IO error occured", ex); }