This commit is contained in:
Myk Melez 2015-01-29 18:26:33 -08:00
Родитель 9c8bdcd97a
Коммит 1e4ed78581
5 изменённых файлов: 82 добавлений и 17 удалений

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

@ -22,8 +22,9 @@ module J2ME {
Load = 0x10,
JIT = 0x20,
Code = 0x40,
Thread = 0x80,
All = Trace | Link | Init | Perf | Load | JIT | Code
All = Trace | Link | Init | Perf | Load | JIT | Code | Thread
}
/**
@ -382,6 +383,7 @@ module J2ME {
jitWriter = writers & WriterFlags.JIT ? writer : null;
codeWriter = writers & WriterFlags.Code ? writer : null;
initWriter = writers & WriterFlags.Init ? writer : null;
threadWriter = writers & WriterFlags.Thread ? writer : null;
loadWriter = writers & WriterFlags.Load ? writer : null;
}
@ -562,17 +564,6 @@ module J2ME {
this.bailoutFrames = [];
}
var frames = this.frames;
if (windingWriter) {
windingWriter.enter("Unwound");
frames.map(function (f) {
if (Frame.isMarker(f)) {
windingWriter.writeLn("- marker -");
} else {
windingWriter.writeLn((f.methodInfo.state === MethodState.Compiled ? "C" : "I") + " " + f.toString());
}
});
windingWriter.leave("");
}
switch (U) {
case VMState.Yielding:
this.resume();

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

@ -440,6 +440,12 @@ module J2ME {
this.methodInfo.isStatic ? this.runtimeClassObject(this.methodInfo.classInfo) : this.getLocal(0)
: "null";
// Insert a preemption check at the top of the method. We can only
// do this if the method has the necessary unwinding code.
if (canYield(this.methodInfo)) {
this.emitPreemptionCheck(this.bodyEmitter, 0);
}
this.emitEntryPoints();
}
@ -852,6 +858,11 @@ module J2ME {
this.emitUnwind(emitter, this.pc, nextPC);
}
private emitPreemptionCheck(emitter: Emitter, nextPC: number) {
emitter.writeLn("CP();");
this.emitUnwind(emitter, nextPC, nextPC);
}
private emitMonitorExit(emitter: Emitter, object: string) {
emitter.writeLn("MX(" + object + ");");
}

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

@ -254,6 +254,10 @@ window.onload = function() {
var el = document.getElementById("unwindCount");
el.textContent = numberWithCommas(J2ME.unwindCount);
var el = document.getElementById("preemptionCount");
el.textContent = numberWithCommas(J2ME.preemptionCount);
}, 500);
function dumpCounters() {

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

@ -611,7 +611,7 @@ Native["java/lang/Thread.sleep.(J)V"] = function(delay) {
};
Native["java/lang/Thread.yield.()V"] = function() {
$.yield();
$.yield("Thread.yield");
};
Native["java/lang/Thread.activeCount.()I"] = function() {

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

@ -88,6 +88,11 @@ module J2ME {
*/
export var initWriter = null;
/**
* Traces thread execution.
*/
export var threadWriter = null;
/**
* Traces generated code.
*/
@ -724,16 +729,16 @@ module J2ME {
$.ctx.bailout(methodInfo, bci, nextBCI, local, stack, lockObject);
}
yield() {
windingWriter && windingWriter.writeLn("yielding");
yield(reason: string) {
unwindCount ++;
runtimeCounter && runtimeCounter.count("yielding");
threadWriter && threadWriter.writeLn("yielding " + reason);
runtimeCounter && runtimeCounter.count("yielding " + reason);
U = VMState.Yielding;
}
pause(reason: string) {
windingWriter && windingWriter.writeLn("pausing");
unwindCount ++;
threadWriter && threadWriter.writeLn("pausing " + reason);
runtimeCounter && runtimeCounter.count("pausing " + reason);
U = VMState.Pausing;
}
@ -1787,6 +1792,58 @@ module J2ME {
return;
}
}
/**
* Last time we preempted a thread.
*/
var lastPreemption = 0;
/**
* The preemption check should be quick. We don't always want to measure
* time so we use a quick counter and mask to determine when to do the
* more expensive preemption check.
*/
var preemptionSamples = 0;
var preemptionSampleMask = 0xFF;
/**
* Number of ms between preemptions, chosen arbitrarily.
*/
var preemptionInterval = 100;
/**
* Number of preemptions thus far.
*/
export var preemptionCount = 0;
/**
* Periodically preempts the current thread. Calls to this method are inserted in
* methods that can yield.
*/
export function checkPreemption() {
preemptionSamples ++;
if ((preemptionSamples & preemptionSampleMask) === 0) {
preempt();
}
}
/**
* TODO: We will almost always preempt the next time we call this if the application
* has been idle. Figure out a better heurisitc here, maybe measure the frequency at
* at which |checkPreemption| is invoked and ony preempt if the frequency is sustained
* for a longer period of time *and* the time since we last preempted is above the
* |preemptionInterval|.
*/
function preempt() {
var now = performance.now();
var elapsed = now - lastPreemption;
if (elapsed > preemptionInterval) {
lastPreemption = now;
preemptionCount ++;
threadWriter && threadWriter.writeLn("Preemption timeout: " + elapsed.toFixed(2) + " ms, samples: " + preemptionSamples + ", count: " + preemptionCount);
$.yield("preemption");
}
}
}
var Runtime = J2ME.Runtime;
@ -1827,3 +1884,5 @@ var CAS = J2ME.checkArrayStore;
var ME = J2ME.monitorEnter;
var MX = J2ME.monitorExit;
var TE = J2ME.translateException;
var CP = J2ME.checkPreemption;