author | Justin Lebar <justin.lebar@gmail.com> |
Wed, 24 Oct 2012 22:06:31 -0400 | |
changeset 111320 | acbfd1eebb3bdabb5f02a83f67dfe66a49938c6a |
parent 111319 | 05636b372638e8effb4f486fdfe87a6322e664ca |
child 111321 | 888ac1c4683084aaea58aeba89dbb50074b4008a |
push id | 17008 |
push user | jlebar@mozilla.com |
push date | Thu, 25 Oct 2012 02:06:51 +0000 |
treeherder | mozilla-inbound@acbfd1eebb3b [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | khuey, njn |
bugs | 803684 |
milestone | 19.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
|
content/base/public/nsDOMFile.h | file | annotate | diff | comparison | revisions | |
content/base/src/nsDOMFile.cpp | file | annotate | diff | comparison | revisions |
--- a/content/base/public/nsDOMFile.h +++ b/content/base/public/nsDOMFile.h @@ -16,17 +16,19 @@ #include "nsCOMArray.h" #include "nsCOMPtr.h" #include "nsString.h" #include "nsIXMLHttpRequest.h" #include "prmem.h" #include "nsAutoPtr.h" #include "mozilla/GuardObjects.h" +#include "mozilla/LinkedList.h" #include "mozilla/StandardInteger.h" +#include "mozilla/StaticPtr.h" #include "mozilla/dom/DOMError.h" #include "mozilla/dom/indexedDB/FileInfo.h" #include "mozilla/dom/indexedDB/FileManager.h" #include "mozilla/dom/indexedDB/IndexedDatabaseManager.h" #include "nsWrapperCache.h" #include "nsCycleCollectionParticipant.h" class nsIFile; @@ -355,27 +357,27 @@ class nsDOMMemoryFile : public nsDOMFile { public: // Create as file nsDOMMemoryFile(void *aMemoryBuffer, uint64_t aLength, const nsAString& aName, const nsAString& aContentType) : nsDOMFile(aName, aContentType, aLength, UINT64_MAX), - mDataOwner(new DataOwner(aMemoryBuffer)) + mDataOwner(new DataOwner(aMemoryBuffer, aLength)) { NS_ASSERTION(mDataOwner && mDataOwner->mData, "must have data"); } // Create as blob nsDOMMemoryFile(void *aMemoryBuffer, uint64_t aLength, const nsAString& aContentType) : nsDOMFile(aContentType, aLength), - mDataOwner(new DataOwner(aMemoryBuffer)) + mDataOwner(new DataOwner(aMemoryBuffer, aLength)) { NS_ASSERTION(mDataOwner && mDataOwner->mData, "must have data"); } NS_IMETHOD GetInternalStream(nsIInputStream**); protected: // Create slice @@ -386,28 +388,50 @@ protected: { NS_ASSERTION(mDataOwner && mDataOwner->mData, "must have data"); mImmutable = aOther->mImmutable; } virtual already_AddRefed<nsIDOMBlob> CreateSlice(uint64_t aStart, uint64_t aLength, const nsAString& aContentType); - friend class DataOwnerAdapter; // Needs to see DataOwner - class DataOwner { + // These classes need to see DataOwner. + friend class DataOwnerAdapter; + friend class nsDOMMemoryFileDataOwnerMemoryReporter; + + class DataOwner : public mozilla::LinkedListElement<DataOwner> { public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DataOwner) - DataOwner(void* aMemoryBuffer) + DataOwner(void* aMemoryBuffer, uint64_t aLength) : mData(aMemoryBuffer) + , mLength(aLength) { + if (!sDataOwners) { + sDataOwners = new mozilla::LinkedList<DataOwner>(); + EnsureMemoryReporterRegistered(); + } + sDataOwners->insertBack(this); } + ~DataOwner() { + remove(); + if (sDataOwners->isEmpty()) { + // Free the linked list if it's empty. + sDataOwners = nullptr; + } + PR_Free(mData); } + + static void EnsureMemoryReporterRegistered(); + + static bool sMemoryReporterRegistered; + static mozilla::StaticAutoPtr<mozilla::LinkedList<DataOwner> > sDataOwners; void* mData; + uint64_t mLength; }; // Used when backed by a memory store nsRefPtr<DataOwner> mDataOwner; }; class nsDOMFileList MOZ_FINAL : public nsIDOMFileList, public nsWrapperCache
--- a/content/base/src/nsDOMFile.cpp +++ b/content/base/src/nsDOMFile.cpp @@ -13,27 +13,30 @@ #include "nsICharsetDetector.h" #include "nsICharsetConverterManager.h" #include "nsIClassInfo.h" #include "nsIConverterInputStream.h" #include "nsIDocument.h" #include "nsIFileStreams.h" #include "nsIInputStream.h" #include "nsIIPCSerializableInputStream.h" +#include "nsIMemoryReporter.h" #include "nsIMIMEService.h" #include "nsIPlatformCharset.h" #include "nsISeekableStream.h" #include "nsIUnicharInputStream.h" #include "nsIUnicodeDecoder.h" #include "nsNetCID.h" #include "nsNetUtil.h" #include "nsIUUIDGenerator.h" #include "nsBlobProtocolHandler.h" #include "nsStringStream.h" #include "nsJSUtils.h" +#include "nsPrintfCString.h" +#include "mozilla/SHA1.h" #include "mozilla/CheckedInt.h" #include "mozilla/Preferences.h" #include "mozilla/Attributes.h" #include "plbase64.h" #include "prmem.h" #include "mozilla/dom/FileListBinding.h" @@ -682,16 +685,131 @@ NS_IMETHODIMP nsDOMMemoryFile::GetInternalStream(nsIInputStream **aStream) { if (mLength > INT32_MAX) return NS_ERROR_FAILURE; return DataOwnerAdapter::Create(mDataOwner, mStart, mLength, aStream); } +/* static */ StaticAutoPtr<LinkedList<nsDOMMemoryFile::DataOwner> > +nsDOMMemoryFile::DataOwner::sDataOwners; + +/* static */ bool +nsDOMMemoryFile::DataOwner::sMemoryReporterRegistered; + +NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(DOMMemoryFileDataOwnerSizeOf, + "memory-file-data"); + +class nsDOMMemoryFileDataOwnerMemoryReporter + : public nsIMemoryMultiReporter +{ + NS_DECL_ISUPPORTS + + NS_IMETHOD GetName(nsACString& aName) + { + aName.AssignASCII("dom-memory-file-data-owner"); + return NS_OK; + } + + NS_IMETHOD GetExplicitNonHeap(int64_t *aResult) + { + // All of this reporter's memory is on the heap. + *aResult = 0; + return NS_OK; + } + + NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback *aCallback, + nsISupports *aClosure) + { + typedef nsDOMMemoryFile::DataOwner DataOwner; + + if (!DataOwner::sDataOwners) { + return NS_OK; + } + + const size_t LARGE_OBJECT_MIN_SIZE = 8 * 1024; + size_t smallObjectsTotal = 0; + + for (DataOwner *owner = DataOwner::sDataOwners->getFirst(); + owner; owner = owner->getNext()) { + + size_t size = DOMMemoryFileDataOwnerSizeOf(owner->mData); + + if (size < LARGE_OBJECT_MIN_SIZE) { + smallObjectsTotal += size; + } + else { + SHA1Sum sha1; + sha1.update(owner->mData, owner->mLength); + uint8_t digest[SHA1Sum::HashSize]; // SHA1 digests are 20 bytes long. + sha1.finish(digest); + + nsAutoCString digestString; + for (uint8_t i = 0; i < sizeof(digest); i++) { + digestString.AppendPrintf("%02x", digest[i]); + } + + nsresult rv = aCallback->Callback( + /* process */ NS_LITERAL_CSTRING(""), + nsPrintfCString( + "explicit/dom/memory-file-data/large/file(length=%d, sha1=%s)", + owner->mLength, digestString.get()), + nsIMemoryReporter::KIND_HEAP, + nsIMemoryReporter::UNITS_BYTES, + size, + nsPrintfCString( + "Memory used to back a memory file of length %d. The file has a " + "sha1 of %s.\n\n" + "Note that the allocator may round up a memory file's length -- " + "that is, an N-byte memory file may take up more than N bytes of " + "memory.", + owner->mLength, digestString.get()), + aClosure); + NS_ENSURE_SUCCESS(rv, rv); + } + } + + if (smallObjectsTotal > 0) { + nsresult rv = aCallback->Callback( + /* process */ NS_LITERAL_CSTRING(""), + NS_LITERAL_CSTRING("explicit/dom/memory-file-data/small"), + nsIMemoryReporter::KIND_HEAP, + nsIMemoryReporter::UNITS_BYTES, + smallObjectsTotal, + nsPrintfCString( + "Memory used to back small memory files (less than %d bytes each).\n\n" + "Note that the allocator may round up a memory file's length -- " + "that is, an N-byte memory file may take up more than N bytes of " + "memory."), + aClosure); + NS_ENSURE_SUCCESS(rv, rv); + } + + return NS_OK; + } +}; + +NS_IMPL_ISUPPORTS1(nsDOMMemoryFileDataOwnerMemoryReporter, + nsIMemoryMultiReporter); + +/* static */ void +nsDOMMemoryFile::DataOwner::EnsureMemoryReporterRegistered() +{ + if (sMemoryReporterRegistered) { + return; + } + + nsRefPtr<nsDOMMemoryFileDataOwnerMemoryReporter> reporter = new + nsDOMMemoryFileDataOwnerMemoryReporter(); + NS_RegisterMemoryMultiReporter(reporter); + + sMemoryReporterRegistered = true; +} + //////////////////////////////////////////////////////////////////////////// // nsDOMFileList implementation DOMCI_DATA(FileList, nsDOMFileList) NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(nsDOMFileList) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMFileList)