Bug 1301863 - Tell the JS engine how much memory blob reflectors hold alive r=baku

This commit is contained in:
Jon Coppeard 2017-09-12 10:46:51 +01:00
parent 6af41593df
commit a4fe4cbe3c
15 changed files with 90 additions and 28 deletions

View File

@ -2819,6 +2819,18 @@ ToSupportsIsOnPrimaryInheritanceChain(T* aObject, nsWrapperCache* aCache)
aCache);
}
// Get the size of allocated memory to associate with a binding JSObject for a
// native object. This is supplied to the JS engine to allow it to schedule GC
// when necessary.
//
// This function supplies a default value and is overloaded for specific native
// object types.
inline uint64_t
BindingJSObjectMallocBytes(void *aNativePtr)
{
return 0;
}
// The BindingJSObjectCreator class is supposed to be used by a caller that
// wants to create and initialise a binding JSObject. After initialisation has
// been successfully completed it should call ForgetObject().
@ -2861,6 +2873,10 @@ public:
mNative = aNative;
mReflector = aReflector;
}
if (uint64_t mallocBytes = BindingJSObjectMallocBytes(aNative)) {
JS_updateMallocCounter(aCx, mallocBytes);
}
}
void
@ -2874,6 +2890,10 @@ public:
mNative = aNative;
mReflector = aReflector;
}
if (uint64_t mallocBytes = BindingJSObjectMallocBytes(aNative)) {
JS_updateMallocCounter(aCx, mallocBytes);
}
}
void

View File

@ -40,19 +40,9 @@ CanvasRenderingContextHelper::ToBlob(JSContext* aCx,
{
RefPtr<Blob> blob = aBlob;
ErrorResult rv;
uint64_t size = blob->GetSize(rv);
if (rv.Failed()) {
rv.SuppressException();
} else {
AutoJSAPI jsapi;
if (jsapi.Init(mGlobal)) {
JS_updateMallocCounter(jsapi.cx(), size);
}
}
RefPtr<Blob> newBlob = Blob::Create(mGlobal, blob->Impl());
ErrorResult rv;
mBlobCallback->Call(newBlob, rv);
mGlobal = nullptr;

View File

@ -266,17 +266,6 @@ OffscreenCanvas::ToBlob(JSContext* aCx,
{
RefPtr<Blob> blob = aBlob;
ErrorResult rv;
uint64_t size = blob->GetSize(rv);
if (rv.Failed()) {
rv.SuppressException();
} else {
AutoJSAPI jsapi;
if (jsapi.Init(mGlobal)) {
JS_updateMallocCounter(jsapi.cx(), size);
}
}
if (mPromise) {
RefPtr<Blob> newBlob = Blob::Create(mGlobal, blob->Impl());
mPromise->MaybeResolve(newBlob);
@ -285,7 +274,7 @@ OffscreenCanvas::ToBlob(JSContext* aCx,
mGlobal = nullptr;
mPromise = nullptr;
return rv.StealNSResult();
return NS_OK;
}
nsCOMPtr<nsIGlobalObject> mGlobal;

View File

@ -97,6 +97,11 @@ public:
virtual void GetType(nsAString& aType) override;
size_t GetAllocationSize() const override
{
return 0;
}
virtual uint64_t GetSerialNumber() const override { return mSerialNumber; }
virtual already_AddRefed<BlobImpl>

View File

@ -214,6 +214,12 @@ Blob::Slice(const Optional<int64_t>& aStart,
return blob.forget();
}
size_t
Blob::GetAllocationSize() const
{
return mImpl->GetAllocationSize();
}
NS_IMETHODIMP
Blob::GetSendInfo(nsIInputStream** aBody,
uint64_t* aContentLength,
@ -286,5 +292,12 @@ Blob::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
mImpl->GetInternalStream(aStream, aRv);
}
uint64_t
BindingJSObjectMallocBytes(Blob* aBlob)
{
MOZ_ASSERT(aBlob);
return aBlob->GetAllocationSize();
}
} // namespace dom
} // namespace mozilla

View File

@ -130,6 +130,8 @@ public:
const nsAString& aContentType,
ErrorResult& aRv);
size_t GetAllocationSize() const;
protected:
// File constructor should never be used directly. Use Blob::Create instead.
Blob(nsISupports* aParent, BlobImpl* aImpl);
@ -147,6 +149,10 @@ private:
nsCOMPtr<nsISupports> mParent;
};
// Override BindingJSObjectMallocBytes for blobs to tell the JS GC how much
// memory is held live by the binding object.
uint64_t BindingJSObjectMallocBytes(Blob* aBlob);
} // namespace dom
} // namespace mozilla

View File

@ -51,6 +51,8 @@ public:
virtual void GetType(nsAString& aType) = 0;
virtual size_t GetAllocationSize() const = 0;
/**
* An effectively-unique serial number identifying this instance of FileImpl.
*

View File

@ -53,6 +53,11 @@ public:
return true;
}
size_t GetAllocationSize() const override
{
return mLength;
}
class DataOwner final : public mozilla::LinkedListElement<DataOwner>
{
public:

View File

@ -411,3 +411,13 @@ MultipartBlobImpl::MayBeClonedToOtherThreads() const
return true;
}
size_t MultipartBlobImpl::GetAllocationSize() const
{
size_t total = 0;
for (uint32_t i = 0; i < mBlobImpls.Length(); ++i) {
total += mBlobImpls[i]->GetAllocationSize();
}
return total;
}

View File

@ -92,6 +92,8 @@ public:
virtual bool MayBeClonedToOtherThreads() const override;
size_t GetAllocationSize() const override;
protected:
MultipartBlobImpl(nsTArray<RefPtr<BlobImpl>>&& aBlobImpls,
const nsAString& aName,

View File

@ -156,5 +156,17 @@ StreamBlobImpl::CollectReports(nsIHandleReportCallback* aHandleReport,
return NS_OK;
}
size_t
StreamBlobImpl::GetAllocationSize() const
{
nsCOMPtr<nsIStringInputStream> stringInputStream =
do_QueryInterface(mInputStream);
if (!stringInputStream) {
return 0;
}
return stringInputStream->SizeOfIncludingThis(MallocSizeOf);
}
} // namespace dom
} // namespace mozilla

View File

@ -77,6 +77,8 @@ public:
return mIsDirectory;
}
size_t GetAllocationSize() const override;
private:
StreamBlobImpl(nsIInputStream* aInputStream,
const nsAString& aContentType,

View File

@ -32,6 +32,11 @@ public:
CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType, ErrorResult& aRv) override;
size_t GetAllocationSize() const override
{
return mData.Length();
}
private:
StringBlobImpl(const nsACString& aData, const nsAString& aContentType);

View File

@ -942,11 +942,6 @@ HTMLCanvasElement::MozGetAsFileImpl(const nsAString& aName,
rv = NS_ReadInputStreamToBuffer(stream, &imgData, (uint32_t)imgSize);
NS_ENSURE_SUCCESS(rv, rv);
JSContext* cx = nsContentUtils::GetCurrentJSContext();
if (cx) {
JS_updateMallocCounter(cx, imgSize);
}
nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(OwnerDoc()->GetScopeObject());
// The File takes ownership of the buffer

View File

@ -108,6 +108,12 @@ private:
mBlobImpl->GetType(aType);
}
size_t
GetAllocationSize() const override
{
return mBlobImpl->GetAllocationSize();
}
virtual uint64_t
GetSerialNumber() const override
{