Bug 1131953 - SharedArrayBuffer mailbox for the shell. r=luke

This commit is contained in:
Lars T Hansen 2015-02-20 14:06:35 +01:00
Родитель b35c2674a2
Коммит 980f247ef3
1 изменённых файлов: 105 добавлений и 0 удалений

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

@ -72,6 +72,7 @@
#include "vm/HelperThreads.h"
#include "vm/Monitor.h"
#include "vm/Shape.h"
#include "vm/SharedArrayObject.h"
#include "vm/TypedArrayObject.h"
#include "vm/WrapperObject.h"
@ -4252,6 +4253,93 @@ IsLatin1(JSContext *cx, unsigned argc, Value *vp)
return true;
}
// Global mailbox that is used to communicate a SharedArrayBuffer
// value from one worker to another.
//
// For simplicity we store only the SharedArrayRawBuffer; retaining
// the SAB object would require per-runtime storage, and would have no
// real benefits.
//
// Invariant: when a SARB is in the mailbox its reference count is at
// least 1, accounting for the reference from the mailbox.
//
// The lock guards the mailbox variable and prevents a race where two
// workers try to set the mailbox at the same time to replace a SARB
// that is only referenced from the mailbox: the workers will both
// decrement the reference count on the old SARB, and one of those
// decrements will be on a garbage object. We could implement this
// with atomics and a CAS loop but it's not worth the bother.
static PRLock *sharedArrayBufferMailboxLock;
static SharedArrayRawBuffer *sharedArrayBufferMailbox;
static bool
InitSharedArrayBufferMailbox()
{
sharedArrayBufferMailboxLock = PR_NewLock();
return sharedArrayBufferMailboxLock != nullptr;
}
static void
DestructSharedArrayBufferMailbox()
{
// All workers need to have terminated at this point.
if (sharedArrayBufferMailbox)
sharedArrayBufferMailbox->dropReference();
PR_DestroyLock(sharedArrayBufferMailboxLock);
}
static bool
GetSharedArrayBuffer(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
JSObject *newObj = nullptr;
bool rval = true;
PR_Lock(sharedArrayBufferMailboxLock);
SharedArrayRawBuffer *buf = sharedArrayBufferMailbox;
if (buf) {
buf->addReference();
newObj = SharedArrayBufferObject::New(cx, buf);
if (!newObj) {
buf->dropReference();
rval = false;
}
}
PR_Unlock(sharedArrayBufferMailboxLock);
args.rval().setObjectOrNull(newObj);
return rval;
}
static bool
SetSharedArrayBuffer(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
SharedArrayRawBuffer *newBuffer = nullptr;
if (argc == 0 || args.get(0).isNullOrUndefined()) {
// Clear out the mailbox
}
else if (args.get(0).isObject() && args[0].toObject().is<SharedArrayBufferObject>()) {
newBuffer = args[0].toObject().as<SharedArrayBufferObject>().rawBufferObject();
newBuffer->addReference();
} else {
JS_ReportError(cx, "Only a SharedArrayBuffer can be installed in the global mailbox");
return false;
}
PR_Lock(sharedArrayBufferMailboxLock);
SharedArrayRawBuffer *oldBuffer = sharedArrayBufferMailbox;
if (oldBuffer)
oldBuffer->dropReference();
sharedArrayBufferMailbox = newBuffer;
PR_Unlock(sharedArrayBufferMailboxLock);
args.rval().setUndefined();
return true;
}
static const JSFunctionSpecWithHelp shell_functions[] = {
JS_FN_HELP("version", Version, 0, 0,
"version([number])",
@ -4445,6 +4533,18 @@ static const JSFunctionSpecWithHelp shell_functions[] = {
"evalInWorker(str)",
" Evaluate 'str' in a separate thread with its own runtime.\n"),
JS_FN_HELP("getSharedArrayBuffer", GetSharedArrayBuffer, 0, 0,
"getSharedArrayBuffer()",
" Retrieve the SharedArrayBuffer object from the cross-worker mailbox.\n"
" The object retrieved may not be identical to the object that was\n"
" installed, but it references the same shared memory.\n"
" getSharedArrayBuffer performs an ordering memory barrier.\n"),
JS_FN_HELP("setSharedArrayBuffer", SetSharedArrayBuffer, 0, 0,
"setSharedArrayBuffer()",
" Install the SharedArrayBuffer object in the cross-worker mailbox.\n"
" setSharedArrayBuffer performs an ordering memory barrier.\n"),
JS_FN_HELP("shapeOf", ShapeOf, 1, 0,
"shapeOf(obj)",
" Get the shape of obj (an implementation detail)."),
@ -6014,6 +6114,9 @@ main(int argc, char **argv, char **envp)
if (!JS_Init())
return 1;
if (!InitSharedArrayBufferMailbox())
return 1;
// The fake thread count must be set before initializing the Runtime,
// which spins up the thread pool.
int32_t threadCount = op.getIntOption("thread-count");
@ -6097,6 +6200,8 @@ main(int argc, char **argv, char **envp)
for (size_t i = 0; i < workerThreads.length(); i++)
PR_JoinThread(workerThreads[i]);
DestructSharedArrayBufferMailbox();
JS_DestroyRuntime(rt);
JS_ShutDown();
return result;