Bug 1370614. Replace some uses of ProtoAndIfaceCache::EntrySlotIfExists with a faster boolean-returning test function. r=froydnj
authorBoris Zbarsky <bzbarsky@mit.edu>
Wed, 07 Jun 2017 12:56:27 -0400
changeset 410852 b84707ac2dfeec9de7d16ccf17d8a703844a59e7
parent 410851 7df7e414a2be891a6bd039ae92e4507337bfc389
child 410853 37f50095e77ef92ede26761f9e8c9835d60879e8
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1370614
milestone55.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 1370614. Replace some uses of ProtoAndIfaceCache::EntrySlotIfExists with a faster boolean-returning test function. r=froydnj
dom/bindings/BindingUtils.h
dom/bindings/Codegen.py
dom/bindings/WebIDLGlobalNameHash.cpp
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -268,16 +268,20 @@ class ProtoAndIfaceCache
 
   class ArrayCache : public Array<JS::Heap<JSObject*>, kProtoAndIfaceCacheCount>
   {
   public:
     JSObject* EntrySlotIfExists(size_t i) {
       return (*this)[i];
     }
 
+    bool HasEntryInSlot(size_t i) {
+      return (*this)[i];
+    }
+
     JS::Heap<JSObject*>& EntrySlotOrCreate(size_t i) {
       return (*this)[i];
     }
 
     JS::Heap<JSObject*>& EntrySlotMustExist(size_t i) {
       return (*this)[i];
     }
 
@@ -311,16 +315,27 @@ class ProtoAndIfaceCache
       size_t leafIndex = i % kPageSize;
       Page* p = mPages[pageIndex];
       if (!p) {
         return nullptr;
       }
       return (*p)[leafIndex];
     }
 
+    bool HasEntryInSlot(size_t i) {
+      MOZ_ASSERT(i < kProtoAndIfaceCacheCount);
+      size_t pageIndex = i / kPageSize;
+      size_t leafIndex = i % kPageSize;
+      Page* p = mPages[pageIndex];
+      if (!p) {
+        return false;
+      }
+      return (*p)[leafIndex];
+    }
+
     JS::Heap<JSObject*>& EntrySlotOrCreate(size_t i) {
       MOZ_ASSERT(i < kProtoAndIfaceCacheCount);
       size_t pageIndex = i / kPageSize;
       size_t leafIndex = i % kPageSize;
       Page* p = mPages[pageIndex];
       if (!p) {
         p = new Page;
         mPages[pageIndex] = p;
@@ -398,16 +413,24 @@ public:
   } while(0)
 
   // Return the JSObject stored in slot i, if that slot exists.  If
   // the slot does not exist, return null.
   JSObject* EntrySlotIfExists(size_t i) {
     FORWARD_OPERATION(EntrySlotIfExists, (i));
   }
 
+  // Return whether slot i contains an object.  This doesn't return the object
+  // itself because in practice consumers just want to know whether it's there
+  // or not, and that doesn't require barriering, which returning the object
+  // pointer does.
+  bool HasEntryInSlot(size_t i) {
+    FORWARD_OPERATION(HasEntryInSlot, (i));
+  }
+
   // Return a reference to slot i, creating it if necessary.  There
   // may not be an object in the returned slot.
   JS::Heap<JSObject*>& EntrySlotOrCreate(size_t i) {
     FORWARD_OPERATION(EntrySlotOrCreate, (i));
   }
 
   // Return a reference to slot i, which is guaranteed to already
   // exist.  There may not be an object in the slot, if prototype and
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -3284,17 +3284,17 @@ class CGGetPerInterfaceObject(CGAbstract
             /* Make sure our global is sane.  Hopefully we can remove this sometime */
             JSObject* global = JS::CurrentGlobalOrNull(aCx);
             if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
               return nullptr;
             }
 
             /* Check to see whether the interface objects are already installed */
             ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
-            if (!protoAndIfaceCache.EntrySlotIfExists(${id})) {
+            if (!protoAndIfaceCache.HasEntryInSlot(${id})) {
               JS::Rooted<JSObject*> rootedGlobal(aCx, global);
               CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
             }
 
             /*
              * The object might _still_ be null, but that's OK.
              *
              * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
--- a/dom/bindings/WebIDLGlobalNameHash.cpp
+++ b/dom/bindings/WebIDLGlobalNameHash.cpp
@@ -313,17 +313,17 @@ WebIDLGlobalNameHash::GetNames(JSContext
 {
   // aObj is always a Window here, so GetProtoAndIfaceCache on it is safe.
   ProtoAndIfaceCache* cache = GetProtoAndIfaceCache(aObj);
   for (auto iter = sWebIDLGlobalNames->Iter(); !iter.Done(); iter.Next()) {
     const WebIDLNameTableEntry* entry = iter.Get();
     // If aNameType is not AllNames, only include things whose entry slot in the
     // ProtoAndIfaceCache is null.
     if ((aNameType == AllNames ||
-         !cache->EntrySlotIfExists(entry->mConstructorId)) &&
+         !cache->HasEntryInSlot(entry->mConstructorId)) &&
         (!entry->mEnabled || entry->mEnabled(aCx, aObj))) {
       JSString* str = JS_AtomizeStringN(aCx, sNames + entry->mNameOffset,
                                         entry->mNameLength);
       if (!str || !aNames.append(NON_INTEGER_ATOM_TO_JSID(str))) {
         return false;
       }
     }
   }