зеркало из https://github.com/mozilla/pluotsorbet.git
improve locking of class initialization
This commit is contained in:
Родитель
11394b361b
Коммит
eb7b9eec14
60
context.js
60
context.js
|
@ -32,7 +32,6 @@ Context.prototype.popFrame = function() {
|
|||
Context.prototype.pushClassInitFrame = function(classInfo) {
|
||||
if (classInfo.initialized)
|
||||
return;
|
||||
// console.log("starting initialization of", classInfo.className, this.thread.toString());
|
||||
classInfo.thread = this.thread;
|
||||
var syntheticMethod = {
|
||||
classInfo: {
|
||||
|
@ -53,8 +52,12 @@ Context.prototype.pushClassInitFrame = function(classInfo) {
|
|||
code: [
|
||||
0x2a, // aload_0
|
||||
0x59, // dup
|
||||
0x59, // dup
|
||||
0x59, // dup
|
||||
0xc2, // monitorenter
|
||||
0xb7, 0x00, 0x01, // invokespecial <idx=1>
|
||||
0xb7, 0x00, 0x07, // invokespecial <idx=7>
|
||||
0xc3, // monitorexit
|
||||
0xb1, // return
|
||||
],
|
||||
exception_table: [],
|
||||
|
@ -185,30 +188,6 @@ Context.prototype.resume = function() {
|
|||
this.start(this.stopFrame);
|
||||
}
|
||||
|
||||
Context.prototype.wait = function(obj) {
|
||||
if (!obj.waiters)
|
||||
obj.waiters = [];
|
||||
obj.waiters.push(this);
|
||||
throw VM.Pause;
|
||||
}
|
||||
|
||||
Context.prototype.notify = function(obj) {
|
||||
if (obj.waiters && obj.waiters.length) {
|
||||
if (!obj.ready)
|
||||
obj.ready = [];
|
||||
obj.ready.push(obj.waiters.pop());
|
||||
}
|
||||
if (!obj.ready || !obj.ready.length)
|
||||
return;
|
||||
var ctx = obj.ready.pop();
|
||||
window.setZeroTimeout(VM.execute.bind(null, ctx));
|
||||
}
|
||||
|
||||
Context.prototype.notifyAll = function(obj) {
|
||||
while ((obj.waiters && obj.waiters.length) || (obj.ready && obj.ready.length))
|
||||
this.notify(obj);
|
||||
}
|
||||
|
||||
Context.prototype.monitorEnter = function(obj) {
|
||||
var lock = obj.lock;
|
||||
if (!lock) {
|
||||
|
@ -219,7 +198,10 @@ Context.prototype.monitorEnter = function(obj) {
|
|||
++lock.count;
|
||||
return;
|
||||
}
|
||||
this.wait(obj);
|
||||
if (!obj.ready)
|
||||
obj.ready = [];
|
||||
obj.ready.push(this);
|
||||
throw VM.Pause;
|
||||
}
|
||||
|
||||
Context.prototype.monitorExit = function(obj) {
|
||||
|
@ -232,5 +214,29 @@ Context.prototype.monitorExit = function(obj) {
|
|||
return;
|
||||
}
|
||||
obj.lock = null;
|
||||
this.notifyAll(obj);
|
||||
if (obj.ready && obj.ready.length) {
|
||||
var ctx = obj.ready.pop();
|
||||
ctx.monitorEnter(obj);
|
||||
ctx.resume();
|
||||
}
|
||||
}
|
||||
|
||||
Context.prototype.wait = function(obj, timeout) {
|
||||
if (!obj.lock || obj.lock.thread !== this.thread || obj.lock.count !== 1)
|
||||
this.raiseException("java/lang/IllegalMonitorStateException");
|
||||
this.monitorExit(obj);
|
||||
if (!obj.waiting)
|
||||
obj.waiting = [];
|
||||
obj.waiting.push(obj);
|
||||
throw VM.Pause;
|
||||
}
|
||||
|
||||
Context.prototype.notify = function(obj, notifyAll) {
|
||||
if (!obj.lock || obj.lock.thread !== this.thread)
|
||||
this.raiseException("java/lang/IllegalMonitorStateException");
|
||||
while (obj.waiting && obj.waiting.length) {
|
||||
obj.ready.push(obj.waiting.pop());
|
||||
if (!notifyAll)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
12
native.js
12
native.js
|
@ -103,7 +103,6 @@ Native["java/lang/Object.hashCode.()I"] = function(ctx, stack) {
|
|||
var hashCode = obj.hashCode;
|
||||
while (!hashCode)
|
||||
hashCode = obj.hashCode = util.id();
|
||||
console.log(hashCode);
|
||||
stack.push(hashCode);
|
||||
}
|
||||
|
||||
|
@ -113,7 +112,11 @@ Native["java/lang/Object.wait.(J)V"] = function(ctx, stack) {
|
|||
}
|
||||
|
||||
Native["java/lang/Class.invoke_clinit.()V"] = function(ctx, stack) {
|
||||
var classInfo = stack.pop().vmClass;
|
||||
var classObject = stack.pop();
|
||||
var classInfo = classObject.vmClass;
|
||||
if (classInfo.initialized || classInfo.pending)
|
||||
return;
|
||||
classInfo.pending = true;
|
||||
var clinit = CLASSES.getMethod(classInfo, "<clinit>", "()V", true);
|
||||
if (clinit)
|
||||
ctx.pushFrame(clinit, 0);
|
||||
|
@ -125,9 +128,10 @@ Native["java/lang/Class.invoke_clinit.()V"] = function(ctx, stack) {
|
|||
Native["java/lang/Class.init9.()V"] = function(ctx, stack) {
|
||||
var classObject = stack.pop();
|
||||
var classInfo = classObject.vmClass;
|
||||
if (classInfo.initialized)
|
||||
return;
|
||||
classInfo.pending = false;
|
||||
classInfo.initialized = true;
|
||||
classInfo.thread = null;
|
||||
ctx.notifyAll(classObject);
|
||||
}
|
||||
|
||||
Native["java/lang/Class.getName.()Ljava/lang/String;"] = function(ctx, stack) {
|
||||
|
|
7
vm.js
7
vm.js
|
@ -95,13 +95,6 @@ VM.execute = function(ctx) {
|
|||
function classInitCheck(classInfo, ip) {
|
||||
if (classInfo.initialized)
|
||||
return;
|
||||
if (classInfo.thread) {
|
||||
// Nothing to do if class initialization is currently in progress on this thread.
|
||||
if (classInfo.thread === ctx.thread)
|
||||
return;
|
||||
ctx.wait(classInfo.getClassObject());
|
||||
// not reached
|
||||
}
|
||||
frame.ip = ip;
|
||||
ctx.pushClassInitFrame(classInfo);
|
||||
throw VM.Yield;
|
||||
|
|
Загрузка…
Ссылка в новой задаче