Bug 1088307 - Pull out WeakMap unbarriering to a single location, r=terrence
authorSteve Fink <sfink@mozilla.com>
Mon, 27 Oct 2014 14:11:31 -0700
changeset 212486 dab206576a0c8b52f60da153ffa1a732a44307a5
parent 212485 62a8be146b4bd63bd83771fed860958cf6964883
child 212487 5422ee0c1808856ace552e784447a039df823182
push id50993
push usersfink@mozilla.com
push dateTue, 28 Oct 2014 00:28:16 +0000
treeherdermozilla-inbound@5422ee0c1808 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence
bugs1088307
milestone36.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 1088307 - Pull out WeakMap unbarriering to a single location, r=terrence
js/src/jsweakmap.cpp
js/src/jsweakmap.h
js/src/vm/ScopeObject.cpp
--- a/js/src/jsweakmap.cpp
+++ b/js/src/jsweakmap.cpp
@@ -347,33 +347,20 @@ TryPreserveReflector(JSContext *cx, Hand
     }
     return true;
 }
 
 static inline void
 WeakMapPostWriteBarrier(JSRuntime *rt, ObjectValueMap *weakMap, JSObject *key)
 {
 #ifdef JSGC_GENERATIONAL
-    /*
-     * Strip the barriers from the type before inserting into the store buffer.
-     * This will automatically ensure that barriers do not fire during GC.
-     *
-     * Some compilers complain about instantiating the WeakMap class for
-     * unbarriered type arguments, so we cast to a HashMap instead.  Because of
-     * WeakMap's multiple inheritace, We need to do this in two stages, first to
-     * the HashMap base class and then to the unbarriered version.
-     */
-    ObjectValueMap::Base *baseHashMap = static_cast<ObjectValueMap::Base *>(weakMap);
-
-    typedef HashMap<JSObject *, Value> UnbarrieredMap;
-    UnbarrieredMap *unbarrieredMap = reinterpret_cast<UnbarrieredMap *>(baseHashMap);
-
-    typedef HashKeyRef<UnbarrieredMap, JSObject *> Ref;
+    // Strip the barriers from the type before inserting into the store buffer.
+    // This will automatically ensure that barriers do not fire during GC.
     if (key && IsInsideNursery(key))
-        rt->gc.storeBuffer.putGeneric(Ref((unbarrieredMap), key));
+        rt->gc.storeBuffer.putGeneric(UnbarrieredRef(weakMap, key));
 #endif
 }
 
 static MOZ_ALWAYS_INLINE bool
 SetWeakMapEntryInternal(JSContext *cx, Handle<WeakMapObject*> mapObj,
                         HandleObject key, HandleValue value)
 {
     ObjectValueMap *map = mapObj->getMap();
--- a/js/src/jsweakmap.h
+++ b/js/src/jsweakmap.h
@@ -7,16 +7,17 @@
 #ifndef jsweakmap_h
 #define jsweakmap_h
 
 #include "jscompartment.h"
 #include "jsfriendapi.h"
 #include "jsobj.h"
 
 #include "gc/Marking.h"
+#include "gc/StoreBuffer.h"
 #include "js/HashTable.h"
 
 namespace js {
 
 // A subclass template of js::HashMap whose keys and values may be garbage-collected. When
 // a key is collected, the table entry disappears, dropping its reference to the value.
 //
 // More precisely:
@@ -274,16 +275,38 @@ protected:
             MOZ_ASSERT(!gc::IsAboutToBeFinalized(&k));
             MOZ_ASSERT(!gc::IsAboutToBeFinalized(&r.front().value()));
             MOZ_ASSERT(k == r.front().key());
         }
 #endif
     }
 };
 
+/*
+ * At times, you will need to ignore barriers when accessing WeakMap entries.
+ * Localize the templatized casting craziness here.
+ */
+template <class Key, class Value>
+static inline gc::HashKeyRef<HashMap<Key, Value, DefaultHasher<Key>, RuntimeAllocPolicy>, Key>
+UnbarrieredRef(WeakMap<PreBarriered<Key>, RelocatablePtr<Value>> *map, Key key)
+{
+    /*
+     * Some compilers complain about instantiating the WeakMap class for
+     * unbarriered type arguments, so we cast to a HashMap instead. Because of
+     * WeakMap's multiple inheritance, we need to do this in two stages, first
+     * to the HashMap base class and then to the unbarriered version.
+     */
+
+    typedef typename WeakMap<PreBarriered<Key>, RelocatablePtr<Value>>::Base BaseMap;
+    auto baseMap = static_cast<BaseMap*>(map);
+    typedef HashMap<Key, Value, DefaultHasher<Key>, RuntimeAllocPolicy> UnbarrieredMap;
+    typedef gc::HashKeyRef<UnbarrieredMap, Key> UnbarrieredKeyRef;
+    return UnbarrieredKeyRef(reinterpret_cast<UnbarrieredMap*>(baseMap), key);
+}
+
 /* WeakMap methods exposed so they can be installed in the self-hosting global. */
 
 extern JSObject *
 InitBareWeakMapCtor(JSContext *cx, js::HandleObject obj);
 
 extern bool
 WeakMap_has(JSContext *cx, unsigned argc, Value *vp);
 
--- a/js/src/vm/ScopeObject.cpp
+++ b/js/src/vm/ScopeObject.cpp
@@ -1841,33 +1841,18 @@ js_IsDebugScopeSlow(ProxyObject *proxy)
 
 /*****************************************************************************/
 
 /* static */ MOZ_ALWAYS_INLINE void
 DebugScopes::proxiedScopesPostWriteBarrier(JSRuntime *rt, ObjectWeakMap *map,
                                            const PreBarrieredObject &key)
 {
 #ifdef JSGC_GENERATIONAL
-    /*
-     * Strip the barriers from the type before inserting into the store buffer.
-     * This will automatically ensure that barriers do not fire during GC.
-     *
-     * Some compilers complain about instantiating the WeakMap class for
-     * unbarriered type arguments, so we cast to a HashMap instead.  Because of
-     * WeakMap's multiple inheritace, We need to do this in two stages, first to
-     * the HashMap base class and then to the unbarriered version.
-     */
-    ObjectWeakMap::Base *baseHashMap = static_cast<ObjectWeakMap::Base *>(map);
-
-    typedef HashMap<JSObject *, JSObject *> UnbarrieredMap;
-    UnbarrieredMap *unbarrieredMap = reinterpret_cast<UnbarrieredMap *>(baseHashMap);
-
-    typedef gc::HashKeyRef<UnbarrieredMap, JSObject *> Ref;
     if (key && IsInsideNursery(key))
-        rt->gc.storeBuffer.putGeneric(Ref(unbarrieredMap, key.get()));
+        rt->gc.storeBuffer.putGeneric(UnbarrieredRef(map, key.get()));
 #endif
 }
 
 #ifdef JSGC_GENERATIONAL
 class DebugScopes::MissingScopesRef : public gc::BufferableRef
 {
     MissingScopeMap *map;
     ScopeIterKey key;