Bug 1382645: Part 1 - Add memory reporter for StructuredCloneHolder binding implementation. r?billm draft
authorKris Maglione <maglione.k@gmail.com>
Thu, 20 Jul 2017 14:04:43 -0700
changeset 612585 4924ca331db1c244410c9d816ef56353f64db1f3
parent 612584 8e46fc907da91a5ad9630fdca9fddaf3557eda63
child 612586 42263850ff33ef1934e6678398376900d2ee540e
push id69543
push usermaglione.k@gmail.com
push dateThu, 20 Jul 2017 21:06:27 +0000
reviewersbillm
bugs1382645
milestone56.0a1
Bug 1382645: Part 1 - Add memory reporter for StructuredCloneHolder binding implementation. r?billm MozReview-Commit-ID: aK3ljfCJVi
dom/base/StructuredCloneBlob.cpp
dom/base/StructuredCloneBlob.h
dom/base/StructuredCloneHolder.h
js/public/StructuredClone.h
mfbt/BufferList.h
--- a/dom/base/StructuredCloneBlob.cpp
+++ b/dom/base/StructuredCloneBlob.cpp
@@ -17,27 +17,32 @@
 #include "mozilla/dom/StructuredCloneTags.h"
 
 namespace mozilla {
 namespace dom {
 
 StructuredCloneBlob::StructuredCloneBlob()
     : StructuredCloneHolder(CloningSupported, TransferringNotSupported,
                             StructuredCloneScope::DifferentProcess)
-{};
+{}
+
+StructuredCloneBlob::~StructuredCloneBlob()
+{
+  UnregisterWeakMemoryReporter(this);
+}
 
 
 /* static */ already_AddRefed<StructuredCloneBlob>
 StructuredCloneBlob::Constructor(GlobalObject& aGlobal, JS::HandleValue aValue,
                                  JS::HandleObject aTargetGlobal,
                                  ErrorResult& aRv)
 {
   JSContext* cx = aGlobal.Context();
 
-  RefPtr<StructuredCloneBlob> holder = new StructuredCloneBlob();
+  RefPtr<StructuredCloneBlob> holder = StructuredCloneBlob::Create();
 
   Maybe<JSAutoCompartment> ac;
   JS::RootedValue value(cx, aValue);
 
   if (aTargetGlobal) {
     JS::RootedObject targetGlobal(cx, js::CheckedUnwrap(aTargetGlobal));
     if (!targetGlobal) {
       js::ReportAccessDenied(cx);
@@ -99,17 +104,17 @@ StructuredCloneBlob::Deserialize(JSConte
 
 
 /* static */ JSObject*
 StructuredCloneBlob::ReadStructuredClone(JSContext* aCx, JSStructuredCloneReader* aReader,
                                          StructuredCloneHolder* aHolder)
 {
   JS::RootedObject obj(aCx);
   {
-    RefPtr<StructuredCloneBlob> holder = new StructuredCloneBlob();
+    RefPtr<StructuredCloneBlob> holder = StructuredCloneBlob::Create();
 
     if (!holder->ReadStructuredCloneInternal(aCx, aReader, aHolder) ||
         !holder->WrapObject(aCx, nullptr, &obj)) {
       return nullptr;
     }
   }
   return obj.get();
 }
@@ -176,10 +181,25 @@ StructuredCloneBlob::WriteStructuredClon
 }
 
 bool
 StructuredCloneBlob::WrapObject(JSContext* aCx, JS::HandleObject aGivenProto, JS::MutableHandleObject aResult)
 {
     return StructuredCloneHolderBinding::Wrap(aCx, this, aGivenProto, aResult);
 }
 
+
+NS_IMETHODIMP
+StructuredCloneBlob::CollectReports(nsIHandleReportCallback* aHandleReport,
+                                    nsISupports* aData, bool aAnonymize)
+{
+  MOZ_COLLECT_REPORT(
+    "explicit/dom/structured-clone-holder", KIND_HEAP, UNITS_BYTES,
+    MallocSizeOf(this) + SizeOfExcludingThis(MallocSizeOf),
+    "Memory used by StructuredCloneHolder DOM objects.");
+
+  return NS_OK;
+}
+
+NS_IMPL_ISUPPORTS(StructuredCloneBlob, nsIMemoryReporter)
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/base/StructuredCloneBlob.h
+++ b/dom/base/StructuredCloneBlob.h
@@ -4,32 +4,33 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_StructuredCloneBlob_h
 #define mozilla_dom_StructuredCloneBlob_h
 
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/StructuredCloneHolder.h"
 #include "mozilla/dom/StructuredCloneHolderBinding.h"
-#include "mozilla/RefCounted.h"
 
 #include "jsapi.h"
 
+#include "nsIMemoryReporter.h"
 #include "nsISupports.h"
 
 namespace mozilla {
 namespace dom {
 
-class StructuredCloneBlob : public StructuredCloneHolder
-                          , public RefCounted<StructuredCloneBlob>
+class StructuredCloneBlob final : public nsIMemoryReporter
+                                , public StructuredCloneHolder
 {
+  MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
+
 public:
-  MOZ_DECLARE_REFCOUNTED_TYPENAME(StructuredCloneBlob)
-
-  explicit StructuredCloneBlob();
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIMEMORYREPORTER
 
   static JSObject* ReadStructuredClone(JSContext* aCx, JSStructuredCloneReader* aReader,
                                        StructuredCloneHolder* aHolder);
   bool WriteStructuredClone(JSContext* aCx, JSStructuredCloneWriter* aWriter,
                             StructuredCloneHolder* aHolder);
 
   static already_AddRefed<StructuredCloneBlob>
   Constructor(GlobalObject& aGlobal, JS::HandleValue aValue, JS::HandleObject aTargetGlobal, ErrorResult& aRv);
@@ -38,22 +39,28 @@ public:
                    JS::MutableHandleValue aResult, ErrorResult& aRv);
 
   nsISupports* GetParentObject() const { return nullptr; }
   JSObject* GetWrapper() const { return nullptr; }
 
   bool WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto, JS::MutableHandleObject aResult);
 
 protected:
-  template <typename T, detail::RefCountAtomicity>
-  friend class detail::RefCounted;
-
-  ~StructuredCloneBlob() = default;
+  virtual ~StructuredCloneBlob();
 
 private:
+  explicit StructuredCloneBlob();
+
+  static already_AddRefed<StructuredCloneBlob> Create()
+  {
+    RefPtr<StructuredCloneBlob> holder = new StructuredCloneBlob();
+    RegisterWeakMemoryReporter(holder);
+    return holder.forget();
+  }
+
   bool ReadStructuredCloneInternal(JSContext* aCx, JSStructuredCloneReader* aReader,
                                    StructuredCloneHolder* aHolder);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_StructuredCloneBlob_h
--- a/dom/base/StructuredCloneHolder.h
+++ b/dom/base/StructuredCloneHolder.h
@@ -3,16 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_StructuredCloneHolder_h
 #define mozilla_dom_StructuredCloneHolder_h
 
 #include "jsapi.h"
 #include "js/StructuredClone.h"
+#include "mozilla/MemoryReporting.h"
 #include "mozilla/Move.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "nsISupports.h"
 #include "nsTArray.h"
 
 #ifdef DEBUG
 #include "nsIThread.h"
@@ -111,16 +112,25 @@ public:
   }
 
   JSStructuredCloneData& BufferData() const
   {
     MOZ_ASSERT(mBuffer, "Write() has never been called.");
     return mBuffer->data();
   }
 
+  size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf)
+  {
+    size_t size = 0;
+    if (HasData()) {
+      size += mBuffer->sizeOfIncludingThis(aMallocSizeOf);
+    }
+    return size;
+  }
+
 protected:
   UniquePtr<JSAutoStructuredCloneBuffer> mBuffer;
 
   StructuredCloneScope mStructuredCloneScope;
 
 #ifdef DEBUG
   bool mClearCalled;
 #endif
--- a/js/public/StructuredClone.h
+++ b/js/public/StructuredClone.h
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef js_StructuredClone_h
 #define js_StructuredClone_h
 
 #include "mozilla/Attributes.h"
 #include "mozilla/BufferList.h"
+#include "mozilla/MemoryReporting.h"
 
 #include <stdint.h>
 
 #include "jstypes.h"
 
 #include "js/RootingAPI.h"
 #include "js/TypeDecls.h"
 #include "js/Value.h"
@@ -334,16 +335,26 @@ class JS_PUBLIC_API(JSAutoStructuredClon
 
     bool write(JSContext* cx, JS::HandleValue v,
                const JSStructuredCloneCallbacks* optionalCallbacks=nullptr, void* closure=nullptr);
 
     bool write(JSContext* cx, JS::HandleValue v, JS::HandleValue transferable,
                JS::CloneDataPolicy cloneDataPolicy,
                const JSStructuredCloneCallbacks* optionalCallbacks=nullptr, void* closure=nullptr);
 
+    size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)
+    {
+        return data_.SizeOfExcludingThis(mallocSizeOf);
+    }
+
+    size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
+    {
+        return mallocSizeOf(this) + sizeOfExcludingThis(mallocSizeOf);
+    }
+
   private:
     // Copy and assignment are not supported.
     JSAutoStructuredCloneBuffer(const JSAutoStructuredCloneBuffer& other) = delete;
     JSAutoStructuredCloneBuffer& operator=(const JSAutoStructuredCloneBuffer& other) = delete;
 };
 
 // The range of tag values the application may use for its own custom object types.
 #define JS_SCTAG_USER_MIN  ((uint32_t) 0xFFFF8000)
--- a/mfbt/BufferList.h
+++ b/mfbt/BufferList.h
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_BufferList_h
 #define mozilla_BufferList_h
 
 #include <algorithm>
 #include "mozilla/AllocPolicy.h"
+#include "mozilla/MemoryReporting.h"
 #include "mozilla/Move.h"
 #include "mozilla/ScopeExit.h"
 #include "mozilla/Types.h"
 #include "mozilla/TypeTraits.h"
 #include "mozilla/Vector.h"
 #include <string.h>
 
 // BufferList represents a sequence of buffers of data. A BufferList can choose
@@ -131,16 +132,25 @@ class BufferList : private AllocPolicy
     MOZ_ASSERT(aInitialCapacity % kSegmentAlignment == 0);
 
     return AllocateSegment(aInitialSize, aInitialCapacity);
   }
 
   // Returns the sum of the sizes of all the buffers.
   size_t Size() const { return mSize; }
 
+  size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf)
+  {
+    size_t size = mSegments.sizeOfExcludingThis(aMallocSizeOf);
+    for (Segment& segment : mSegments) {
+      size += aMallocSizeOf(segment.Start());
+    }
+    return size;
+  }
+
   void Clear()
   {
     if (mOwning) {
       for (Segment& segment : mSegments) {
         this->free_(segment.mData);
       }
     }
     mSegments.clear();