Bug 1412852 - Make the JS shell SAB mailbox transmit the length. r=luke
authorLars T Hansen <lhansen@mozilla.com>
Wed, 08 Nov 2017 16:35:45 +0100
changeset 393129 bb88efd97a282d4ec1c517903a684360497d848f
parent 393128 a2f237ccf5bf2ac923bbf8d2cb1b175a50e3f532
child 393130 2d62270047217e43ce7a8c4931b5c95b0f7b0f0c
push id97587
push userlhansen@mozilla.com
push dateWed, 22 Nov 2017 12:18:33 +0000
treeherdermozilla-inbound@2d6227004721 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs1412852
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1412852 - Make the JS shell SAB mailbox transmit the length. r=luke
js/src/shell/js.cpp
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -87,16 +87,17 @@
 #include "js/StructuredClone.h"
 #include "js/SweepingAPI.h"
 #include "js/TrackedOptimizationInfo.h"
 #include "perf/jsperf.h"
 #include "shell/jsoptparse.h"
 #include "shell/jsshell.h"
 #include "shell/OSObject.h"
 #include "threading/ConditionVariable.h"
+#include "threading/ExclusiveData.h"
 #include "threading/LockGuard.h"
 #include "threading/Thread.h"
 #include "vm/ArgumentsObject.h"
 #include "vm/AsyncFunction.h"
 #include "vm/AsyncIteration.h"
 #include "vm/Compression.h"
 #include "vm/Debugger.h"
 #include "vm/HelperThreads.h"
@@ -5554,96 +5555,112 @@ DisableGeckoProfiling(JSContext* cx, uns
 //
 // 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 Mutex* sharedArrayBufferMailboxLock;
-static SharedArrayRawBuffer* sharedArrayBufferMailbox;
+struct SharedArrayBufferMailbox
+{
+    SharedArrayBufferMailbox() : buffer(nullptr), length(0) {}
+
+    SharedArrayRawBuffer* buffer;
+    uint32_t              length;
+};
+
+typedef ExclusiveData<SharedArrayBufferMailbox> SABMailbox;
+
+// Never null after successful initialization.
+static SABMailbox* sharedArrayBufferMailbox;
 
 static bool
 InitSharedArrayBufferMailbox()
 {
-    sharedArrayBufferMailboxLock = js_new<Mutex>(mutexid::ShellArrayBufferMailbox);
-    return sharedArrayBufferMailboxLock != nullptr;
+    sharedArrayBufferMailbox = js_new<SABMailbox>(mutexid::ShellArrayBufferMailbox);
+    return sharedArrayBufferMailbox != nullptr;
 }
 
 static void
 DestructSharedArrayBufferMailbox()
 {
     // All workers need to have terminated at this point.
-    if (sharedArrayBufferMailbox)
-        sharedArrayBufferMailbox->dropReference();
-    js_delete(sharedArrayBufferMailboxLock);
+
+    {
+        auto mbx = sharedArrayBufferMailbox->lock();
+        if (mbx->buffer)
+            mbx->buffer->dropReference();
+    }
+
+    js_delete(sharedArrayBufferMailbox);
+    sharedArrayBufferMailbox = nullptr;
 }
 
 static bool
 GetSharedArrayBuffer(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     JSObject* newObj = nullptr;
 
     {
-        sharedArrayBufferMailboxLock->lock();
-        auto unlockMailbox = MakeScopeExit([]() { sharedArrayBufferMailboxLock->unlock(); });
-
-        SharedArrayRawBuffer* buf = sharedArrayBufferMailbox;
-        if (buf) {
+        auto mbx = sharedArrayBufferMailbox->lock();
+
+        if (SharedArrayRawBuffer* buf = mbx->buffer) {
             if (!buf->addReference()) {
                 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_SC_SAB_REFCNT_OFLO);
                 return false;
             }
 
             // Shared memory is enabled globally in the shell: there can't be a worker
             // that does not enable it if the main thread has it.
             MOZ_ASSERT(cx->compartment()->creationOptions().getSharedMemoryAndAtomicsEnabled());
-            SharedArrayRawBuffer::Lock l(buf);
-            newObj = SharedArrayBufferObject::New(cx, buf, buf->byteLength(l));
+
+            newObj = SharedArrayBufferObject::New(cx, buf, mbx->length);
             if (!newObj) {
                 buf->dropReference();
                 return false;
             }
         }
     }
 
     args.rval().setObjectOrNull(newObj);
     return true;
 }
 
 static bool
 SetSharedArrayBuffer(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     SharedArrayRawBuffer* newBuffer = nullptr;
-
-    if (argc == 0 || args.get(0).isNullOrUndefined()) {
+    uint32_t newLength = 0;
+
+    if (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();
+        newLength = args[0].toObject().as<SharedArrayBufferObject>().byteLength();
         if (!newBuffer->addReference()) {
             JS_ReportErrorASCII(cx, "Reference count overflow on SharedArrayBuffer");
             return false;
         }
     } else {
         JS_ReportErrorASCII(cx, "Only a SharedArrayBuffer can be installed in the global mailbox");
         return false;
     }
 
     {
-        sharedArrayBufferMailboxLock->lock();
-        auto unlockMailbox = MakeScopeExit([]() { sharedArrayBufferMailboxLock->unlock(); });
-
-        SharedArrayRawBuffer* oldBuffer = sharedArrayBufferMailbox;
-        if (oldBuffer)
+        auto mbx = sharedArrayBufferMailbox->lock();
+
+        if (SharedArrayRawBuffer* oldBuffer = mbx->buffer)
             oldBuffer->dropReference();
-        sharedArrayBufferMailbox = newBuffer;
+
+        mbx->buffer = newBuffer;
+        mbx->length = newLength;
     }
 
     args.rval().setUndefined();
     return true;
 }
 
 struct BufferStreamJob
 {