Bug 848592 - Mark memory accessed by dynamic rooting analysis as defined, r=njn
☠☠ backed out by 9c2358efab23 ☠ ☠
authorSteve Fink <sfink@mozilla.com>
Wed, 06 Mar 2013 15:56:35 -0800
changeset 145651 55fa2277a70226c70c99db95a71007b6a90567ad
parent 145650 37c3c32546e44d6c65e2587915408d31862492f9
child 145652 44465f14b9826ac1e6f9006987df7fd5200e4713
push id2697
push userbbajaj@mozilla.com
push dateMon, 05 Aug 2013 18:49:53 +0000
treeherdermozilla-beta@dfec938c7b63 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnjn
bugs848592
milestone24.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 848592 - Mark memory accessed by dynamic rooting analysis as defined, r=njn
js/public/RootingAPI.h
js/src/gc/Verifier.cpp
--- a/js/public/RootingAPI.h
+++ b/js/public/RootingAPI.h
@@ -584,18 +584,20 @@ class MOZ_STACK_CLASS Rooted : public js
 
   private:
     void commonInit(Rooted<void*> **thingGCRooters) {
 #if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
         js::ThingRootKind kind = js::RootMethods<T>::kind();
         this->stack = &thingGCRooters[kind];
         this->prev = *stack;
         *stack = reinterpret_cast<Rooted<void*>*>(this);
-
+# ifdef JSGC_ROOT_ANALYSIS
+        this->scanned = false;
         JS_ASSERT(!js::RootMethods<T>::poisoned(ptr));
+# endif
 #endif
     }
 
 #if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
     Rooted<void*> **stack, *prev;
 #endif
 
 #if defined(DEBUG) && defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
--- a/js/src/gc/Verifier.cpp
+++ b/js/src/gc/Verifier.cpp
@@ -54,22 +54,50 @@ CheckStackRootThing(uintptr_t *w, Rooted
     return rootp->address() == static_cast<void*>(w);
 }
 
 struct Rooter {
     Rooted<void*> *rooter;
     ThingRootKind kind;
 };
 
+// Temporarily mark a region of memory as defined for valgrind's purposes, so
+// that we don't get false positive warnings due to examining or poisoning
+// undefined memory that happens to look like gcthing pointers. The advantage
+// of using this RAII class over an unconditional VALGRIND_MAKE_MEM_DEFINED is
+// that it is reverted to undefined afterwards, so that true uses of undefined
+// memory will not be suppressed.
+template <typename T>
+struct AutoMarkDefinedForValgrind {
+    static const unsigned int VALGRIND_RUNNING_AND_REQUEST_SUCCESSFUL = 1;
+
+    T *ptr_;
+    bool active;
+    uint8_t defined[sizeof(T)];
+    AutoMarkDefinedForValgrind(T *ptr)
+        : ptr_(ptr), active(true)
+    {
+        // The 'v bits' are Valgrind's representation of whether a valid is defined
+        active = (VALGRIND_GET_VBITS(ptr_, defined, sizeof(T)) ==
+                  VALGRIND_RUNNING_AND_REQUEST_SUCCESSFUL);
+        VALGRIND_MAKE_MEM_DEFINED(ptr_, sizeof(T));
+    }
+    ~AutoMarkDefinedForValgrind() {
+        if (active)
+            (void) VALGRIND_SET_VBITS(ptr_, defined, sizeof(T));
+    }
+};
+
 static void
 CheckStackRoot(JSRuntime *rt, uintptr_t *w, Rooter *begin, Rooter *end)
 {
     /* Mark memory as defined for valgrind, as in MarkWordConservatively. */
 #ifdef MOZ_VALGRIND
     VALGRIND_MAKE_MEM_DEFINED(&w, sizeof(w));
+    AutoMarkDefinedForValgrind<uintptr_t> define(w);
 #endif
 
     void *thing = GetAddressableGCThing(rt, *w);
     if (!thing)
         return;
 
     /* Don't check atoms as these will never be subject to generational collection. */
     if (static_cast<Cell *>(thing)->tenuredZone() == rt->atomsCompartment->zone())