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, Load = 0x10,
JIT = 0x20, JIT = 0x20,
Code = 0x40, 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; jitWriter = writers & WriterFlags.JIT ? writer : null;
codeWriter = writers & WriterFlags.Code ? writer : null; codeWriter = writers & WriterFlags.Code ? writer : null;
initWriter = writers & WriterFlags.Init ? writer : null; initWriter = writers & WriterFlags.Init ? writer : null;
threadWriter = writers & WriterFlags.Thread ? writer : null;
loadWriter = writers & WriterFlags.Load ? writer : null; loadWriter = writers & WriterFlags.Load ? writer : null;
} }
@ -562,17 +564,6 @@ module J2ME {
this.bailoutFrames = []; this.bailoutFrames = [];
} }
var frames = this.frames; 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) { switch (U) {
case VMState.Yielding: case VMState.Yielding:
this.resume(); this.resume();

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

@ -440,6 +440,12 @@ module J2ME {
this.methodInfo.isStatic ? this.runtimeClassObject(this.methodInfo.classInfo) : this.getLocal(0) this.methodInfo.isStatic ? this.runtimeClassObject(this.methodInfo.classInfo) : this.getLocal(0)
: "null"; : "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(); this.emitEntryPoints();
} }
@ -852,6 +858,11 @@ module J2ME {
this.emitUnwind(emitter, this.pc, nextPC); 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) { private emitMonitorExit(emitter: Emitter, object: string) {
emitter.writeLn("MX(" + object + ");"); emitter.writeLn("MX(" + object + ");");
} }

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

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

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

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

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

@ -88,6 +88,11 @@ module J2ME {
*/ */
export var initWriter = null; export var initWriter = null;
/**
* Traces thread execution.
*/
export var threadWriter = null;
/** /**
* Traces generated code. * Traces generated code.
*/ */
@ -724,16 +729,16 @@ module J2ME {
$.ctx.bailout(methodInfo, bci, nextBCI, local, stack, lockObject); $.ctx.bailout(methodInfo, bci, nextBCI, local, stack, lockObject);
} }
yield() { yield(reason: string) {
windingWriter && windingWriter.writeLn("yielding");
unwindCount ++; unwindCount ++;
runtimeCounter && runtimeCounter.count("yielding"); threadWriter && threadWriter.writeLn("yielding " + reason);
runtimeCounter && runtimeCounter.count("yielding " + reason);
U = VMState.Yielding; U = VMState.Yielding;
} }
pause(reason: string) { pause(reason: string) {
windingWriter && windingWriter.writeLn("pausing");
unwindCount ++; unwindCount ++;
threadWriter && threadWriter.writeLn("pausing " + reason);
runtimeCounter && runtimeCounter.count("pausing " + reason); runtimeCounter && runtimeCounter.count("pausing " + reason);
U = VMState.Pausing; U = VMState.Pausing;
} }
@ -1787,6 +1792,58 @@ module J2ME {
return; 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; var Runtime = J2ME.Runtime;
@ -1827,3 +1884,5 @@ var CAS = J2ME.checkArrayStore;
var ME = J2ME.monitorEnter; var ME = J2ME.monitorEnter;
var MX = J2ME.monitorExit; var MX = J2ME.monitorExit;
var TE = J2ME.translateException; var TE = J2ME.translateException;
var CP = J2ME.checkPreemption;