Bug 1422057 - Add hash function and boilerplate for deduplicating DisplayItemClipChain via std::set. r?mstange draft
authorKartikaya Gupta <kgupta@mozilla.com>
Sat, 06 Jan 2018 09:52:58 -0500
changeset 716817 2c7e515618faefdfcfa88f472960b99cb82e6aa1
parent 716816 a287abe5ba1afd123c8ace60c6d6b7d08ff809b6
child 716818 667637f3cde67ad6a5f374d3347944c33c33e01f
push id94505
push userkgupta@mozilla.com
push dateSat, 06 Jan 2018 16:27:17 +0000
reviewersmstange
bugs1422057
milestone59.0a1
Bug 1422057 - Add hash function and boilerplate for deduplicating DisplayItemClipChain via std::set. r?mstange MozReview-Commit-ID: I2eos3vwFF0
layout/painting/DisplayItemClipChain.cpp
layout/painting/DisplayItemClipChain.h
--- a/layout/painting/DisplayItemClipChain.cpp
+++ b/layout/painting/DisplayItemClipChain.cpp
@@ -28,16 +28,37 @@ DisplayItemClipChain::Equal(const Displa
     return false;
   }
 
   return aClip1->mASR == aClip2->mASR &&
          aClip1->mClip == aClip2->mClip &&
          Equal(aClip1->mParent, aClip2->mParent);
 }
 
+uint32_t
+DisplayItemClipChain::Hash(const DisplayItemClipChain* aClip)
+{
+  if (!aClip) {
+    return 0;
+  }
+
+  // We include the number of rounded rects in the hash but not their contents.
+  // This is to keep the hash fast, because most clips will not have rounded
+  // rects and including them will slow down the hash in the common case. Note
+  // that the ::Equal check still checks the rounded rect contents, so in case
+  // of hash collisions the clip chains can still be distinguished using that.
+  uint32_t hash = HashGeneric(aClip->mASR, aClip->mClip.GetRoundedRectCount());
+  if (aClip->mClip.HasClip()) {
+    const nsRect& rect = aClip->mClip.GetClipRect();
+    hash = AddToHash(hash, rect.x, rect.y, rect.width, rect.height);
+  }
+
+  return hash;
+}
+
 /* static */ nsCString
 DisplayItemClipChain::ToString(const DisplayItemClipChain* aClipChain)
 {
   nsAutoCString str;
   for (auto* sc = aClipChain; sc; sc = sc->mParent) {
     if (sc->mASR) {
       str.AppendPrintf("0x%p <%s> [0x%p]", sc, sc->mClip.ToString().get(), sc->mASR->mScrollableFrame);
     } else {
--- a/layout/painting/DisplayItemClipChain.h
+++ b/layout/painting/DisplayItemClipChain.h
@@ -39,16 +39,21 @@ struct DisplayItemClipChain {
   /**
    * Get the display item clip in this chain that moves with aASR, or nullptr
    * if no such clip exists. aClipChain can be null.
    */
   static const DisplayItemClip* ClipForASR(const DisplayItemClipChain* aClipChain,
                                            const ActiveScrolledRoot* aASR);
 
   static bool Equal(const DisplayItemClipChain* aClip1, const DisplayItemClipChain* aClip2);
+  /**
+   * Hash function that returns the same value for any two clips A and B
+   * where Equal(A, B) is true.
+   */
+  static uint32_t Hash(const DisplayItemClipChain* aClip);
 
   static nsCString ToString(const DisplayItemClipChain* aClipChain);
 
   bool HasRoundedCorners() const;
 
   void AddRef() {
     mRefCount++;
   }
@@ -66,11 +71,31 @@ struct DisplayItemClipChain {
   DisplayItemClipChain() {}
 
   DisplayItemClip mClip;
   const ActiveScrolledRoot* mASR;
   RefPtr<const DisplayItemClipChain> mParent;
   mutable uint32_t mRefCount = 0;
 };
 
+struct DisplayItemClipChainHasher
+{
+  typedef const DisplayItemClipChain* Key;
+
+  std::size_t operator()(const Key& aKey) const
+  {
+    return DisplayItemClipChain::Hash(aKey);
+  }
+};
+
+struct DisplayItemClipChainEqualer
+{
+  typedef const DisplayItemClipChain* Key;
+
+  bool operator()(const Key& lhs, const Key& rhs) const
+  {
+    return DisplayItemClipChain::Equal(lhs, rhs);
+  }
+};
+
 } // namespace mozilla
 
 #endif /* DISPLAYITEMCLIPCHAIN_H_ */