Bug 1288909, part 4 - Use a strong reference to the set in ClassInfo2NativeSetMap. r=billm draft
authorAndrew McCreight <continuation@gmail.com>
Tue, 06 Sep 2016 12:58:27 -0700
changeset 414167 3fdcd659011c5f2d0d6d4851a6bd8c74d90ce857
parent 414166 a5911f3cd512cfefccd446315d2c2fd120e34fcd
child 414168 edbd8ea023ac0f4a93cab4439144c78565e42f94
child 414169 74a2156028d9b34ab8f371923da472956d0bee31
push id29606
push userbmo:continuation@gmail.com
push dateThu, 15 Sep 2016 19:59:29 +0000
reviewersbillm
bugs1288909
milestone51.0a1
Bug 1288909, part 4 - Use a strong reference to the set in ClassInfo2NativeSetMap. r=billm Entries should end up getting cleared out from this table before the value dies, so let's just make the reference strong so that any mistakes will result in leaks and not use-after-frees. Using smart pointer classes with PLDHashtable is a little questionable, and I don't want to convert this one hash table to nsTHashtable, so I use manual addref and release. MozReview-Commit-ID: Kfg9veS6r11
js/xpconnect/src/XPCMaps.cpp
js/xpconnect/src/XPCMaps.h
--- a/js/xpconnect/src/XPCMaps.cpp
+++ b/js/xpconnect/src/XPCMaps.cpp
@@ -197,24 +197,51 @@ IID2NativeInterfaceMap::SizeOfIncludingT
     }
     return n;
 }
 
 /***************************************************************************/
 // implement ClassInfo2NativeSetMap...
 
 // static
+bool ClassInfo2NativeSetMap::Entry::Match(const PLDHashEntryHdr* aEntry,
+                                          const void* aKey)
+{
+    return static_cast<const Entry*>(aEntry)->key == aKey;
+}
+
+// static
+void ClassInfo2NativeSetMap::Entry::Clear(PLDHashTable* aTable,
+                                          PLDHashEntryHdr* aEntry)
+{
+    auto entry = static_cast<Entry*>(aEntry);
+    NS_RELEASE(entry->value);
+
+    entry->key = nullptr;
+    entry->value = nullptr;
+}
+
+const PLDHashTableOps ClassInfo2NativeSetMap::Entry::sOps =
+{
+    PLDHashTable::HashVoidPtrKeyStub,
+    Match,
+    PLDHashTable::MoveEntryStub,
+    Clear,
+    nullptr
+};
+
+// static
 ClassInfo2NativeSetMap*
 ClassInfo2NativeSetMap::newMap(int length)
 {
     return new ClassInfo2NativeSetMap(length);
 }
 
 ClassInfo2NativeSetMap::ClassInfo2NativeSetMap(int length)
-  : mTable(PLDHashTable::StubOps(), sizeof(Entry), length)
+  : mTable(&ClassInfo2NativeSetMap::Entry::sOps, sizeof(Entry), length)
 {
 }
 
 size_t
 ClassInfo2NativeSetMap::ShallowSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
 {
     size_t n = mallocSizeOf(this);
     n += mTable.ShallowSizeOfExcludingThis(mallocSizeOf);
--- a/js/xpconnect/src/XPCMaps.h
+++ b/js/xpconnect/src/XPCMaps.h
@@ -273,17 +273,22 @@ private:
 /*************************/
 
 class ClassInfo2NativeSetMap
 {
 public:
     struct Entry : public PLDHashEntryHdr
     {
         nsIClassInfo* key;
-        XPCNativeSet* value;
+        XPCNativeSet* value; // strong reference
+        static const PLDHashTableOps sOps;
+
+    private:
+        static bool Match(const PLDHashEntryHdr* aEntry, const void* aKey);
+        static void Clear(PLDHashTable* aTable, PLDHashEntryHdr* aEntry);
     };
 
     static ClassInfo2NativeSetMap* newMap(int length);
 
     inline XPCNativeSet* Find(nsIClassInfo* info)
     {
         auto entry = static_cast<Entry*>(mTable.Search(info));
         return entry ? entry->value : nullptr;
@@ -293,17 +298,17 @@ public:
     {
         NS_PRECONDITION(info,"bad param");
         auto entry = static_cast<Entry*>(mTable.Add(info, mozilla::fallible));
         if (!entry)
             return nullptr;
         if (entry->key)
             return entry->value;
         entry->key = info;
-        entry->value = set;
+        NS_ADDREF(entry->value = set);
         return set;
     }
 
     inline void Remove(nsIClassInfo* info)
     {
         NS_PRECONDITION(info,"bad param");
         mTable.Remove(info);
     }