Bug 1254893 - Followup: read barrier wasm modules exposed via Debugger.findScript. (r=luke)
authorShu-yu Guo <shu@rfrn.org>
Fri, 11 Mar 2016 23:52:56 -0800
changeset 288420 a3a44b86faaa69c219b039d80ba26f143c9cd26b
parent 288419 ec2bed5822e5af65e700c1dfaf59c41bbe7eb5c6
child 288421 ba5dd6053cc4351e58ad407d8ef96a6dfcf344d4
push id30079
push userryanvm@gmail.com
push dateSat, 12 Mar 2016 20:24:19 +0000
treeherdermozilla-central@d1d47ba19ce9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs1254893
milestone48.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 1254893 - Followup: read barrier wasm modules exposed via Debugger.findScript. (r=luke)
js/src/asmjs/Wasm.cpp
js/src/asmjs/WasmModule.cpp
js/src/asmjs/WasmModule.h
js/src/jscompartment.h
js/src/vm/Debugger-inl.h
js/src/vm/Debugger.cpp
--- a/js/src/asmjs/Wasm.cpp
+++ b/js/src/asmjs/Wasm.cpp
@@ -1449,17 +1449,16 @@ DecodeModule(JSContext* cx, UniqueChars 
 
     moduleObj.set(WasmModuleObject::create(cx));
     if (!moduleObj)
         return false;
 
     if (!moduleObj->init(cx->new_<Module>(Move(module))))
         return false;
 
-    cx->compartment()->wasmModules.insertBack(&moduleObj->module());
     return moduleObj->module().staticallyLink(cx, *staticLink);
 }
 
 /*****************************************************************************/
 // Top-level functions
 
 bool
 wasm::HasCompilerSupport(ExclusiveContext* cx)
--- a/js/src/asmjs/WasmModule.cpp
+++ b/js/src/asmjs/WasmModule.cpp
@@ -901,16 +901,22 @@ Module::trace(JSTracer* trc)
     if (heap_)
         TraceEdge(trc, &heap_, "wasm buffer");
 
     MOZ_ASSERT(ownerObject_);
     TraceEdge(trc, &ownerObject_, "wasm owner object");
 }
 
 /* virtual */ void
+Module::readBarrier()
+{
+    InternalBarrierMethods<JSObject*>::readBarrier(owner());
+}
+
+/* virtual */ void
 Module::addSizeOfMisc(MallocSizeOf mallocSizeOf, size_t* code, size_t* data)
 {
     *code += codeBytes();
     *data += mallocSizeOf(this) +
              globalBytes() +
              mallocSizeOf(module_.get()) +
              module_->sizeOfExcludingThis(mallocSizeOf) +
              funcPtrTables_.sizeOfExcludingThis(mallocSizeOf) +
--- a/js/src/asmjs/WasmModule.h
+++ b/js/src/asmjs/WasmModule.h
@@ -509,16 +509,17 @@ class Module : public mozilla::LinkedLis
   public:
     static const unsigned SizeOfImportExit = sizeof(ImportExit);
     static const unsigned OffsetOfImportExitFun = offsetof(ImportExit, fun);
     static const unsigned SizeOfEntryArg = sizeof(EntryArg);
 
     explicit Module(UniqueModuleData module);
     virtual ~Module();
     virtual void trace(JSTracer* trc);
+    virtual void readBarrier();
     virtual void addSizeOfMisc(MallocSizeOf mallocSizeOf, size_t* code, size_t* data);
 
     void setOwner(WasmModuleObject* owner) { MOZ_ASSERT(!ownerObject_); ownerObject_ = owner; }
     inline const HeapPtr<WasmModuleObject*>& owner() const;
 
     uint8_t* code() const { return module_->code.get(); }
     uint32_t codeBytes() const { return module_->codeBytes; }
     uint8_t* globalData() const { return code() + module_->codeBytes; }
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -465,18 +465,20 @@ struct JSCompartment
     // Inline transparent typed objects do not initially have an array buffer,
     // but can have that buffer created lazily if it is accessed later. This
     // table manages references from such typed objects to their buffers.
     js::ObjectWeakMap* lazyArrayBuffers;
 
     // All unboxed layouts in the compartment.
     mozilla::LinkedList<js::UnboxedLayout> unboxedLayouts;
 
-    // All wasm modules in the compartment.
-    mozilla::LinkedList<js::wasm::Module> wasmModules;
+    // All wasm modules in the compartment. Weakly held.
+    //
+    // The caller needs to call wasm::Module::readBarrier() manually!
+    mozilla::LinkedList<js::wasm::Module> wasmModuleWeakList;
 
   private:
     // All non-syntactic lexical scopes in the compartment. These are kept in
     // a map because when loading scripts into a non-syntactic scope, we need
     // to use the same lexical scope to persist lexical bindings.
     js::ObjectWeakMap* nonSyntacticLexicalScopes_;
 
   public:
--- a/js/src/vm/Debugger-inl.h
+++ b/js/src/vm/Debugger-inl.h
@@ -87,13 +87,16 @@ js::Debugger::onIonCompilation(JSContext
         return;
 
     slowPathOnIonCompilation(cx, scripts, graph);
 }
 
 /* static */ void
 js::Debugger::onNewWasmModule(JSContext* cx, Handle<WasmModuleObject*> wasmModule)
 {
+    // Insert the wasm::Module into a compartment-wide list for discovery
+    // later without a heap walk.
+    cx->compartment()->wasmModuleWeakList.insertBack(&wasmModule->module());
     if (cx->compartment()->isDebuggee())
         slowPathOnNewWasmModule(cx, wasmModule);
 }
 
 #endif /* vm_Debugger_inl_h */
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -4066,18 +4066,18 @@ class MOZ_STACK_CLASS Debugger::ScriptQu
                     return false;
                 }
             }
         }
 
         // TODOshu: Until such time that wasm modules are real ES6 modules,
         // unconditionally consider all wasm toplevel module scripts.
         for (WeakGlobalObjectSet::Range r = debugger->allDebuggees(); !r.empty(); r.popFront()) {
-            for (wasm::Module* module : r.front()->compartment()->wasmModules)
-                consider(module->owner());
+            for (wasm::Module* module : r.front()->compartment()->wasmModuleWeakList)
+                consider(module);
         }
 
         return true;
     }
 
     Handle<ScriptVector> foundScripts() const {
         return vector;
     }
@@ -4299,24 +4299,29 @@ class MOZ_STACK_CLASS Debugger::ScriptQu
 
         return;
     }
 
     /*
      * If |wasmModule| matches this query, append it to |wasmModuleVector|.
      * Set |oom| if an out of memory condition occurred.
      */
-    void consider(WasmModuleObject* wasmModule) {
+    void consider(wasm::Module* wasmModule) {
         if (oom)
             return;
 
-        if (hasSource && source != AsVariant(wasmModule))
+        WasmModuleObject* moduleObject = wasmModule->owner();
+        if (hasSource && source != AsVariant(moduleObject))
             return;
 
-        if (!wasmModuleVector.append(wasmModule))
+        // The compartment-wide wasm::Module list is held weakly. Read barrier
+        // the ones we intend to expose.
+        wasmModule->readBarrier();
+
+        if (!wasmModuleVector.append(moduleObject))
             oom = true;
     }
 };
 
 /* static */ bool
 Debugger::findScripts(JSContext* cx, unsigned argc, Value* vp)
 {
     THIS_DEBUGGER(cx, argc, vp, "findScripts", args, dbg);