Bug 1081277 - OdinMonkey: maintain list of asm.js modules in the runtime (r=bbouvier)
authorLuke Wagner <luke@mozilla.com>
Tue, 14 Oct 2014 10:58:21 -0500
changeset 210616 88497210b950bb6e77d603fc5677eecbfef9627f
parent 210615 8d4702c0db518445e34ada90e42bba24bfbe2a84
child 210617 20aa7722f330ac3a58c418fa2ebfb969ca4b7847
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersbbouvier
bugs1081277
milestone36.0a1
Bug 1081277 - OdinMonkey: maintain list of asm.js modules in the runtime (r=bbouvier)
js/src/asmjs/AsmJSLink.cpp
js/src/asmjs/AsmJSModule.cpp
js/src/asmjs/AsmJSModule.h
js/src/vm/Runtime.cpp
js/src/vm/Runtime.h
--- a/js/src/asmjs/AsmJSLink.cpp
+++ b/js/src/asmjs/AsmJSLink.cpp
@@ -496,17 +496,17 @@ LinkModuleToHeap(JSContext *cx, AsmJSMod
 
     module.initHeap(heap, cx);
     return true;
 }
 
 static bool
 DynamicallyLinkModule(JSContext *cx, CallArgs args, AsmJSModule &module)
 {
-    module.setIsDynamicallyLinked();
+    module.setIsDynamicallyLinked(cx->runtime());
 
     HandleValue globalVal = args.get(0);
     HandleValue importVal = args.get(1);
     HandleValue bufferVal = args.get(2);
 
     Rooted<ArrayBufferObjectMaybeShared *> heap(cx);
     if (module.hasArrayView()) {
         if (IsArrayBuffer(bufferVal) || IsSharedArrayBuffer(bufferVal))
--- a/js/src/asmjs/AsmJSModule.cpp
+++ b/js/src/asmjs/AsmJSModule.cpp
@@ -73,16 +73,18 @@ AsmJSModule::AsmJSModule(ScriptSource *s
   : srcStart_(srcStart),
     srcBodyStart_(srcBodyStart),
     scriptSource_(scriptSource),
     globalArgumentName_(nullptr),
     importArgumentName_(nullptr),
     bufferArgumentName_(nullptr),
     code_(nullptr),
     interruptExit_(nullptr),
+    prevLinked_(nullptr),
+    nextLinked_(nullptr),
     dynamicallyLinked_(false),
     loadedFromCache_(false),
     profilingEnabled_(false),
     interrupted_(false),
     codeIsProtected_(false)
 {
     mozilla::PodZero(&pod);
     pod.funcPtrTableAndExitBytes_ = SIZE_MAX;
@@ -111,16 +113,21 @@ AsmJSModule::~AsmJSModule()
             exitDatum.ionScript->removeDependentAsmJSModule(exit);
         }
 
         DeallocateExecutableMemory(code_, pod.totalBytes_, AsmJSPageSize);
     }
 
     for (size_t i = 0; i < numFunctionCounts(); i++)
         js_delete(functionCounts(i));
+
+    if (prevLinked_)
+        *prevLinked_ = nextLinked_;
+    if (nextLinked_)
+        nextLinked_->prevLinked_ = prevLinked_;
 }
 
 void
 AsmJSModule::trace(JSTracer *trc)
 {
     for (unsigned i = 0; i < globals_.length(); i++)
         globals_[i].trace(trc);
     for (unsigned i = 0; i < exits_.length(); i++) {
--- a/js/src/asmjs/AsmJSModule.h
+++ b/js/src/asmjs/AsmJSModule.h
@@ -814,16 +814,18 @@ class AsmJSModule
     ScriptSource *                        scriptSource_;
     PropertyName *                        globalArgumentName_;
     PropertyName *                        importArgumentName_;
     PropertyName *                        bufferArgumentName_;
     uint8_t *                             code_;
     uint8_t *                             interruptExit_;
     StaticLinkData                        staticLinkData_;
     HeapPtrArrayBufferObjectMaybeShared   maybeHeap_;
+    AsmJSModule **                        prevLinked_;
+    AsmJSModule *                         nextLinked_;
     bool                                  dynamicallyLinked_;
     bool                                  loadedFromCache_;
     bool                                  profilingEnabled_;
     bool                                  interrupted_;
 
     // This field is accessed concurrently when requesting an interrupt.
     // Access must be synchronized via the runtime's interrupt lock.
     mutable bool                          codeIsProtected_;
@@ -1444,33 +1446,45 @@ class AsmJSModule
     // linked" which specializes the code to its current address (this allows
     // code to be relocated between serialization and deserialization).
     void staticallyLink(ExclusiveContext *cx);
 
     // After a module is statically linked, it is "dynamically linked" which
     // specializes it to a particular set of arguments. In particular, this
     // binds the code to a particular heap (via initHeap) and set of global
     // variables. A given asm.js module cannot be dynamically linked more than
-    // once so, if JS tries, the module is cloned.
-    void setIsDynamicallyLinked() {
+    // once so, if JS tries, the module is cloned. When linked, an asm.js module
+    // is kept in a list so that it can be updated if the linked buffer is
+    // detached.
+    void setIsDynamicallyLinked(JSRuntime *rt) {
         MOZ_ASSERT(!isDynamicallyLinked());
         dynamicallyLinked_ = true;
+        nextLinked_ = rt->linkedAsmJSModules;
+        prevLinked_ = &rt->linkedAsmJSModules;
+        if (nextLinked_)
+            nextLinked_->prevLinked_ = &nextLinked_;
+        rt->linkedAsmJSModules = this;
         MOZ_ASSERT(isDynamicallyLinked());
     }
+
     void initHeap(Handle<ArrayBufferObjectMaybeShared*> heap, JSContext *cx);
     void restoreHeapToInitialState(ArrayBufferObjectMaybeShared *maybePrevBuffer);
     void restoreToInitialState(ArrayBufferObjectMaybeShared *maybePrevBuffer,
                                uint8_t *prevCode,
                                ExclusiveContext *cx);
     bool clone(JSContext *cx, ScopedJSDeletePtr<AsmJSModule> *moduleOut) const;
     bool changeHeap(Handle<ArrayBufferObject*> newHeap, JSContext *cx);
 
     /*************************************************************************/
     // Functions that can be called after dynamic linking succeeds:
 
+    AsmJSModule *nextLinked() const {
+        MOZ_ASSERT(isDynamicallyLinked());
+        return nextLinked_;
+    }
     CodePtr entryTrampoline(const ExportedFunction &func) const {
         MOZ_ASSERT(isDynamicallyLinked());
         MOZ_ASSERT(!func.isChangeHeap());
         return JS_DATA_TO_FUNC_PTR(CodePtr, code_ + func.pod.codeOffset_);
     }
     uint8_t *interruptExit() const {
         MOZ_ASSERT(isDynamicallyLinked());
         return interruptExit_;
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -192,16 +192,17 @@ JSRuntime::JSRuntime(JSRuntime *parentRu
     defaultFreeOp_(thisFromCtor()),
     debuggerMutations(0),
     securityCallbacks(const_cast<JSSecurityCallbacks *>(&NullSecurityCallbacks)),
     DOMcallbacks(nullptr),
     destroyPrincipals(nullptr),
     structuredCloneCallbacks(nullptr),
     telemetryCallback(nullptr),
     errorReporter(nullptr),
+    linkedAsmJSModules(nullptr),
     propertyRemovals(0),
 #if !EXPOSE_INTL_API
     thousandsSeparator(0),
     decimalSeparator(0),
     numGrouping(0),
 #endif
     mathCache_(nullptr),
     activeCompilations_(0),
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -73,16 +73,17 @@ js_ReportAllocationOverflow(js::ThreadSa
 extern void
 js_ReportOverRecursed(js::ThreadSafeContext *cx);
 
 namespace js {
 
 class Activation;
 class ActivationIterator;
 class AsmJSActivation;
+class AsmJSModule;
 class MathCache;
 
 namespace jit {
 class JitRuntime;
 class JitActivation;
 struct PcScriptCache;
 class Simulator;
 class SimulatorRuntime;
@@ -1075,17 +1076,20 @@ struct JSRuntime : public JS::shadow::Ru
 
     /* Call this to accumulate telemetry data. */
     JSAccumulateTelemetryDataCallback telemetryCallback;
 
     /* Optional error reporter. */
     JSErrorReporter     errorReporter;
 
     /* AsmJSCache callbacks are runtime-wide. */
-    JS::AsmJSCacheOps asmJSCacheOps;
+    JS::AsmJSCacheOps   asmJSCacheOps;
+
+    /* Head of the linked list of linked asm.js modules. */
+    js::AsmJSModule    *linkedAsmJSModules;
 
     /*
      * The propertyRemovals counter is incremented for every JSObject::clear,
      * and for each JSObject::remove method call that frees a slot in the given
      * object. See js_NativeGet and js_NativeSet in jsobj.cpp.
      */
     uint32_t            propertyRemovals;