Bug 1481998 - Change sJSObjWrappers initialization. r=luke
authorNicholas Nethercote <nnethercote@mozilla.com>
Thu, 09 Aug 2018 14:15:42 +1000
changeset 486276 6bb61989d9ae6611277918cbf320e878c55dd825
parent 486275 acf69d2b847db39c9c8740606ba8fe8d191b416e
child 486277 223884f0ad76f8224f046311dd016b83fbb3aa6e
push id9719
push userffxbld-merge
push dateFri, 24 Aug 2018 17:49:46 +0000
treeherdermozilla-beta@719ec98fba77 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs1481998
milestone63.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 1481998 - Change sJSObjWrappers initialization. r=luke GCHashMap will shortly lose its initialized() function, so we need another way to indicate whether this table has been created. This patch changes it to use a pointer instead.
dom/plugins/base/nsJSNPRuntime.cpp
--- a/dom/plugins/base/nsJSNPRuntime.cpp
+++ b/dom/plugins/base/nsJSNPRuntime.cpp
@@ -23,16 +23,17 @@
 #include "xpcpublic.h"
 #include "nsIContent.h"
 #include "nsPluginInstanceOwner.h"
 #include "nsWrapperCacheInlines.h"
 #include "js/GCHashTable.h"
 #include "js/TracingAPI.h"
 #include "js/Wrapper.h"
 #include "mozilla/HashFunctions.h"
+#include "mozilla/UniquePtr.h"
 #include "mozilla/dom/ScriptSettings.h"
 
 #define NPRUNTIME_JSCLASS_NAME "NPObject JS wrapper class"
 
 using namespace mozilla::plugins::parent;
 using namespace mozilla;
 
 #include "mozilla/plugins/PluginScriptableObjectParent.h"
@@ -80,17 +81,17 @@ public:
 // created. This is needed to be able to properly drop the wrappers
 // when a plugin is torn down in case there's a leak in the plugin (we
 // don't want to leak the world just because a plugin leaks an
 // NPObject).
 typedef JS::GCHashMap<nsJSObjWrapperKey,
                       nsJSObjWrapper*,
                       JSObjWrapperHasher,
                       js::SystemAllocPolicy> JSObjWrapperTable;
-static JSObjWrapperTable sJSObjWrappers;
+static UniquePtr<JSObjWrapperTable> sJSObjWrappers;
 
 // Whether it's safe to iterate sJSObjWrappers.  Set to true when sJSObjWrappers
 // has been initialized and is not currently being enumerated.
 static bool sJSObjWrappersAccessible = false;
 
 // Hash of NPObject wrappers that wrap NPObjects as JSObjects.
 static PLDHashTable* sNPObjWrappers;
 
@@ -289,18 +290,18 @@ static const JSClass sNPObjectMemberClas
 };
 
 static void
 OnWrapperDestroyed();
 
 static void
 TraceJSObjWrappers(JSTracer *trc, void *data)
 {
-  if (sJSObjWrappers.initialized()) {
-    sJSObjWrappers.trace(trc);
+  if (sJSObjWrappers) {
+    sJSObjWrappers->trace(trc);
   }
 }
 
 static void
 DelayedReleaseGCCallback(JSGCStatus status)
 {
   if (JSGC_END == status) {
     // Take ownership of sDelayedReleases and null it out now. The
@@ -356,41 +357,42 @@ UnregisterGCCallbacks()
     sCallbackIsRegistered = false;
   }
 }
 
 static bool
 CreateJSObjWrapperTable()
 {
   MOZ_ASSERT(!sJSObjWrappersAccessible);
-  MOZ_ASSERT(!sJSObjWrappers.initialized());
+  MOZ_ASSERT(!sJSObjWrappers);
 
   if (!RegisterGCCallbacks()) {
     return false;
   }
 
-  if (!sJSObjWrappers.init(16)) {
-    NS_ERROR("Error initializing PLDHashTable sJSObjWrappers!");
+  sJSObjWrappers = MakeUnique<JSObjWrapperTable>();
+  if (!sJSObjWrappers->init(16)) {
+    sJSObjWrappers = nullptr;
+    NS_ERROR("Error initializing sJSObjWrappers!");
     return false;
   }
 
   sJSObjWrappersAccessible = true;
   return true;
 }
 
 static void
 DestroyJSObjWrapperTable()
 {
   MOZ_ASSERT(sJSObjWrappersAccessible);
-  MOZ_ASSERT(sJSObjWrappers.initialized());
-  MOZ_ASSERT(sJSObjWrappers.count() == 0);
-
-  // No more wrappers, and our hash was initialized. Finish the
-  // hash to prevent leaking it.
-  sJSObjWrappers.finish();
+  MOZ_ASSERT(sJSObjWrappers);
+  MOZ_ASSERT(sJSObjWrappers->count() == 0);
+
+  // No more wrappers. Delete the table.
+  sJSObjWrappers = nullptr;
   sJSObjWrappersAccessible = false;
 }
 
 static bool
 CreateNPObjWrapperTable()
 {
   MOZ_ASSERT(!sNPObjWrappers);
 
@@ -689,19 +691,19 @@ nsJSObjWrapper::NP_Invalidate(NPObject *
 {
   nsJSObjWrapper *jsnpobj = (nsJSObjWrapper *)npobj;
 
   if (jsnpobj && jsnpobj->mJSObj) {
 
     if (sJSObjWrappersAccessible) {
       // Remove the wrapper from the hash
       nsJSObjWrapperKey key(jsnpobj->mJSObj, jsnpobj->mNpp);
-      JSObjWrapperTable::Ptr ptr = sJSObjWrappers.lookup(key);
+      JSObjWrapperTable::Ptr ptr = sJSObjWrappers->lookup(key);
       MOZ_ASSERT(ptr.found());
-      sJSObjWrappers.remove(ptr);
+      sJSObjWrappers->remove(ptr);
     }
 
     // Forget our reference to the JSObject.
     jsnpobj->mJSObj = nullptr;
     jsnpobj->mJSObjGlobal = nullptr;
   }
 }
 
@@ -1127,24 +1129,24 @@ nsJSObjWrapper::GetNewOrUsed(NPP npp, JS
     // us to throw.
     if (!npobj)
       return nullptr;
 
     if (LookupNPP(npobj) == npp)
       return _retainobject(npobj);
   }
 
-  if (!sJSObjWrappers.initialized()) {
+  if (!sJSObjWrappers) {
     // No hash yet (or any more), initialize it.
     if (!CreateJSObjWrapperTable())
       return nullptr;
   }
   MOZ_ASSERT(sJSObjWrappersAccessible);
 
-  JSObjWrapperTable::Ptr p = sJSObjWrappers.lookupForAdd(nsJSObjWrapperKey(obj, npp));
+  JSObjWrapperTable::Ptr p = sJSObjWrappers->lookupForAdd(nsJSObjWrapperKey(obj, npp));
   if (p) {
     MOZ_ASSERT(p->value());
     // Found a live nsJSObjWrapper, return it.
 
     return _retainobject(p->value());
   }
 
   // No existing nsJSObjWrapper, create one.
@@ -1157,17 +1159,17 @@ nsJSObjWrapper::GetNewOrUsed(NPP npp, JS
     return nullptr;
   }
 
   wrapper->mJSObj = obj;
   wrapper->mJSObjGlobal = objGlobal;
 
   // Insert the new wrapper into the hashtable, rooting the JSObject. Its
   // lifetime is now tied to that of the NPObject.
-  if (!sJSObjWrappers.putNew(nsJSObjWrapperKey(obj, npp), wrapper)) {
+  if (!sJSObjWrappers->putNew(nsJSObjWrapperKey(obj, npp), wrapper)) {
     // Out of memory, free the wrapper we created.
     _releaseobject(wrapper);
     return nullptr;
   }
 
   return wrapper;
 }
 
@@ -2027,17 +2029,17 @@ nsNPObjWrapper::GetNewOrUsed(NPP npp, JS
 void
 nsJSNPRuntime::OnPluginDestroy(NPP npp)
 {
   if (sJSObjWrappersAccessible) {
 
     // Prevent modification of sJSObjWrappers table if we go reentrant.
     sJSObjWrappersAccessible = false;
 
-    for (auto iter = sJSObjWrappers.modIter(); !iter.done(); iter.next()) {
+    for (auto iter = sJSObjWrappers->modIter(); !iter.done(); iter.next()) {
       nsJSObjWrapper* npobj = iter.get().value();
       MOZ_ASSERT(npobj->_class == &nsJSObjWrapper::sJSObjWrapperNPClass);
       if (npobj->mNpp == npp) {
         if (npobj->_class && npobj->_class->invalidate) {
           npobj->_class->invalidate(npobj);
         }
 
         _releaseobject(npobj);
@@ -2100,17 +2102,17 @@ nsJSNPRuntime::OnPluginDestroy(NPP npp)
 
 // static
 void
 nsJSNPRuntime::OnPluginDestroyPending(NPP npp)
 {
   if (sJSObjWrappersAccessible) {
     // Prevent modification of sJSObjWrappers table if we go reentrant.
     sJSObjWrappersAccessible = false;
-    for (auto iter = sJSObjWrappers.iter(); !iter.done(); iter.next()) {
+    for (auto iter = sJSObjWrappers->iter(); !iter.done(); iter.next()) {
       nsJSObjWrapper* npobj = iter.get().value();
       MOZ_ASSERT(npobj->_class == &nsJSObjWrapper::sJSObjWrapperNPClass);
       if (npobj->mNpp == npp) {
         npobj->mDestroyPending = true;
       }
     }
     sJSObjWrappersAccessible = true;
   }