зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1346068 - Implement $262.agent. r=shu
--HG-- extra : rebase_source : 73cb86ed09a22a393cdfed0eb6a2be8e13ee0b76 extra : histedit_source : e6cd352554c3c1c8cfe84a4e2f3f692e191279cb
This commit is contained in:
Родитель
c055a4757e
Коммит
5669ef5c81
|
@ -826,21 +826,23 @@ skip script test262/language/expressions/class/gen-method-yield-spread-obj.js
|
|||
skip script test262/language/expressions/class/dstr-meth-static-dflt-obj-ptrn-rest-val-obj.js
|
||||
skip script test262/language/expressions/class/dstr-gen-meth-static-dflt-obj-ptrn-rest-getter.js
|
||||
|
||||
# https://bugzilla.mozilla.org/show_bug.cgi?id=1346068
|
||||
skip script test262/built-ins/Atomics/wait/negative-timeout.js
|
||||
skip script test262/built-ins/Atomics/wait/was-woken.js
|
||||
skip script test262/built-ins/Atomics/wait/did-timeout.js
|
||||
skip script test262/built-ins/Atomics/wait/good-views.js
|
||||
skip script test262/built-ins/Atomics/wait/no-spurious-wakeup.js
|
||||
skip script test262/built-ins/Atomics/wait/nan-timeout.js
|
||||
skip script test262/built-ins/Atomics/wake/wake-all.js
|
||||
skip script test262/built-ins/Atomics/wake/wake-zero.js
|
||||
skip script test262/built-ins/Atomics/wake/wake-negative.js
|
||||
skip script test262/built-ins/Atomics/wake/wake-nan.js
|
||||
skip script test262/built-ins/Atomics/wake/wake-two.js
|
||||
skip script test262/built-ins/Atomics/wake/wake-in-order.js
|
||||
skip script test262/built-ins/Atomics/wake/wake-one.js
|
||||
skip script test262/built-ins/Atomics/wake/wake-all-on-loc.js
|
||||
# Dependent on evalInWorker, setSharedArrayBuffer, and
|
||||
# getSharedArrayBuffer, plus the test cases can't actually run in the
|
||||
# browser even if that were fixed, https://bugzil.la/1349863
|
||||
skip-if(!xulRuntime.shell) script test262/built-ins/Atomics/wait/negative-timeout.js
|
||||
skip-if(!xulRuntime.shell) script test262/built-ins/Atomics/wait/was-woken.js
|
||||
skip-if(!xulRuntime.shell) script test262/built-ins/Atomics/wait/did-timeout.js
|
||||
skip-if(!xulRuntime.shell) script test262/built-ins/Atomics/wait/good-views.js
|
||||
skip-if(!xulRuntime.shell) script test262/built-ins/Atomics/wait/no-spurious-wakeup.js
|
||||
skip-if(!xulRuntime.shell) script test262/built-ins/Atomics/wait/nan-timeout.js
|
||||
skip-if(!xulRuntime.shell) script test262/built-ins/Atomics/wake/wake-all.js
|
||||
skip-if(!xulRuntime.shell) script test262/built-ins/Atomics/wake/wake-zero.js
|
||||
skip-if(!xulRuntime.shell) script test262/built-ins/Atomics/wake/wake-negative.js
|
||||
skip-if(!xulRuntime.shell) script test262/built-ins/Atomics/wake/wake-nan.js
|
||||
skip-if(!xulRuntime.shell) script test262/built-ins/Atomics/wake/wake-two.js
|
||||
skip-if(!xulRuntime.shell) script test262/built-ins/Atomics/wake/wake-in-order.js
|
||||
skip-if(!xulRuntime.shell) script test262/built-ins/Atomics/wake/wake-one.js
|
||||
skip-if(!xulRuntime.shell) script test262/built-ins/Atomics/wake/wake-all-on-loc.js
|
||||
|
||||
# SharedArrayBuffer API pedantry
|
||||
# https://bugzilla.mozilla.org/show_bug.cgi?id=1346071
|
||||
|
|
|
@ -7,6 +7,21 @@
|
|||
var FunctionToString = global.Function.prototype.toString;
|
||||
var ReflectApply = global.Reflect.apply;
|
||||
var NewGlobal = global.newGlobal;
|
||||
var Atomics = global.Atomics;
|
||||
var SharedArrayBuffer = global.SharedArrayBuffer;
|
||||
var Int32Array = global.Int32Array;
|
||||
var setSharedArrayBuffer = global.setSharedArrayBuffer;
|
||||
var getSharedArrayBuffer = global.getSharedArrayBuffer;
|
||||
var evalInWorker = global.evalInWorker;
|
||||
var hasThreads = ("helperThreadCount" in global ? global.helperThreadCount() > 0 : true);
|
||||
var hasMailbox = typeof setSharedArrayBuffer == "function" && typeof getSharedArrayBuffer == "function";
|
||||
var hasEvalInWorker = typeof evalInWorker == "function";
|
||||
|
||||
// The $262.agent framework is not appropriate for browsers yet, and some
|
||||
// test cases can't work in browsers (they block the main thread).
|
||||
|
||||
var shellCode = hasMailbox && hasEvalInWorker;
|
||||
var sabTestable = Atomics && SharedArrayBuffer && hasThreads && shellCode;
|
||||
|
||||
global.$262 = {
|
||||
__proto__: null,
|
||||
|
@ -19,6 +34,152 @@
|
|||
detachArrayBuffer: global.detachArrayBuffer,
|
||||
evalScript: global.evaluateScript || global.evaluate,
|
||||
global,
|
||||
agent: (function () {
|
||||
|
||||
// SpiderMonkey complication: With run-time argument --no-threads
|
||||
// our test runner will not properly filter test cases that can't be
|
||||
// run because agents can't be started, and so we do a little
|
||||
// filtering here: We will quietly succeed and exit if an agent test
|
||||
// should not have been run because threads cannot be started.
|
||||
//
|
||||
// Firefox complication: The test cases that use $262.agent can't
|
||||
// currently work in the browser, so for now we rely on them not
|
||||
// being run at all.
|
||||
|
||||
if (!sabTestable) {
|
||||
return {
|
||||
_notAvailable() {
|
||||
// See comment above.
|
||||
if (!hasThreads && shellCode) {
|
||||
global.reportCompare(0,0);
|
||||
global.quit(0);
|
||||
}
|
||||
throw new Error("Agents not available");
|
||||
},
|
||||
start(script) { this._notAvailable() },
|
||||
broadcast(sab, id) { this._notAvailable() },
|
||||
getReport() { this._notAvailable() },
|
||||
sleep(s) { this._notAvailable() }
|
||||
}
|
||||
}
|
||||
|
||||
// The SpiderMonkey implementation uses a designated shared buffer _ia
|
||||
// for coordination, and spinlocks for everything except sleeping.
|
||||
|
||||
var _MSG_LOC = 0; // Low bit set: broadcast available; High bits: seq #
|
||||
var _ID_LOC = 1; // ID sent with broadcast
|
||||
var _ACK_LOC = 2; // Worker increments this to ack that broadcast was received
|
||||
var _RDY_LOC = 3; // Worker increments this to ack that worker is up and running
|
||||
var _LOCKTXT_LOC = 4; // Writer lock for the text buffer: 0=open, 1=closed
|
||||
var _NUMTXT_LOC = 5; // Count of messages in text buffer
|
||||
var _NEXT_LOC = 6; // First free location in the buffer
|
||||
var _SLEEP_LOC = 7; // Used for sleeping
|
||||
|
||||
var _FIRST = 10; // First location of first message
|
||||
|
||||
var _ia = new Int32Array(new SharedArrayBuffer(65536));
|
||||
_ia[_NEXT_LOC] = _FIRST;
|
||||
|
||||
var _worker_prefix =
|
||||
// BEGIN WORKER PREFIX
|
||||
`if (typeof $262 == 'undefined')
|
||||
$262 = {};
|
||||
$262.agent = (function () {
|
||||
var _ia = new Int32Array(getSharedArrayBuffer());
|
||||
var agent = {
|
||||
receiveBroadcast(receiver) {
|
||||
var k;
|
||||
while (((k = Atomics.load(_ia, ${_MSG_LOC})) & 1) == 0)
|
||||
;
|
||||
var received_sab = getSharedArrayBuffer();
|
||||
var received_id = Atomics.load(_ia, ${_ID_LOC});
|
||||
Atomics.add(_ia, ${_ACK_LOC}, 1);
|
||||
while (Atomics.load(_ia, ${_MSG_LOC}) == k)
|
||||
;
|
||||
receiver(received_sab, received_id);
|
||||
},
|
||||
|
||||
report(msg) {
|
||||
while (Atomics.compareExchange(_ia, ${_LOCKTXT_LOC}, 0, 1) == 1)
|
||||
;
|
||||
msg = "" + msg;
|
||||
var i = _ia[${_NEXT_LOC}];
|
||||
_ia[i++] = msg.length;
|
||||
for ( let j=0 ; j < msg.length ; j++ )
|
||||
_ia[i++] = msg.charCodeAt(j);
|
||||
_ia[${_NEXT_LOC}] = i;
|
||||
Atomics.add(_ia, ${_NUMTXT_LOC}, 1);
|
||||
Atomics.store(_ia, ${_LOCKTXT_LOC}, 0);
|
||||
},
|
||||
|
||||
sleep(s) {
|
||||
Atomics.wait(_ia, ${_SLEEP_LOC}, 0, s);
|
||||
},
|
||||
|
||||
leaving() {}
|
||||
};
|
||||
Atomics.add(_ia, ${_RDY_LOC}, 1);
|
||||
return agent;
|
||||
})();`;
|
||||
// END WORKER PREFIX
|
||||
|
||||
return {
|
||||
_numWorkers: 0,
|
||||
_numReports: 0,
|
||||
_reportPtr: _FIRST,
|
||||
|
||||
_bailIfNotAvailable() {
|
||||
if (!sabTestable) {
|
||||
// See comment above.
|
||||
if (!hasThreads && shellCode) {
|
||||
global.reportCompare(0,0);
|
||||
global.quit(0);
|
||||
}
|
||||
throw new Error("Agents not available");
|
||||
}
|
||||
},
|
||||
|
||||
start(script) {
|
||||
this._bailIfNotAvailable();
|
||||
setSharedArrayBuffer(_ia.buffer);
|
||||
var oldrdy = Atomics.load(_ia, _RDY_LOC);
|
||||
evalInWorker(_worker_prefix + script);
|
||||
while (Atomics.load(_ia, _RDY_LOC) == oldrdy)
|
||||
;
|
||||
this._numWorkers++;
|
||||
},
|
||||
|
||||
broadcast(sab, id) {
|
||||
this._bailIfNotAvailable();
|
||||
setSharedArrayBuffer(sab);
|
||||
Atomics.store(_ia, _ID_LOC, id);
|
||||
Atomics.store(_ia, _ACK_LOC, 0);
|
||||
Atomics.add(_ia, _MSG_LOC, 1);
|
||||
while (Atomics.load(_ia, _ACK_LOC) < this._numWorkers)
|
||||
;
|
||||
Atomics.add(_ia, _MSG_LOC, 1);
|
||||
},
|
||||
|
||||
getReport() {
|
||||
this._bailIfNotAvailable();
|
||||
if (this._numReports == Atomics.load(_ia, _NUMTXT_LOC))
|
||||
return null;
|
||||
var s = "";
|
||||
var i = this._reportPtr;
|
||||
var len = _ia[i++];
|
||||
for ( let j=0 ; j < len ; j++ )
|
||||
s += String.fromCharCode(_ia[i++]);
|
||||
this._reportPtr = i;
|
||||
this._numReports++;
|
||||
return s;
|
||||
},
|
||||
|
||||
sleep(s) {
|
||||
this._bailIfNotAvailable();
|
||||
Atomics.wait(_ia, _SLEEP_LOC, 0, s);
|
||||
},
|
||||
};
|
||||
})()
|
||||
};
|
||||
})(this);
|
||||
|
||||
|
|
|
@ -243,6 +243,21 @@ function testFailed(message) {
|
|||
var FunctionToString = global.Function.prototype.toString;
|
||||
var ReflectApply = global.Reflect.apply;
|
||||
var NewGlobal = global.newGlobal;
|
||||
var Atomics = global.Atomics;
|
||||
var SharedArrayBuffer = global.SharedArrayBuffer;
|
||||
var Int32Array = global.Int32Array;
|
||||
var setSharedArrayBuffer = global.setSharedArrayBuffer;
|
||||
var getSharedArrayBuffer = global.getSharedArrayBuffer;
|
||||
var evalInWorker = global.evalInWorker;
|
||||
var hasThreads = ("helperThreadCount" in global ? global.helperThreadCount() > 0 : true);
|
||||
var hasMailbox = typeof setSharedArrayBuffer == "function" && typeof getSharedArrayBuffer == "function";
|
||||
var hasEvalInWorker = typeof evalInWorker == "function";
|
||||
|
||||
// The $262.agent framework is not appropriate for browsers yet, and some
|
||||
// test cases can't work in browsers (they block the main thread).
|
||||
|
||||
var shellCode = hasMailbox && hasEvalInWorker;
|
||||
var sabTestable = Atomics && SharedArrayBuffer && hasThreads && shellCode;
|
||||
|
||||
global.$262 = {
|
||||
__proto__: null,
|
||||
|
@ -255,6 +270,152 @@ function testFailed(message) {
|
|||
detachArrayBuffer: global.detachArrayBuffer,
|
||||
evalScript: global.evaluateScript || global.evaluate,
|
||||
global,
|
||||
agent: (function () {
|
||||
|
||||
// SpiderMonkey complication: With run-time argument --no-threads
|
||||
// our test runner will not properly filter test cases that can't be
|
||||
// run because agents can't be started, and so we do a little
|
||||
// filtering here: We will quietly succeed and exit if an agent test
|
||||
// should not have been run because threads cannot be started.
|
||||
//
|
||||
// Firefox complication: The test cases that use $262.agent can't
|
||||
// currently work in the browser, so for now we rely on them not
|
||||
// being run at all.
|
||||
|
||||
if (!sabTestable) {
|
||||
return {
|
||||
_notAvailable() {
|
||||
// See comment above.
|
||||
if (!hasThreads && shellCode) {
|
||||
global.reportCompare(0,0);
|
||||
global.quit(0);
|
||||
}
|
||||
throw new Error("Agents not available");
|
||||
},
|
||||
start(script) { this._notAvailable() },
|
||||
broadcast(sab, id) { this._notAvailable() },
|
||||
getReport() { this._notAvailable() },
|
||||
sleep(s) { this._notAvailable() }
|
||||
}
|
||||
}
|
||||
|
||||
// The SpiderMonkey implementation uses a designated shared buffer _ia
|
||||
// for coordination, and spinlocks for everything except sleeping.
|
||||
|
||||
var _MSG_LOC = 0; // Low bit set: broadcast available; High bits: seq #
|
||||
var _ID_LOC = 1; // ID sent with broadcast
|
||||
var _ACK_LOC = 2; // Worker increments this to ack that broadcast was received
|
||||
var _RDY_LOC = 3; // Worker increments this to ack that worker is up and running
|
||||
var _LOCKTXT_LOC = 4; // Writer lock for the text buffer: 0=open, 1=closed
|
||||
var _NUMTXT_LOC = 5; // Count of messages in text buffer
|
||||
var _NEXT_LOC = 6; // First free location in the buffer
|
||||
var _SLEEP_LOC = 7; // Used for sleeping
|
||||
|
||||
var _FIRST = 10; // First location of first message
|
||||
|
||||
var _ia = new Int32Array(new SharedArrayBuffer(65536));
|
||||
_ia[_NEXT_LOC] = _FIRST;
|
||||
|
||||
var _worker_prefix =
|
||||
// BEGIN WORKER PREFIX
|
||||
`if (typeof $262 == 'undefined')
|
||||
$262 = {};
|
||||
$262.agent = (function () {
|
||||
var _ia = new Int32Array(getSharedArrayBuffer());
|
||||
var agent = {
|
||||
receiveBroadcast(receiver) {
|
||||
var k;
|
||||
while (((k = Atomics.load(_ia, ${_MSG_LOC})) & 1) == 0)
|
||||
;
|
||||
var received_sab = getSharedArrayBuffer();
|
||||
var received_id = Atomics.load(_ia, ${_ID_LOC});
|
||||
Atomics.add(_ia, ${_ACK_LOC}, 1);
|
||||
while (Atomics.load(_ia, ${_MSG_LOC}) == k)
|
||||
;
|
||||
receiver(received_sab, received_id);
|
||||
},
|
||||
|
||||
report(msg) {
|
||||
while (Atomics.compareExchange(_ia, ${_LOCKTXT_LOC}, 0, 1) == 1)
|
||||
;
|
||||
msg = "" + msg;
|
||||
var i = _ia[${_NEXT_LOC}];
|
||||
_ia[i++] = msg.length;
|
||||
for ( let j=0 ; j < msg.length ; j++ )
|
||||
_ia[i++] = msg.charCodeAt(j);
|
||||
_ia[${_NEXT_LOC}] = i;
|
||||
Atomics.add(_ia, ${_NUMTXT_LOC}, 1);
|
||||
Atomics.store(_ia, ${_LOCKTXT_LOC}, 0);
|
||||
},
|
||||
|
||||
sleep(s) {
|
||||
Atomics.wait(_ia, ${_SLEEP_LOC}, 0, s);
|
||||
},
|
||||
|
||||
leaving() {}
|
||||
};
|
||||
Atomics.add(_ia, ${_RDY_LOC}, 1);
|
||||
return agent;
|
||||
})();`;
|
||||
// END WORKER PREFIX
|
||||
|
||||
return {
|
||||
_numWorkers: 0,
|
||||
_numReports: 0,
|
||||
_reportPtr: _FIRST,
|
||||
|
||||
_bailIfNotAvailable() {
|
||||
if (!sabTestable) {
|
||||
// See comment above.
|
||||
if (!hasThreads && shellCode) {
|
||||
global.reportCompare(0,0);
|
||||
global.quit(0);
|
||||
}
|
||||
throw new Error("Agents not available");
|
||||
}
|
||||
},
|
||||
|
||||
start(script) {
|
||||
this._bailIfNotAvailable();
|
||||
setSharedArrayBuffer(_ia.buffer);
|
||||
var oldrdy = Atomics.load(_ia, _RDY_LOC);
|
||||
evalInWorker(_worker_prefix + script);
|
||||
while (Atomics.load(_ia, _RDY_LOC) == oldrdy)
|
||||
;
|
||||
this._numWorkers++;
|
||||
},
|
||||
|
||||
broadcast(sab, id) {
|
||||
this._bailIfNotAvailable();
|
||||
setSharedArrayBuffer(sab);
|
||||
Atomics.store(_ia, _ID_LOC, id);
|
||||
Atomics.store(_ia, _ACK_LOC, 0);
|
||||
Atomics.add(_ia, _MSG_LOC, 1);
|
||||
while (Atomics.load(_ia, _ACK_LOC) < this._numWorkers)
|
||||
;
|
||||
Atomics.add(_ia, _MSG_LOC, 1);
|
||||
},
|
||||
|
||||
getReport() {
|
||||
this._bailIfNotAvailable();
|
||||
if (this._numReports == Atomics.load(_ia, _NUMTXT_LOC))
|
||||
return null;
|
||||
var s = "";
|
||||
var i = this._reportPtr;
|
||||
var len = _ia[i++];
|
||||
for ( let j=0 ; j < len ; j++ )
|
||||
s += String.fromCharCode(_ia[i++]);
|
||||
this._reportPtr = i;
|
||||
this._numReports++;
|
||||
return s;
|
||||
},
|
||||
|
||||
sleep(s) {
|
||||
this._bailIfNotAvailable();
|
||||
Atomics.wait(_ia, _SLEEP_LOC, 0, s);
|
||||
},
|
||||
};
|
||||
})()
|
||||
};
|
||||
})(this);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче