Bug 1312148 - report memory allocation while creating ImageBitmap; r=mtseng,smaug

Creating ImageBitmap from the following sources includes allocating new memory:
(1) from ImageData.
(2) from Blob.
(3) from HTMLCanvasElement.
(4) from CanvasRenderingContext2D.
(5) from Structured-clone.
(6) from Transferring.
(7) from OffscreenCanvas.
(8) from ArrayBuffer/TypedArray.

We need to report to DOM so that the GC would be triggered appropriately.

MozReview-Commit-ID: 7rvNsjVNqpz

--HG--
extra : rebase_source : 25760f91bd71fe2150fa3ae37dfc1fb8b53c15a4
This commit is contained in:
Kaku Kuo 2016-10-28 18:18:48 +08:00
parent 6acb5b36ed
commit de99dd7b42

View File

@ -34,6 +34,19 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ImageBitmap)
NS_INTERFACE_MAP_ENTRY(nsISupports) NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END NS_INTERFACE_MAP_END
/*
* This helper function is used to notify DOM that aBytes memory is allocated
* here so that we could trigger GC appropriately.
*/
static void
RegisterAllocation(nsIGlobalObject* aGlobal, size_t aBytes)
{
AutoJSAPI jsapi;
if (jsapi.Init(aGlobal)) {
JS_updateMallocCounter(jsapi.cx(), aBytes);
}
}
/* /*
* If either aRect.width or aRect.height are negative, then return a new IntRect * If either aRect.width or aRect.height are negative, then return a new IntRect
* which represents the same rectangle as the aRect does but with positive width * which represents the same rectangle as the aRect does but with positive width
@ -707,6 +720,9 @@ ImageBitmap::CreateFromCloneData(nsIGlobalObject* aGlobal,
RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data,
aData->mIsPremultipliedAlpha); aData->mIsPremultipliedAlpha);
// Report memory allocation.
RegisterAllocation(aGlobal, ret->mDataWrapper->GetBufferLength());
ret->mIsCroppingAreaOutSideOfSourceImage = ret->mIsCroppingAreaOutSideOfSourceImage =
aData->mIsCroppingAreaOutSideOfSourceImage; aData->mIsCroppingAreaOutSideOfSourceImage;
@ -741,6 +757,10 @@ ImageBitmap::CreateFromOffscreenCanvas(nsIGlobalObject* aGlobal,
CreateImageFromSurface(surface); CreateImageFromSurface(surface);
RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data); RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data);
// Report memory allocation.
RegisterAllocation(aGlobal, ret->mDataWrapper->GetBufferLength());
return ret.forget(); return ret.forget();
} }
@ -865,6 +885,7 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, HTMLCanvasElement& aCanvas
// If the HTMLCanvasElement's rendering context is WebGL, then the snapshot // If the HTMLCanvasElement's rendering context is WebGL, then the snapshot
// we got from the HTMLCanvasElement is a DataSourceSurface which is a copy // we got from the HTMLCanvasElement is a DataSourceSurface which is a copy
// of the rendering context. We handle cropping in this case. // of the rendering context. We handle cropping in this case.
bool needToReportMemoryAllocation = false;
if ((aCanvasEl.GetCurrentContextType() == CanvasContextType::WebGL1 || if ((aCanvasEl.GetCurrentContextType() == CanvasContextType::WebGL1 ||
aCanvasEl.GetCurrentContextType() == CanvasContextType::WebGL2) && aCanvasEl.GetCurrentContextType() == CanvasContextType::WebGL2) &&
aCropRect.isSome()) { aCropRect.isSome()) {
@ -875,6 +896,7 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, HTMLCanvasElement& aCanvas
RefPtr<DataSourceSurface> dataSurface = surface->GetDataSurface(); RefPtr<DataSourceSurface> dataSurface = surface->GetDataSurface();
croppedSurface = CropAndCopyDataSourceSurface(dataSurface, cropRect); croppedSurface = CropAndCopyDataSourceSurface(dataSurface, cropRect);
cropRect.MoveTo(0, 0); cropRect.MoveTo(0, 0);
needToReportMemoryAllocation = true;
} }
else { else {
croppedSurface = surface; croppedSurface = surface;
@ -895,6 +917,11 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, HTMLCanvasElement& aCanvas
RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data); RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data);
// Report memory allocation if needed.
if (needToReportMemoryAllocation) {
RegisterAllocation(aGlobal, ret->mDataWrapper->GetBufferLength());
}
// Set the picture rectangle. // Set the picture rectangle.
if (ret && aCropRect.isSome()) { if (ret && aCropRect.isSome()) {
ret->SetPictureRect(cropRect, aRv); ret->SetPictureRect(cropRect, aRv);
@ -958,6 +985,9 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, ImageData& aImageData,
// ImageData's underlying data is not alpha-premultiplied. // ImageData's underlying data is not alpha-premultiplied.
RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, false); RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, false);
// Report memory allocation.
RegisterAllocation(aGlobal, ret->mDataWrapper->GetBufferLength());
// The cropping information has been handled in the CreateImageFromRawData() // The cropping information has been handled in the CreateImageFromRawData()
// function. // function.
@ -999,6 +1029,9 @@ ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, CanvasRenderingContext2D&
RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data); RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data);
// Report memory allocation.
RegisterAllocation(aGlobal, ret->mDataWrapper->GetBufferLength());
// Set the picture rectangle. // Set the picture rectangle.
if (ret && aCropRect.isSome()) { if (ret && aCropRect.isSome()) {
ret->SetPictureRect(aCropRect.ref(), aRv); ret->SetPictureRect(aCropRect.ref(), aRv);
@ -1240,6 +1273,9 @@ protected:
} }
} }
// Report memory allocation.
RegisterAllocation(mGlobalObject, imageBitmap->mDataWrapper->GetBufferLength());
mPromise->MaybeResolve(imageBitmap); mPromise->MaybeResolve(imageBitmap);
return true; return true;
} }
@ -1524,6 +1560,9 @@ ImageBitmap::ReadStructuredClone(JSContext* aCx,
if (!GetOrCreateDOMReflector(aCx, imageBitmap, &value)) { if (!GetOrCreateDOMReflector(aCx, imageBitmap, &value)) {
return nullptr; return nullptr;
} }
// Report memory allocation.
RegisterAllocation(aParent, imageBitmap->mDataWrapper->GetBufferLength());
} }
return &(value.toObject()); return &(value.toObject());
@ -2112,6 +2151,9 @@ ImageBitmap::Create(nsIGlobalObject* aGlobal,
// Assume the data from an external buffer is not alpha-premultiplied. // Assume the data from an external buffer is not alpha-premultiplied.
RefPtr<ImageBitmap> imageBitmap = new ImageBitmap(aGlobal, data, false); RefPtr<ImageBitmap> imageBitmap = new ImageBitmap(aGlobal, data, false);
// Report memory allocation.
RegisterAllocation(aGlobal, imageBitmap->mDataWrapper->GetBufferLength());
// We don't need to call SetPictureRect() here because there is no cropping // We don't need to call SetPictureRect() here because there is no cropping
// supported and the ImageBitmap's mPictureRect is the size of the source // supported and the ImageBitmap's mPictureRect is the size of the source
// image in default // image in default