Bug 1536154 - Update JS_updateMallocCounter callers to use the new API r=bzbarsky
authorJon Coppeard <jcoppeard@mozilla.com>
Wed, 24 Apr 2019 15:58:42 +0100
changeset 530897 5159ad4a890bf2e2fd94972d798ac9e22f929168
parent 530896 b6ca67e7684f4f9409b8e22e0b52afa8e1de2dab
child 530898 4cf9348fa63c5c1b226578fd888d341f7a07b10a
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbzbarsky
bugs1536154
milestone68.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 1536154 - Update JS_updateMallocCounter callers to use the new API r=bzbarsky This updates existing callers to use the new JS::AddAssociatedMemory API and adds calls to RemoveAssociatedMemory in finalizers. The associated memory doesn't need to be exact, so some simplifiations are made, e.g. in CanvasRenderingContext2D where we don't wait for memory to be allocated but update the number of bytes when the dimensions change, and for stream blobs where the value returned by SizeOfIncludingThis changes over the lifetime of the object. Differential Revision: https://phabricator.services.mozilla.com/D28692
dom/bindings/BindingUtils.h
dom/bindings/Codegen.py
dom/canvas/CanvasRenderingContext2D.cpp
dom/file/Blob.cpp
toolkit/components/osfile/NativeOSFileInternals.cpp
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -2586,33 +2586,35 @@ class MOZ_STACK_CLASS BindingJSObjectCre
     if (aReflector) {
       js::SetProxyReservedSlot(aReflector, DOM_OBJECT_SLOT,
                                JS::PrivateValue(aNative));
       mNative = aNative;
       mReflector = aReflector;
     }
 
     if (size_t mallocBytes = BindingJSObjectMallocBytes(aNative)) {
-      JS_updateMallocCounter(aCx, mallocBytes);
+      JS::AddAssociatedMemory(aReflector, mallocBytes,
+                              JS::MemoryUse::DOMBinding);
     }
   }
 
   void CreateObject(JSContext* aCx, const JSClass* aClass,
                     JS::Handle<JSObject*> aProto, T* aNative,
                     JS::MutableHandle<JSObject*> aReflector) {
     aReflector.set(JS_NewObjectWithGivenProto(aCx, aClass, aProto));
     if (aReflector) {
       js::SetReservedSlot(aReflector, DOM_OBJECT_SLOT,
                           JS::PrivateValue(aNative));
       mNative = aNative;
       mReflector = aReflector;
     }
 
     if (size_t mallocBytes = BindingJSObjectMallocBytes(aNative)) {
-      JS_updateMallocCounter(aCx, mallocBytes);
+      JS::AddAssociatedMemory(aReflector, mallocBytes,
+                              JS::MemoryUse::DOMBinding);
     }
   }
 
   void InitializationSucceeded() {
     T* pointer;
     mNative.forget(&pointer);
     RecordReplayRegisterDeferredFinalize<T>(pointer);
 
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -1752,16 +1752,24 @@ def finalizeHook(descriptor, hookName, f
               self->mExpandoAndGeneration.expando = JS::UndefinedValue();
             }
             """,
             obj=obj)
     if descriptor.wrapperCache:
         finalize += "ClearWrapper(self, self, %s);\n" % obj
     if descriptor.isGlobal():
         finalize += "mozilla::dom::FinalizeGlobal(CastToJSFreeOp(%s), %s);\n" % (freeOp, obj)
+    finalize += fill(
+        """
+        if (size_t mallocBytes = BindingJSObjectMallocBytes(self)) {
+          JS::RemoveAssociatedMemory(${obj}, mallocBytes,
+                                     JS::MemoryUse::DOMBinding);
+        }
+        """,
+        obj=obj)
     finalize += ("AddForDeferredFinalization<%s>(self);\n" %
                  descriptor.nativeType)
     return CGIfWrapper(CGGeneric(finalize), "self")
 
 
 class CGClassFinalizeHook(CGAbstractClassHook):
     """
     A hook for finalize, used to release our native object.
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -1481,18 +1481,32 @@ void CanvasRenderingContext2D::ClearTarg
   Reset();
 
   mResetLayer = true;
 
   SetInitialState();
 
   // Update dimensions only if new (strictly positive) values were passed.
   if (aWidth > 0 && aHeight > 0) {
+    // Update the memory size associated with the wrapper object when we change
+    // the dimensions. Note that we need to keep updating dying wrappers before
+    // they are finalized so that the memory accounting balances out.
+    JSObject* wrapper = GetWrapperMaybeDead();
+    if (wrapper) {
+      JS::RemoveAssociatedMemory(wrapper, BindingJSObjectMallocBytes(this),
+                                 JS::MemoryUse::DOMBinding);
+    }
+
     mWidth = aWidth;
     mHeight = aHeight;
+
+    if (wrapper) {
+      JS::AddAssociatedMemory(wrapper, BindingJSObjectMallocBytes(this),
+                              JS::MemoryUse::DOMBinding);
+    }
   }
 
   if (!mCanvasElement || !mCanvasElement->IsInComposedDoc()) {
     return;
   }
 
   // For vertical writing-mode, unless text-orientation is sideways,
   // we'll modify the initial value of textBaseline to 'middle'.
--- a/dom/file/Blob.cpp
+++ b/dom/file/Blob.cpp
@@ -8,16 +8,17 @@
 #include "File.h"
 #include "MemoryBlobImpl.h"
 #include "mozilla/dom/BlobBinding.h"
 #include "MultipartBlobImpl.h"
 #include "nsIInputStream.h"
 #include "nsPIDOMWindow.h"
 #include "StreamBlobImpl.h"
 #include "StringBlobImpl.h"
+#include "js/GCAPI.h"
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(Blob)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Blob)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
@@ -224,13 +225,19 @@ int64_t Blob::GetFileId() { return mImpl
 bool Blob::IsMemoryFile() const { return mImpl->IsMemoryFile(); }
 
 void Blob::CreateInputStream(nsIInputStream** aStream, ErrorResult& aRv) {
   mImpl->CreateInputStream(aStream, aRv);
 }
 
 size_t BindingJSObjectMallocBytes(Blob* aBlob) {
   MOZ_ASSERT(aBlob);
+
+  // TODO: The hazard analysis currently can't see that none of the
+  // implementations of the GetAllocationSize virtual method call can GC (see
+  // bug 1531951).
+  JS::AutoSuppressGCAnalysis nogc;
+
   return aBlob->GetAllocationSize();
 }
 
 }  // namespace dom
 }  // namespace mozilla
--- a/toolkit/components/osfile/NativeOSFileInternals.cpp
+++ b/toolkit/components/osfile/NativeOSFileInternals.cpp
@@ -352,31 +352,28 @@ nsresult TypedArrayResult::GetCacheableR
   // We cannot simply construct a typed array using contents.data as
   // this would allow us to have several otherwise unrelated
   // ArrayBuffers with the same underlying C buffer. As this would be
   // very unsafe, we need to cache the result once we have it.
 
   const ArrayBufferContents& contents = mContents.get();
   MOZ_ASSERT(contents.data);
 
+  // This takes ownership of the buffer and notes the memory allocation.
   JS::Rooted<JSObject*> arrayBuffer(
       cx, JS::NewArrayBufferWithContents(cx, contents.nbytes, contents.data));
   if (!arrayBuffer) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   JS::Rooted<JSObject*> result(
       cx, JS_NewUint8ArrayWithBuffer(cx, arrayBuffer, 0, contents.nbytes));
   if (!result) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
-  // The memory of contents has been allocated on a thread that
-  // doesn't have a JSRuntime, hence without a context. Now that we
-  // have a context, attach the memory to where it belongs.
-  JS_updateMallocCounter(cx, contents.nbytes);
   mContents.forget();
 
   aResult.setObject(*result);
   return NS_OK;
 }
 
 /**
  * Return a result as an int32_t.