This commit is contained in:
Brendan Dahl 2014-12-15 17:38:27 -08:00
Родитель 1df7157c8e
Коммит f81fa7db28
6 изменённых файлов: 73 добавлений и 82 удалений

Просмотреть файл

@ -8,10 +8,6 @@ function throwHelper(e) {
throw e;
}
function throwYield() {
throwHelper(VM.Yield);
}
function throwPause() {
throwHelper(VM.Pause);
}

Просмотреть файл

@ -167,6 +167,16 @@ module J2ME {
}
executeNewFrameSet(frames: Frame []) {
var self = this;
function flattenFrameSet() {
// Append all the current frames to the parent frame set, so a single frame stack
// exists when the bailout finishes.
var currentFrames = self.frames;
self.frames = self.frameSets.pop();
for (var i = 0; i < currentFrames.length; i++) {
self.frames.push(currentFrames[i]);
}
}
this.frameSets.push(this.frames);
this.frames = frames;
try {
@ -176,17 +186,15 @@ module J2ME {
traceWriter.enter("> " + MethodType[MethodType.Interpreted][0] + " " + frameDetails);
}
var returnValue = VM.execute(this);
if ($.Y) {
flattenFrameSet();
return;
}
if (traceWriter) {
traceWriter.leave("<");
}
} catch (e) {
// Append all the current frames to the parent frame set, so a single frame stack
// exists when the bailout finishes.
var currentFrames = this.frames;
this.frames = this.frameSets.pop();
for (var i = 0; i < currentFrames.length; i++) {
this.frames.push(currentFrames[i]);
}
flattenFrameSet();
if (traceWriter) {
traceWriter.leave("< " + e);
}
@ -248,42 +256,17 @@ module J2ME {
if (!message)
message = "";
message = "" + message;
var syntheticMethod = new MethodInfo({
name: "RaiseExceptionSynthetic",
signature: "()V",
isStatic: true,
classInfo: {
className: className,
vmc: {},
vfc: {},
constant_pool: [
null,
{tag: TAGS.CONSTANT_Class, name_index: 2},
{bytes: className},
{tag: TAGS.CONSTANT_String, string_index: 4},
{bytes: message},
{tag: TAGS.CONSTANT_Methodref, class_index: 1, name_and_type_index: 6},
{name_index: 7, signature_index: 8},
{bytes: "<init>"},
{bytes: "(Ljava/lang/String;)V"},
],
},
code: new Uint8Array([
0xbb, 0x00, 0x01, // new <idx=1>
0x59, // dup
0x12, 0x03, // ldc <idx=2>
0xb7, 0x00, 0x05, // invokespecial <idx=5>
0xbf // athrow
])
});
// pushFrame() is not used since the invoker may be a compiled frame.
var callee = new Frame(syntheticMethod, [], 0);
this.frames.push(callee);
var classInfo = CLASSES.getClass(className);
var exception = new classInfo.klass();
var methodInfo = CLASSES.getMethod(classInfo, "I.<init>.(Ljava/lang/String;)V");
jsGlobal[methodInfo.mangledClassAndMethodName](message ? $S(message) : null);
throw exception;
}
raiseExceptionAndYield(className, message?) {
this.raiseException(className, message);
throwYield();
}
setCurrent() {
@ -301,19 +284,15 @@ module J2ME {
Instrument.callResumeHooks(this.current());
this.setCurrent();
do {
try {
VM.execute(this);
} catch (e) {
switch (e) {
case VM.Yield:
// Ignore the yield and continue executing instructions on this thread.
break;
case VM.Pause:
Instrument.callPauseHooks(this.current());
return;
default:
throwHelper(e);
}
VM.execute(this);
if ($.Y === VmState.Yielding) {
// Ignore the yield and continue executing instructions on this thread.
$.Y = VmState.Running;
continue;
} else if ($.Y === VmState.Pausing) {
$.Y = VmState.Running;
Instrument.callPauseHooks(this.current());
return;
}
} while (this.frames.length !== 0);
}
@ -322,20 +301,13 @@ module J2ME {
var ctx = this;
this.setCurrent();
Instrument.callResumeHooks(ctx.current());
try {
VM.execute(ctx);
} catch (e) {
switch (e) {
case VM.Yield:
break;
case VM.Pause:
Instrument.callPauseHooks(ctx.current());
return;
default:
console.info(e);
throw e;
}
VM.execute(ctx);
if ($.Y === VmState.Pausing) {
$.Y = VmState.Running;
Instrument.callPauseHooks(this.current());
return;
}
$.Y = VmState.Running;
Instrument.callPauseHooks(ctx.current());
if (ctx.frames.length === 0) {
@ -355,7 +327,7 @@ module J2ME {
obj[queue] = [];
obj[queue].push(this);
this.lockLevel = lockLevel;
throwPause();
$.pause();
}
unblock(obj, queue, notifyAll, callback) {
@ -380,8 +352,12 @@ module J2ME {
obj.ready = [];
obj.ready.push(this);
} else {
while (this.lockLevel-- > 0)
while (this.lockLevel-- > 0) {
this.monitorEnter(obj);
if ($.Y === VmState.Pausing) {
return;
}
}
this.resume();
}
}

Просмотреть файл

@ -70,6 +70,9 @@ module J2ME {
function throw_(ex, ctx) {
var exClass = ex.class;
if (!ex.stackTrace) {
ex.stackTrace = [];
}
var stackTrace = ex.stackTrace;
@ -960,6 +963,9 @@ module J2ME {
ctx.raiseExceptionAndYield("java/lang/NullPointerException");
}
ctx.monitorEnter(obj);
if ($.Y === VmState.Pausing) {
return;
}
break;
case Bytecodes.MONITOREXIT:
var obj = stack.pop();
@ -1045,6 +1051,9 @@ module J2ME {
var returnValue;
try {
returnValue = fn.apply(obj, args);
if ($.Y) {
return;
}
} catch (ex) {
throw_(ex, ctx);
continue;

Просмотреть файл

@ -567,7 +567,7 @@ Native.create("java/lang/Thread.sleep.(J)V", function(delay) {
}, true);
Native.create("java/lang/Thread.yield.()V", function() {
throwYield();
$.yield();
});
Native.create("java/lang/Thread.activeCount.()I", function(ctx) {

Просмотреть файл

@ -96,7 +96,7 @@ function executePromise(ret, doReturn, ctx, key) {
Instrument.enterAsyncNative(key, ret);
}
throwPause();
$.pause();
}
/**
@ -135,9 +135,7 @@ function createAlternateImpl(object, key, fn, usesPromise) {
var ret = fn.apply(this, args);
return postExec(ret, doReturn, ctx, key);
} catch(e) {
if (e === VM.Pause || e === VM.Yield) {
throwHelper(e);
} else if (e.name === "TypeError") {
if (e.name === "TypeError") {
// JavaScript's TypeError is analogous to a NullPointerException.
console.log(e.stack);
ctx.raiseExceptionAndYield("java/lang/NullPointerException", e);

Просмотреть файл

@ -285,6 +285,12 @@ module J2ME {
}
}
export enum VmState {
Running = 0,
Yielding = 1,
Pausing = 2
}
export class Runtime extends RuntimeTemplate {
private static _nextId: number = 0;
id: number;
@ -292,7 +298,7 @@ module J2ME {
/**
* Are we currently unwinding the stack because of a Yield?
*/
Y: boolean = false;
Y: VmState = VmState.Running;
/**
* Bailout callback whenever a JIT frame is unwound.
@ -301,6 +307,14 @@ module J2ME {
}
yield() {
this.Y = VmState.Yielding;
}
pause() {
this.Y = VmState.Pausing;
}
constructor(jvm: JVM) {
super(jvm);
this.id = Runtime._nextId ++;
@ -710,12 +724,10 @@ module J2ME {
? methodInfo.classInfo.getClassObject($.ctx)
: frame.getLocal(0);
}
try {
$.ctx.monitorEnter(frame.lockObject);
} catch (e) {
// Ensure the frame gets pushed on vm pause.
$.ctx.monitorEnter(frame.lockObject);
if ($.Y === VmState.Pausing) {
$.ctx.frames.push(frame);
throw e;
return;
}
}
return $.ctx.executeNewFrameSet([frame]);