Bug 1904048 - Add prototype for ImageBitmap's BindingJSObjectMallocBytes. r=aosmond
It looks like there was never a prototype for ImageBitmap's BindingJSObjectMallocBytes function. Even though it was defined and expected to associate ImageBitmap's internally allocated surface memory for the GC to track, the bindings generator never actually tried to call it because the lack of the prototype caused the default non-specialized version of this function to be called instead. With the protoype in place, this actually gets called and the GC is able to properly clean out ImageBitmap's in a more timely fashion. Differential Revision: https://phabricator.services.mozilla.com/D216250
This commit is contained in:
@@ -38,6 +38,7 @@
|
|||||||
#include "nsStreamUtils.h"
|
#include "nsStreamUtils.h"
|
||||||
#include "imgLoader.h"
|
#include "imgLoader.h"
|
||||||
#include "imgTools.h"
|
#include "imgTools.h"
|
||||||
|
#include "jsapi.h"
|
||||||
|
|
||||||
using namespace mozilla::gfx;
|
using namespace mozilla::gfx;
|
||||||
using namespace mozilla::layers;
|
using namespace mozilla::layers;
|
||||||
@@ -651,13 +652,14 @@ static already_AddRefed<SourceSurface> GetSurfaceFromElement(
|
|||||||
}
|
}
|
||||||
|
|
||||||
ImageBitmap::ImageBitmap(nsIGlobalObject* aGlobal, layers::Image* aData,
|
ImageBitmap::ImageBitmap(nsIGlobalObject* aGlobal, layers::Image* aData,
|
||||||
bool aWriteOnly, gfxAlphaType aAlphaType)
|
bool aAllocatedImageData, bool aWriteOnly,
|
||||||
|
gfxAlphaType aAlphaType)
|
||||||
: mParent(aGlobal),
|
: mParent(aGlobal),
|
||||||
mData(aData),
|
mData(aData),
|
||||||
mSurface(nullptr),
|
mSurface(nullptr),
|
||||||
mPictureRect(aData->GetPictureRect()),
|
mPictureRect(aData->GetPictureRect()),
|
||||||
mAlphaType(aAlphaType),
|
mAlphaType(aAlphaType),
|
||||||
mAllocatedImageData(false),
|
mAllocatedImageData(aAllocatedImageData),
|
||||||
mWriteOnly(aWriteOnly) {
|
mWriteOnly(aWriteOnly) {
|
||||||
MOZ_ASSERT(aData, "aData is null in ImageBitmap constructor.");
|
MOZ_ASSERT(aData, "aData is null in ImageBitmap constructor.");
|
||||||
|
|
||||||
@@ -689,6 +691,7 @@ JSObject* ImageBitmap::WrapObject(JSContext* aCx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ImageBitmap::Close() {
|
void ImageBitmap::Close() {
|
||||||
|
RemoveAssociatedMemory();
|
||||||
mData = nullptr;
|
mData = nullptr;
|
||||||
mSurface = nullptr;
|
mSurface = nullptr;
|
||||||
mPictureRect.SetEmpty();
|
mPictureRect.SetEmpty();
|
||||||
@@ -969,8 +972,7 @@ already_AddRefed<ImageBitmap> ImageBitmap::CreateFromSourceSurface(
|
|||||||
nsIGlobalObject* aGlobal, gfx::SourceSurface* aSource, ErrorResult& aRv) {
|
nsIGlobalObject* aGlobal, gfx::SourceSurface* aSource, ErrorResult& aRv) {
|
||||||
RefPtr<layers::Image> data = CreateImageFromSurface(aSource);
|
RefPtr<layers::Image> data = CreateImageFromSurface(aSource);
|
||||||
RefPtr<ImageBitmap> ret =
|
RefPtr<ImageBitmap> ret =
|
||||||
new ImageBitmap(aGlobal, data, false /* writeOnly */);
|
new ImageBitmap(aGlobal, data, true, false /* writeOnly */);
|
||||||
ret->mAllocatedImageData = true;
|
|
||||||
return ret.forget();
|
return ret.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -979,10 +981,8 @@ already_AddRefed<ImageBitmap> ImageBitmap::CreateFromCloneData(
|
|||||||
nsIGlobalObject* aGlobal, ImageBitmapCloneData* aData) {
|
nsIGlobalObject* aGlobal, ImageBitmapCloneData* aData) {
|
||||||
RefPtr<layers::Image> data = CreateImageFromSurface(aData->mSurface);
|
RefPtr<layers::Image> data = CreateImageFromSurface(aData->mSurface);
|
||||||
|
|
||||||
RefPtr<ImageBitmap> ret =
|
RefPtr<ImageBitmap> ret = new ImageBitmap(
|
||||||
new ImageBitmap(aGlobal, data, aData->mWriteOnly, aData->mAlphaType);
|
aGlobal, data, true, aData->mWriteOnly, aData->mAlphaType);
|
||||||
|
|
||||||
ret->mAllocatedImageData = true;
|
|
||||||
|
|
||||||
ErrorResult rv;
|
ErrorResult rv;
|
||||||
ret->SetPictureRect(aData->mPictureRect, rv);
|
ret->SetPictureRect(aData->mPictureRect, rv);
|
||||||
@@ -1010,9 +1010,7 @@ already_AddRefed<ImageBitmap> ImageBitmap::CreateFromOffscreenCanvas(
|
|||||||
|
|
||||||
RefPtr<layers::Image> data = CreateImageFromSurface(surface);
|
RefPtr<layers::Image> data = CreateImageFromSurface(surface);
|
||||||
|
|
||||||
RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, writeOnly);
|
RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, true, writeOnly);
|
||||||
|
|
||||||
ret->mAllocatedImageData = true;
|
|
||||||
|
|
||||||
return ret.forget();
|
return ret.forget();
|
||||||
}
|
}
|
||||||
@@ -1128,12 +1126,8 @@ already_AddRefed<ImageBitmap> ImageBitmap::CreateImageBitmapInternal(
|
|||||||
|
|
||||||
// Create an Image from the SourceSurface.
|
// Create an Image from the SourceSurface.
|
||||||
RefPtr<layers::Image> data = CreateImageFromSurface(surface);
|
RefPtr<layers::Image> data = CreateImageFromSurface(surface);
|
||||||
RefPtr<ImageBitmap> ret =
|
RefPtr<ImageBitmap> ret = new ImageBitmap(
|
||||||
new ImageBitmap(aGlobal, data, aWriteOnly, alphaType);
|
aGlobal, data, needToReportMemoryAllocation, aWriteOnly, alphaType);
|
||||||
|
|
||||||
if (needToReportMemoryAllocation) {
|
|
||||||
ret->mAllocatedImageData = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the picture rectangle.
|
// Set the picture rectangle.
|
||||||
ret->SetPictureRect(cropRect, aRv);
|
ret->SetPictureRect(cropRect, aRv);
|
||||||
@@ -1232,7 +1226,7 @@ already_AddRefed<ImageBitmap> ImageBitmap::CreateInternal(
|
|||||||
RefPtr<SourceSurface> surface = data->GetAsSourceSurface();
|
RefPtr<SourceSurface> surface = data->GetAsSourceSurface();
|
||||||
if (!surface) {
|
if (!surface) {
|
||||||
// preserve original behavior in case of unavailble surface
|
// preserve original behavior in case of unavailble surface
|
||||||
RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, writeOnly);
|
RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, false, writeOnly);
|
||||||
return ret.forget();
|
return ret.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1399,9 +1393,8 @@ already_AddRefed<ImageBitmap> ImageBitmap::CreateInternal(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create an ImageBitmap.
|
// Create an ImageBitmap.
|
||||||
RefPtr<ImageBitmap> ret =
|
RefPtr<ImageBitmap> ret = new ImageBitmap(
|
||||||
new ImageBitmap(aGlobal, data, false /* write-only */, alphaType);
|
aGlobal, data, true, false /* write-only */, alphaType);
|
||||||
ret->mAllocatedImageData = true;
|
|
||||||
|
|
||||||
// The cropping information has been handled in the
|
// The cropping information has been handled in the
|
||||||
// CreateImageFromRawData() function.
|
// CreateImageFromRawData() function.
|
||||||
@@ -1911,7 +1904,7 @@ JSObject* ImageBitmap::ReadStructuredClone(
|
|||||||
#endif
|
#endif
|
||||||
RefPtr<layers::Image> img = CreateImageFromSurface(aClonedSurfaces[aIndex]);
|
RefPtr<layers::Image> img = CreateImageFromSurface(aClonedSurfaces[aIndex]);
|
||||||
RefPtr<ImageBitmap> imageBitmap =
|
RefPtr<ImageBitmap> imageBitmap =
|
||||||
new ImageBitmap(aParent, img, !!writeOnly, alphaType);
|
new ImageBitmap(aParent, img, true, !!writeOnly, alphaType);
|
||||||
|
|
||||||
ErrorResult error;
|
ErrorResult error;
|
||||||
imageBitmap->SetPictureRect(
|
imageBitmap->SetPictureRect(
|
||||||
@@ -1924,8 +1917,6 @@ JSObject* ImageBitmap::ReadStructuredClone(
|
|||||||
if (!GetOrCreateDOMReflector(aCx, imageBitmap, &value)) {
|
if (!GetOrCreateDOMReflector(aCx, imageBitmap, &value)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
imageBitmap->mAllocatedImageData = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &(value.toObject());
|
return &(value.toObject());
|
||||||
@@ -2000,32 +1991,42 @@ void ImageBitmap::WriteStructuredClone(
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t ImageBitmap::GetAllocatedSize() const {
|
size_t ImageBitmap::GetAllocatedSize() const {
|
||||||
if (!mAllocatedImageData) {
|
if (!mAllocatedImageData || !mData) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate how many bytes are used.
|
// Calculate how many bytes are used.
|
||||||
if (mData->GetFormat() == mozilla::ImageFormat::PLANAR_YCBCR) {
|
switch (mData->GetFormat()) {
|
||||||
return mData->AsPlanarYCbCrImage()->GetDataSize();
|
case ImageFormat::PLANAR_YCBCR:
|
||||||
|
return mData->AsPlanarYCbCrImage()->GetDataSize();
|
||||||
|
case ImageFormat::NV_IMAGE:
|
||||||
|
return mData->AsNVImage()->GetBufferSize();
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mData->GetFormat() == mozilla::ImageFormat::NV_IMAGE) {
|
IntSize size = mData->GetSize();
|
||||||
return mData->AsNVImage()->GetBufferSize();
|
CheckedInt<uint32_t> bytes =
|
||||||
}
|
CheckedInt<uint32_t>(size.width) * size.height * 4;
|
||||||
|
return bytes.isValid() ? bytes.value() : 0;
|
||||||
RefPtr<SourceSurface> surface = mData->GetAsSourceSurface();
|
|
||||||
if (NS_WARN_IF(!surface)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int bytesPerPixel = BytesPerPixel(surface->GetFormat());
|
|
||||||
return surface->GetSize().height * surface->GetSize().width * bytesPerPixel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t BindingJSObjectMallocBytes(ImageBitmap* aBitmap) {
|
size_t BindingJSObjectMallocBytes(ImageBitmap* aBitmap) {
|
||||||
return aBitmap->GetAllocatedSize();
|
return aBitmap->GetAllocatedSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ImageBitmap::RemoveAssociatedMemory() {
|
||||||
|
if (!mAllocatedImageData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (JSObject* wrapper = GetWrapperMaybeDead()) {
|
||||||
|
if (size_t bytes = BindingJSObjectMallocBytes(this)) {
|
||||||
|
JS::RemoveAssociatedMemory(wrapper, bytes, JS::MemoryUse::DOMBinding);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mAllocatedImageData = false;
|
||||||
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
already_AddRefed<CreateImageBitmapFromBlob> CreateImageBitmapFromBlob::Create(
|
already_AddRefed<CreateImageBitmapFromBlob> CreateImageBitmapFromBlob::Create(
|
||||||
Promise* aPromise, nsIGlobalObject* aGlobal, Blob& aBlob,
|
Promise* aPromise, nsIGlobalObject* aGlobal, Blob& aBlob,
|
||||||
@@ -2338,8 +2339,8 @@ void CreateImageBitmapFromBlob::
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create ImageBitmap object.
|
// Create ImageBitmap object.
|
||||||
RefPtr<ImageBitmap> imageBitmap =
|
RefPtr<ImageBitmap> imageBitmap = new ImageBitmap(
|
||||||
new ImageBitmap(mGlobalObject, aImage, false /* write-only */, alphaType);
|
mGlobalObject, aImage, true, false /* write-only */, alphaType);
|
||||||
|
|
||||||
if (mCropRect.isSome()) {
|
if (mCropRect.isSome()) {
|
||||||
ErrorResult rv;
|
ErrorResult rv;
|
||||||
@@ -2351,8 +2352,6 @@ void CreateImageBitmapFromBlob::
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
imageBitmap->mAllocatedImageData = true;
|
|
||||||
|
|
||||||
mPromise->MaybeResolve(imageBitmap);
|
mPromise->MaybeResolve(imageBitmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -172,13 +172,16 @@ class ImageBitmap final : public nsISupports, public nsWrapperCache {
|
|||||||
* the aIsPremultipliedAlpha to be false in the
|
* the aIsPremultipliedAlpha to be false in the
|
||||||
* CreateInternal(from ImageData) method.
|
* CreateInternal(from ImageData) method.
|
||||||
*/
|
*/
|
||||||
ImageBitmap(nsIGlobalObject* aGlobal, layers::Image* aData, bool aWriteOnly,
|
ImageBitmap(nsIGlobalObject* aGlobal, layers::Image* aData,
|
||||||
|
bool aAllocatedImageData, bool aWriteOnly,
|
||||||
gfxAlphaType aAlphaType = gfxAlphaType::Premult);
|
gfxAlphaType aAlphaType = gfxAlphaType::Premult);
|
||||||
|
|
||||||
virtual ~ImageBitmap();
|
virtual ~ImageBitmap();
|
||||||
|
|
||||||
void SetPictureRect(const gfx::IntRect& aRect, ErrorResult& aRv);
|
void SetPictureRect(const gfx::IntRect& aRect, ErrorResult& aRv);
|
||||||
|
|
||||||
|
void RemoveAssociatedMemory();
|
||||||
|
|
||||||
static already_AddRefed<ImageBitmap> CreateImageBitmapInternal(
|
static already_AddRefed<ImageBitmap> CreateImageBitmapInternal(
|
||||||
nsIGlobalObject* aGlobal, gfx::SourceSurface* aSurface,
|
nsIGlobalObject* aGlobal, gfx::SourceSurface* aSurface,
|
||||||
const Maybe<gfx::IntRect>& aCropRect, const ImageBitmapOptions& aOptions,
|
const Maybe<gfx::IntRect>& aCropRect, const ImageBitmapOptions& aOptions,
|
||||||
@@ -279,6 +282,8 @@ class ImageBitmap final : public nsISupports, public nsWrapperCache {
|
|||||||
bool mWriteOnly;
|
bool mWriteOnly;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
size_t BindingJSObjectMallocBytes(ImageBitmap* aBitmap);
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user