From 3d95eb1a7eacec18c56853b8a14b73acfa2cd9e2 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Tue, 26 May 2015 22:27:33 +0300 Subject: [PATCH] Trying to fix corrupted state stack when calling Class.newInstance. See https://github.com/konsoletyper/teavm/issues/118 --- .../classlib/impl/tz/DateTimeZoneBuilder.java | 20 +++++--- .../org/teavm/classlib/java/util/TTimer.java | 50 +++++++++++++++---- .../platform/plugin/PlatformGenerator.java | 7 ++- 3 files changed, 59 insertions(+), 18 deletions(-) diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/impl/tz/DateTimeZoneBuilder.java b/teavm-classlib/src/main/java/org/teavm/classlib/impl/tz/DateTimeZoneBuilder.java index e9a8f53f8..18cce899b 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/impl/tz/DateTimeZoneBuilder.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/impl/tz/DateTimeZoneBuilder.java @@ -65,8 +65,7 @@ import org.teavm.classlib.impl.CharFlow; * @since 1.0 */ public class DateTimeZoneBuilder { - private static TimeZone GMT = TimeZone.getTimeZone("GMT+00:00"); - + private static TimeZone gmtCache; private static StorableDateTimeZone buildFixedZone(String id, int wallOffset, int standardOffset) { return new FixedDateTimeZone(id, wallOffset, standardOffset); } @@ -78,6 +77,13 @@ public class DateTimeZoneBuilder { iRuleSets = new ArrayList<>(10); } + private static TimeZone getGMT() { + if (gmtCache == null) { + gmtCache = TimeZone.getTimeZone("GMT+00:00"); + } + return gmtCache; + } + /** * Adds a cutover for added rules. The standard offset at the cutover * defaults to 0. Call setStandardOffset afterwards to change it. @@ -346,7 +352,7 @@ public class DateTimeZoneBuilder { offset = 0; } - Calendar calendar = Calendar.getInstance(GMT); + Calendar calendar = Calendar.getInstance(getGMT()); calendar.setTimeInMillis(0); calendar.set(Calendar.YEAR, year); calendar.set(Calendar.MONTH, iMonthOfYear - 1); @@ -381,7 +387,7 @@ public class DateTimeZoneBuilder { // Convert from UTC to local time. instant += offset; - GregorianCalendar calendar = new GregorianCalendar(GMT); + GregorianCalendar calendar = new GregorianCalendar(getGMT()); calendar.setTimeInMillis(instant); calendar.set(Calendar.MONTH, iMonthOfYear - 1); calendar.set(Calendar.DATE, 1); @@ -427,7 +433,7 @@ public class DateTimeZoneBuilder { // Convert from UTC to local time. instant += offset; - GregorianCalendar calendar = new GregorianCalendar(GMT); + GregorianCalendar calendar = new GregorianCalendar(getGMT()); calendar.setTimeInMillis(instant); calendar.set(Calendar.MONTH, iMonthOfYear - 1); calendar.set(Calendar.DATE, 1); @@ -589,7 +595,7 @@ public class DateTimeZoneBuilder { } public long next(final long instant, int standardOffset, int saveMillis) { - Calendar calendar = Calendar.getInstance(GMT); + Calendar calendar = Calendar.getInstance(getGMT()); final int wallOffset = standardOffset + saveMillis; long testInstant = instant; @@ -844,7 +850,7 @@ public class DateTimeZoneBuilder { } // Stop precalculating if year reaches some arbitrary limit. - Calendar c = Calendar.getInstance(GMT); + Calendar c = Calendar.getInstance(getGMT()); c.setTimeInMillis(nextMillis); if (c.get(Calendar.YEAR) >= YEAR_LIMIT) { return null; 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 500afd299..c252d642f 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,9 @@ 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.platform.Platform; -import org.teavm.platform.PlatformRunnable; +import org.teavm.dom.browser.TimerHandler; +import org.teavm.dom.browser.Window; +import org.teavm.jso.JS; /** * @@ -45,19 +46,50 @@ public class TTimer extends TObject { } } - public void schedule(TTimerTask task, long delay) { + public void schedule(final TTimerTask task, long delay) { if (cancelled || task.timer != null || task.nativeTimerId >= 0) { throw new TIllegalStateException(); } task.timer = this; - task.nativeTimerId = scheduleOnce(task, (int)delay); + task.nativeTimerId = ((Window)JS.getGlobal()).setTimeout(new TimerHandler() { + @Override + public void onTimer() { + new Thread() { + @Override + public void run() { + if (cancelled || task.timer == null) { + return; + } + TTimerTask.performOnce(task); + } + }.start(); + } + }, (int)delay); } - private static int scheduleOnce(final TTimerTask task, int delay) { - return Platform.schedule(new PlatformRunnable() { - @Override public void run() { - TTimerTask.performOnce(task); + public void schedule(final TTimerTask task, long delay, final long period) { + if (cancelled || task.timer != null || task.nativeTimerId >= 0) { + throw new TIllegalStateException(); + } + task.timer = this; + task.nativeTimerId = ((Window)JS.getGlobal()).setTimeout(new TimerHandler() { + @Override + public void onTimer() { + final TimerHandler self = this; + new Thread() { + @Override + public void run() { + if (cancelled || task.timer == null) { + return; + } + task.nativeTimerId = ((Window)JS.getGlobal()).setTimeout(self, (int)period); + TTimerTask.performOnce(task); + if (!cancelled) { + task.timer = TTimer.this; + } + } + }.start(); } - }, delay); + }, (int)delay); } } diff --git a/teavm-platform/src/main/java/org/teavm/platform/plugin/PlatformGenerator.java b/teavm-platform/src/main/java/org/teavm/platform/plugin/PlatformGenerator.java index cdc47f54b..6163da1a5 100644 --- a/teavm-platform/src/main/java/org/teavm/platform/plugin/PlatformGenerator.java +++ b/teavm-platform/src/main/java/org/teavm/platform/plugin/PlatformGenerator.java @@ -112,11 +112,14 @@ public class PlatformGenerator implements Generator, Injector, DependencyPlugin } private void generateNewInstance(GeneratorContext context, SourceWriter writer) throws IOException { + String cls = context.getParameterName(1); + writer.append("if").ws().append("($rt_resuming())").ws().append("{").indent().softNewLine(); - writer.append("return $rt_nativeThread().pop();").softNewLine(); + writer.append("var $r = $rt_nativeThread().pop();").softNewLine(); + writer.append(cls + ".$$constructor$$($r);").softNewLine(); + writer.append("return $r;").softNewLine(); writer.outdent().append("}").softNewLine(); - String cls = context.getParameterName(1); writer.append("if").ws().append("(!").append(cls).append(".hasOwnProperty('$$constructor$$'))") .ws().append("{").indent().softNewLine(); writer.append("return null;").softNewLine();