зеркало из https://github.com/mozilla/pluotsorbet.git
reland thread preemption
This commit is contained in:
Родитель
9c8bdcd97a
Коммит
1e4ed78581
15
context.ts
15
context.ts
|
@ -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 + ");");
|
||||
}
|
||||
|
|
4
main.js
4
main.js
|
@ -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() {
|
||||
|
|
67
runtime.ts
67
runtime.ts
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче