Trying to fix corrupted state stack when calling Class.newInstance.

See https://github.com/konsoletyper/teavm/issues/118
This commit is contained in:
Alexey Andreev 2015-05-26 22:27:33 +03:00
parent e150e2e44f
commit 3d95eb1a7e
3 changed files with 59 additions and 18 deletions

View File

@ -65,8 +65,7 @@ import org.teavm.classlib.impl.CharFlow;
* @since 1.0 * @since 1.0
*/ */
public class DateTimeZoneBuilder { 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) { private static StorableDateTimeZone buildFixedZone(String id, int wallOffset, int standardOffset) {
return new FixedDateTimeZone(id, wallOffset, standardOffset); return new FixedDateTimeZone(id, wallOffset, standardOffset);
} }
@ -78,6 +77,13 @@ public class DateTimeZoneBuilder {
iRuleSets = new ArrayList<>(10); 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 * Adds a cutover for added rules. The standard offset at the cutover
* defaults to 0. Call setStandardOffset afterwards to change it. * defaults to 0. Call setStandardOffset afterwards to change it.
@ -346,7 +352,7 @@ public class DateTimeZoneBuilder {
offset = 0; offset = 0;
} }
Calendar calendar = Calendar.getInstance(GMT); Calendar calendar = Calendar.getInstance(getGMT());
calendar.setTimeInMillis(0); calendar.setTimeInMillis(0);
calendar.set(Calendar.YEAR, year); calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, iMonthOfYear - 1); calendar.set(Calendar.MONTH, iMonthOfYear - 1);
@ -381,7 +387,7 @@ public class DateTimeZoneBuilder {
// Convert from UTC to local time. // Convert from UTC to local time.
instant += offset; instant += offset;
GregorianCalendar calendar = new GregorianCalendar(GMT); GregorianCalendar calendar = new GregorianCalendar(getGMT());
calendar.setTimeInMillis(instant); calendar.setTimeInMillis(instant);
calendar.set(Calendar.MONTH, iMonthOfYear - 1); calendar.set(Calendar.MONTH, iMonthOfYear - 1);
calendar.set(Calendar.DATE, 1); calendar.set(Calendar.DATE, 1);
@ -427,7 +433,7 @@ public class DateTimeZoneBuilder {
// Convert from UTC to local time. // Convert from UTC to local time.
instant += offset; instant += offset;
GregorianCalendar calendar = new GregorianCalendar(GMT); GregorianCalendar calendar = new GregorianCalendar(getGMT());
calendar.setTimeInMillis(instant); calendar.setTimeInMillis(instant);
calendar.set(Calendar.MONTH, iMonthOfYear - 1); calendar.set(Calendar.MONTH, iMonthOfYear - 1);
calendar.set(Calendar.DATE, 1); calendar.set(Calendar.DATE, 1);
@ -589,7 +595,7 @@ public class DateTimeZoneBuilder {
} }
public long next(final long instant, int standardOffset, int saveMillis) { 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; final int wallOffset = standardOffset + saveMillis;
long testInstant = instant; long testInstant = instant;
@ -844,7 +850,7 @@ public class DateTimeZoneBuilder {
} }
// Stop precalculating if year reaches some arbitrary limit. // Stop precalculating if year reaches some arbitrary limit.
Calendar c = Calendar.getInstance(GMT); Calendar c = Calendar.getInstance(getGMT());
c.setTimeInMillis(nextMillis); c.setTimeInMillis(nextMillis);
if (c.get(Calendar.YEAR) >= YEAR_LIMIT) { if (c.get(Calendar.YEAR) >= YEAR_LIMIT) {
return null; return null;

View File

@ -18,8 +18,9 @@ package org.teavm.classlib.java.util;
import org.teavm.classlib.java.lang.TIllegalStateException; import org.teavm.classlib.java.lang.TIllegalStateException;
import org.teavm.classlib.java.lang.TObject; import org.teavm.classlib.java.lang.TObject;
import org.teavm.classlib.java.lang.TString; import org.teavm.classlib.java.lang.TString;
import org.teavm.platform.Platform; import org.teavm.dom.browser.TimerHandler;
import org.teavm.platform.PlatformRunnable; 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) { if (cancelled || task.timer != null || task.nativeTimerId >= 0) {
throw new TIllegalStateException(); throw new TIllegalStateException();
} }
task.timer = this; 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) { public void schedule(final TTimerTask task, long delay, final long period) {
return Platform.schedule(new PlatformRunnable() { if (cancelled || task.timer != null || task.nativeTimerId >= 0) {
@Override public void run() { throw new TIllegalStateException();
TTimerTask.performOnce(task); }
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);
} }
} }

View File

@ -112,11 +112,14 @@ public class PlatformGenerator implements Generator, Injector, DependencyPlugin
} }
private void generateNewInstance(GeneratorContext context, SourceWriter writer) throws IOException { 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("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(); writer.outdent().append("}").softNewLine();
String cls = context.getParameterName(1);
writer.append("if").ws().append("(!").append(cls).append(".hasOwnProperty('$$constructor$$'))") writer.append("if").ws().append("(!").append(cls).append(".hasOwnProperty('$$constructor$$'))")
.ws().append("{").indent().softNewLine(); .ws().append("{").indent().softNewLine();
writer.append("return null;").softNewLine(); writer.append("return null;").softNewLine();