diff --git a/accessible/src/jsat/OutputGenerator.jsm b/accessible/src/jsat/OutputGenerator.jsm index f340a245c0d..3a7ecec1f53 100644 --- a/accessible/src/jsat/OutputGenerator.jsm +++ b/accessible/src/jsat/OutputGenerator.jsm @@ -220,7 +220,12 @@ this.OutputGenerator = { if (!typeName || typeName === 'text') { return; } - aDesc.push(gStringBundle.GetStringFromName('textInputType_' + typeName)); + typeName = 'textInputType_' + typeName; + try { + aDesc.push(gStringBundle.GetStringFromName(typeName)); + } catch (x) { + Logger.warning('Failed to get a string from a bundle for', typeName); + } }, get outputOrder() { diff --git a/accessible/tests/mochitest/jsat/test_utterance_order.html b/accessible/tests/mochitest/jsat/test_utterance_order.html index 2ab7e40c9df..bb661893bbc 100644 --- a/accessible/tests/mochitest/jsat/test_utterance_order.html +++ b/accessible/tests/mochitest/jsat/test_utterance_order.html @@ -83,6 +83,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=753984 "Column 1 Row 1", "Fruits and vegetables", "table with 1 column and 1 row" ]] + }, { + accOrElmOrID: "date", + expected: [["date entry", "2011-09-29"], ["2011-09-29", "date entry"]] }, { accOrElmOrID: "email", expected: [ @@ -302,6 +305,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=753984 + diff --git a/browser/app/profile/extensions/Makefile.in b/browser/app/profile/extensions/Makefile.in deleted file mode 100644 index 3cac5851b51..00000000000 --- a/browser/app/profile/extensions/Makefile.in +++ /dev/null @@ -1,40 +0,0 @@ -# -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -DISTROEXT = $(abspath $(FINAL_TARGET))/distribution/extensions - -include $(topsrcdir)/config/config.mk - -ifneq (,$(filter beta,$(MOZ_UPDATE_CHANNEL))) -EXTENSIONS = \ - $(NULL) - -all_xpis = $(foreach dir,$(EXTENSIONS),$(DISTROEXT)/$(dir).xpi) -libs:: $(all_xpis) -GARBAGE += $(all_xpis) - -define pp_one -$(2) := $(2) -$(2)_PATH := $(dir $(2)) -$(2)_TARGET := libs-$(1) -PP_TARGETS += $(2) -endef -$(foreach d,$(EXTENSIONS), \ - $(foreach in,$(shell cd $(srcdir) ; find $(d) -name '*.in'), \ - $(eval $(call pp_one,$(d),$(in))) \ - ) \ -) - -endif - -include $(topsrcdir)/config/rules.mk - -$(all_xpis): $(DISTROEXT)/%.xpi: $(call mkdir_deps,$(DISTROEXT)) libs-% - cd $* && \ - $(ZIP) -r9XD $@ * -x \*.in -x \*.mkdir.done - cd $(abspath $(srcdir)/$*) && \ - $(ZIP) -r9XD $@ * -x \*.in -x \*.mkdir.done - -.PHONY: $(all_xpis:.xpi=) diff --git a/browser/devtools/webconsole/test/browser.ini b/browser/devtools/webconsole/test/browser.ini index dc441e50d45..2e092f70f0b 100644 --- a/browser/devtools/webconsole/test/browser.ini +++ b/browser/devtools/webconsole/test/browser.ini @@ -185,6 +185,8 @@ support-files = [browser_webconsole_bug_630733_response_redirect_headers.js] [browser_webconsole_bug_632275_getters_document_width.js] [browser_webconsole_bug_632347_iterators_generators.js] +# Too many intermittent timeouts (bug 935277) +skip-if = os == "linux" [browser_webconsole_bug_632817.js] [browser_webconsole_bug_642108_pruneTest.js] [browser_webconsole_bug_642615_autocomplete.js] diff --git a/build/Makefile.in b/build/Makefile.in index d47fef04487..768e63da945 100644 --- a/build/Makefile.in +++ b/build/Makefile.in @@ -47,6 +47,10 @@ DEFINES += \ -DACCEPTED_MAR_CHANNEL_IDS="$(ACCEPTED_MAR_CHANNEL_IDS)" \ $(NULL) +ifeq ($(MOZ_BUILD_APP),browser) +DEFINES += -DMOZ_BUILD_APP_IS_BROWSER +endif + ifdef MOZ_APP_PROFILE DEFINES += -DMOZ_APP_PROFILE="$(MOZ_APP_PROFILE)" endif diff --git a/build/application.ini b/build/application.ini index bb27da61f6f..7d816a49195 100644 --- a/build/application.ini +++ b/build/application.ini @@ -1,8 +1,14 @@ #if MOZ_APP_STATIC_INI +#ifdef MOZ_BUILD_APP_IS_BROWSER +; This file is not used. If you modify it and want the application to use +; your modifications, move it under the browser/ subdirectory and start with +; the "-app /path/to/browser/application.ini" argument. +#else ; This file is not used. If you modify it and want the application to use ; your modifications, start with the "-app /path/to/application.ini" ; argument. #endif +#endif #if 0 ; This Source Code Form is subject to the terms of the Mozilla Public ; License, v. 2.0. If a copy of the MPL was not distributed with this diff --git a/content/base/src/nsDOMFile.cpp b/content/base/src/nsDOMFile.cpp index 7fdef4474c3..48f69f49f5d 100644 --- a/content/base/src/nsDOMFile.cpp +++ b/content/base/src/nsDOMFile.cpp @@ -1,4 +1,5 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -645,15 +646,12 @@ nsDOMMemoryFile::DataOwner::sMemoryReporterRegistered; NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(DOMMemoryFileDataOwnerMallocSizeOf) class nsDOMMemoryFileDataOwnerMemoryReporter MOZ_FINAL - : public nsIMemoryReporter + : public MemoryMultiReporter { - NS_DECL_THREADSAFE_ISUPPORTS - - NS_IMETHOD GetName(nsACString& aName) - { - aName.AssignASCII("dom-memory-file-data-owner"); - return NS_OK; - } +public: + nsDOMMemoryFileDataOwnerMemoryReporter() + : MemoryMultiReporter("dom-memory-file-data-owner") + {} NS_IMETHOD CollectReports(nsIMemoryReporterCallback *aCallback, nsISupports *aClosure) @@ -728,9 +726,6 @@ class nsDOMMemoryFileDataOwnerMemoryReporter MOZ_FINAL } }; -NS_IMPL_ISUPPORTS1(nsDOMMemoryFileDataOwnerMemoryReporter, - nsIMemoryReporter) - /* static */ void nsDOMMemoryFile::DataOwner::EnsureMemoryReporterRegistered() { diff --git a/content/base/src/nsFrameMessageManager.cpp b/content/base/src/nsFrameMessageManager.cpp index bc94b0d8e25..a989affc923 100644 --- a/content/base/src/nsFrameMessageManager.cpp +++ b/content/base/src/nsFrameMessageManager.cpp @@ -1080,11 +1080,15 @@ struct MessageManagerReferentCount namespace mozilla { namespace dom { -class MessageManagerReporter MOZ_FINAL : public nsIMemoryReporter +class MessageManagerReporter MOZ_FINAL : public MemoryMultiReporter { public: - NS_DECL_ISUPPORTS - NS_DECL_NSIMEMORYREPORTER + MessageManagerReporter() + : MemoryMultiReporter("message-manager") + {} + + NS_IMETHOD CollectReports(nsIMemoryReporterCallback* aCallback, + nsISupports* aData); static const size_t kSuspectReferentCount = 300; protected: @@ -1092,8 +1096,6 @@ protected: MessageManagerReferentCount* aReferentCount); }; -NS_IMPL_ISUPPORTS1(MessageManagerReporter, nsIMemoryReporter) - static PLDHashOperator CollectMessageListenerData(const nsAString& aKey, nsAutoTObserverArray* aListeners, @@ -1153,13 +1155,6 @@ MessageManagerReporter::CountReferents(nsFrameMessageManager* aMessageManager, } } -NS_IMETHODIMP -MessageManagerReporter::GetName(nsACString& aName) -{ - aName.AssignLiteral("message-manager"); - return NS_OK; -} - static nsresult ReportReferentCount(const char* aManagerType, const MessageManagerReferentCount& aReferentCount, diff --git a/content/canvas/src/WebGLContextReporter.cpp b/content/canvas/src/WebGLContextReporter.cpp index 8b42f8b475b..f98153d4504 100644 --- a/content/canvas/src/WebGLContextReporter.cpp +++ b/content/canvas/src/WebGLContextReporter.cpp @@ -11,22 +11,17 @@ using namespace mozilla; NS_IMPL_ISUPPORTS1(WebGLMemoryPressureObserver, nsIObserver) -class WebGLMemoryReporter MOZ_FINAL : public nsIMemoryReporter +class WebGLMemoryReporter MOZ_FINAL : public MemoryMultiReporter { - public: - NS_DECL_ISUPPORTS - NS_DECL_NSIMEMORYREPORTER +public: + WebGLMemoryReporter() + : MemoryMultiReporter("webgl") + {} + + NS_IMETHOD CollectReports(nsIMemoryReporterCallback* aCb, + nsISupports* aClosure); }; -NS_IMPL_ISUPPORTS1(WebGLMemoryReporter, nsIMemoryReporter) - -NS_IMETHODIMP -WebGLMemoryReporter::GetName(nsACString &aName) -{ - aName.AssignLiteral("webgl"); - return NS_OK; -} - NS_IMETHODIMP WebGLMemoryReporter::CollectReports(nsIMemoryReporterCallback* aCb, nsISupports* aClosure) diff --git a/content/media/MediaDecoder.cpp b/content/media/MediaDecoder.cpp index c0de05d0050..6dc305faadc 100644 --- a/content/media/MediaDecoder.cpp +++ b/content/media/MediaDecoder.cpp @@ -1763,16 +1763,12 @@ MediaDecoder::IsAppleMP3Enabled() } #endif -class MediaReporter MOZ_FINAL : public nsIMemoryReporter +class MediaReporter MOZ_FINAL : public MemoryMultiReporter { public: - NS_DECL_ISUPPORTS - - NS_IMETHOD GetName(nsACString& aName) - { - aName.AssignLiteral("media"); - return NS_OK; - } + MediaReporter() + : MemoryMultiReporter("media") + {} NS_IMETHOD CollectReports(nsIMemoryReporterCallback* aCb, nsISupports* aClosure) @@ -1800,8 +1796,6 @@ public: } }; -NS_IMPL_ISUPPORTS1(MediaReporter, nsIMemoryReporter) - MediaDecoderOwner* MediaDecoder::GetOwner() { diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index 755e479cf85..26b54a6078a 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -433,7 +433,7 @@ ContentChild::InitXPCOM() } PMemoryReportRequestChild* -ContentChild::AllocPMemoryReportRequestChild() +ContentChild::AllocPMemoryReportRequestChild(const uint32_t& generation) { return new MemoryReportRequestChild(); } @@ -480,7 +480,9 @@ NS_IMPL_ISUPPORTS1( ) bool -ContentChild::RecvPMemoryReportRequestConstructor(PMemoryReportRequestChild* child) +ContentChild::RecvPMemoryReportRequestConstructor( + PMemoryReportRequestChild* child, + const uint32_t& generation) { nsCOMPtr mgr = do_GetService("@mozilla.org/memory-reporter-manager;1"); @@ -504,7 +506,7 @@ ContentChild::RecvPMemoryReportRequestConstructor(PMemoryReportRequestChild* chi r->CollectReports(cb, wrappedReports); } - child->Send__delete__(child, reports); + child->Send__delete__(child, generation, reports); return true; } diff --git a/dom/ipc/ContentChild.h b/dom/ipc/ContentChild.h index 40dfbe5ca7f..71e703a02e7 100644 --- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -111,13 +111,14 @@ public: virtual bool DeallocPIndexedDBChild(PIndexedDBChild* aActor); virtual PMemoryReportRequestChild* - AllocPMemoryReportRequestChild(); + AllocPMemoryReportRequestChild(const uint32_t& generation); virtual bool DeallocPMemoryReportRequestChild(PMemoryReportRequestChild* actor); virtual bool - RecvPMemoryReportRequestConstructor(PMemoryReportRequestChild* child); + RecvPMemoryReportRequestConstructor(PMemoryReportRequestChild* child, + const uint32_t& generation); virtual bool RecvAudioChannelNotify(); diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 3ae773bb5b3..c2a2366dd09 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -78,6 +78,7 @@ #include "nsISupportsPrimitives.h" #include "nsIURIFixup.h" #include "nsIWindowWatcher.h" +#include "nsMemoryReporterManager.h" #include "nsServiceManagerUtils.h" #include "nsStyleSheetService.h" #include "nsThreadUtils.h" @@ -160,61 +161,13 @@ namespace dom { #define NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC "ipc:network:set-offline" -// This represents all the memory reports provided by a child process. -class ChildReporter MOZ_FINAL : public nsIMemoryReporter -{ -public: - ChildReporter(const InfallibleTArray& childReports) - { - for (uint32_t i = 0; i < childReports.Length(); i++) { - MemoryReport r(childReports[i].process(), - childReports[i].path(), - childReports[i].kind(), - childReports[i].units(), - childReports[i].amount(), - childReports[i].desc()); - - // Child reports have a non-empty process. - MOZ_ASSERT(!r.process().IsEmpty()); - - mChildReports.AppendElement(r); - } - } - - NS_DECL_ISUPPORTS - - NS_IMETHOD GetName(nsACString& name) - { - name.AssignLiteral("content-child"); - return NS_OK; - } - - NS_IMETHOD CollectReports(nsIMemoryReporterCallback* aCb, - nsISupports* aClosure) - { - for (uint32_t i = 0; i < mChildReports.Length(); i++) { - nsresult rv; - MemoryReport r = mChildReports[i]; - rv = aCb->Callback(r.process(), r.path(), r.kind(), r.units(), - r.amount(), r.desc(), aClosure); - NS_ENSURE_SUCCESS(rv, rv); - } - return NS_OK; - } - - private: - InfallibleTArray mChildReports; -}; - -NS_IMPL_ISUPPORTS1(ChildReporter, nsIMemoryReporter) - class MemoryReportRequestParent : public PMemoryReportRequestParent { public: MemoryReportRequestParent(); virtual ~MemoryReportRequestParent(); - virtual bool Recv__delete__(const InfallibleTArray& report); + virtual bool Recv__delete__(const uint32_t& generation, const InfallibleTArray& report); private: ContentParent* Owner() { @@ -228,9 +181,13 @@ MemoryReportRequestParent::MemoryReportRequestParent() } bool -MemoryReportRequestParent::Recv__delete__(const InfallibleTArray& childReports) +MemoryReportRequestParent::Recv__delete__(const uint32_t& generation, const InfallibleTArray& childReports) { - Owner()->SetChildMemoryReports(childReports); + nsRefPtr mgr = + nsMemoryReporterManager::GetOrCreate(); + if (mgr) { + mgr->HandleChildReports(generation, childReports); + } return true; } @@ -239,29 +196,21 @@ MemoryReportRequestParent::~MemoryReportRequestParent() MOZ_COUNT_DTOR(MemoryReportRequestParent); } -/** - * A memory reporter for ContentParent objects themselves. - */ -class ContentParentMemoryReporter MOZ_FINAL : public nsIMemoryReporter +// A memory reporter for ContentParent objects themselves. +class ContentParentsMemoryReporter MOZ_FINAL : public MemoryMultiReporter { public: - NS_DECL_ISUPPORTS - NS_DECL_NSIMEMORYREPORTER - NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(MallocSizeOf) + ContentParentsMemoryReporter() + : MemoryMultiReporter("content-parents") + {} + + NS_IMETHOD CollectReports(nsIMemoryReporterCallback* cb, + nsISupports* aClosure); }; -NS_IMPL_ISUPPORTS1(ContentParentMemoryReporter, nsIMemoryReporter) - NS_IMETHODIMP -ContentParentMemoryReporter::GetName(nsACString& aName) -{ - aName.AssignLiteral("ContentParents"); - return NS_OK; -} - -NS_IMETHODIMP -ContentParentMemoryReporter::CollectReports(nsIMemoryReporterCallback* cb, - nsISupports* aClosure) +ContentParentsMemoryReporter::CollectReports(nsIMemoryReporterCallback* cb, + nsISupports* aClosure) { nsAutoTArray cps; ContentParent::GetAllEvenIfDead(cps); @@ -511,8 +460,7 @@ ContentParent::StartUp() return; } - nsRefPtr mr = new ContentParentMemoryReporter(); - NS_RegisterMemoryReporter(mr); + NS_RegisterMemoryReporter(new ContentParentsMemoryReporter()); sCanLaunchSubprocesses = true; @@ -1043,7 +991,6 @@ ContentParent::ShutDownProcess(bool aCloseWithError) // shut down the cycle collector. But by then it's too late to release any // CC'ed objects, so we need to null them out here, while we still can. See // bug 899761. - mChildReporter = nullptr; if (mMessageManager) { mMessageManager->Disconnect(); mMessageManager = nullptr; @@ -1218,8 +1165,12 @@ ContentParent::ActorDestroy(ActorDestroyReason why) ppm->Disconnect(); } - // unregister the child memory reporter - UnregisterChildMemoryReporter(); + // Tell the memory reporter manager that this ContentParent is going away. + nsRefPtr mgr = + nsMemoryReporterManager::GetOrCreate(); + if (mgr) { + mgr->DecrementNumChildProcesses(); + } // remove the global remote preferences observers Preferences::RemoveObserver(this, ""); @@ -1426,6 +1377,13 @@ ContentParent::ContentParent(mozIApplication* aApp, IToplevelProtocol::SetTransport(mSubprocess->GetChannel()); + // Tell the memory reporter manager that this ContentParent exists. + nsRefPtr mgr = + nsMemoryReporterManager::GetOrCreate(); + if (mgr) { + mgr->IncrementNumChildProcesses(); + } + std::vector extraArgs; if (aIsNuwaProcess) { extraArgs.push_back("-nuwa"); @@ -2037,7 +1995,7 @@ ContentParent::Observe(nsISupports* aSubject, return NS_ERROR_NOT_AVAILABLE; } else if (!strcmp(aTopic, "child-memory-reporter-request")) { - unused << SendPMemoryReportRequestConstructor(); + unused << SendPMemoryReportRequestConstructor((uint32_t)(uintptr_t)aData); } else if (!strcmp(aTopic, "child-gc-request")){ unused << SendGarbageCollect(); @@ -2481,7 +2439,7 @@ ContentParent::RecvPIndexedDBConstructor(PIndexedDBParent* aActor) } PMemoryReportRequestParent* -ContentParent::AllocPMemoryReportRequestParent() +ContentParent::AllocPMemoryReportRequestParent(const uint32_t& generation) { MemoryReportRequestParent* parent = new MemoryReportRequestParent(); return parent; @@ -2494,32 +2452,6 @@ ContentParent::DeallocPMemoryReportRequestParent(PMemoryReportRequestParent* act return true; } -void -ContentParent::SetChildMemoryReports(const InfallibleTArray& childReports) -{ - nsCOMPtr mgr = - do_GetService("@mozilla.org/memory-reporter-manager;1"); - - if (mChildReporter) - mgr->UnregisterReporter(mChildReporter); - - mChildReporter = new ChildReporter(childReports); - mgr->RegisterReporter(mChildReporter); - - nsCOMPtr obs = - do_GetService("@mozilla.org/observer-service;1"); - if (obs) - obs->NotifyObservers(nullptr, "child-memory-reporter-update", nullptr); -} - -void -ContentParent::UnregisterChildMemoryReporter() -{ - nsCOMPtr mgr = - do_GetService("@mozilla.org/memory-reporter-manager;1"); - mgr->UnregisterReporter(mChildReporter); -} - PTestShellParent* ContentParent::AllocPTestShellParent() { diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index c291d3965b9..cb2ca2751c3 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -140,10 +140,6 @@ public: bool IsAlive(); bool IsForApp(); - void SetChildMemoryReports(const InfallibleTArray& - childReports); - void UnregisterChildMemoryReporter(); - GeckoChildProcessHost* Process() { return mSubprocess; } @@ -340,7 +336,7 @@ private: virtual bool DeallocPIndexedDBParent(PIndexedDBParent* aActor); - virtual PMemoryReportRequestParent* AllocPMemoryReportRequestParent(); + virtual PMemoryReportRequestParent* AllocPMemoryReportRequestParent(const uint32_t& generation); virtual bool DeallocPMemoryReportRequestParent(PMemoryReportRequestParent* actor); virtual PTestShellParent* AllocPTestShellParent(); @@ -500,14 +496,6 @@ private: uint64_t mChildID; int32_t mGeolocationWatchID; - // This is a reporter holding the reports from the child's last - // "child-memory-reporter-update" notification. To update this, one can - // broadcast the topic "child-memory-reporter-request" using the - // nsIObserverService. - // - // Note that this assumes there is at most one child process at a time! - nsCOMPtr mChildReporter; - nsString mAppManifestURL; /** diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index 641fe30482c..59c9184ce96 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -231,7 +231,7 @@ child: */ async SetProcessPrivileges(ChildPrivileges privs); - PMemoryReportRequest(); + PMemoryReportRequest(uint32_t generation); /** * Notify the AudioChannelService in the child processes. diff --git a/dom/ipc/PMemoryReportRequest.ipdl b/dom/ipc/PMemoryReportRequest.ipdl index f2f95165449..530f06940cf 100644 --- a/dom/ipc/PMemoryReportRequest.ipdl +++ b/dom/ipc/PMemoryReportRequest.ipdl @@ -21,7 +21,7 @@ protocol PMemoryReportRequest { manager PContent; parent: - __delete__(MemoryReport[] report); + __delete__(uint32_t generation, MemoryReport[] report); }; } diff --git a/dom/locales/en-US/chrome/accessibility/AccessFu.properties b/dom/locales/en-US/chrome/accessibility/AccessFu.properties index 2d0d2229ddf..3d3560ab5e7 100644 --- a/dom/locales/en-US/chrome/accessibility/AccessFu.properties +++ b/dom/locales/en-US/chrome/accessibility/AccessFu.properties @@ -73,6 +73,7 @@ definition = definition textarea = text area # Text input types +textInputType_date = date textInputType_email = e-mail textInputType_search = search textInputType_tel = telephone diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index 1fa8c10cec3..d5583d7a420 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -1950,7 +1950,7 @@ struct WorkerPrivate::TimeoutInfo bool mCanceled; }; -class WorkerPrivate::MemoryReporter MOZ_FINAL : public nsIMemoryReporter +class WorkerPrivate::MemoryReporter MOZ_FINAL : public MemoryMultiReporter { friend class WorkerPrivate; @@ -1960,10 +1960,9 @@ class WorkerPrivate::MemoryReporter MOZ_FINAL : public nsIMemoryReporter bool mAlreadyMappedToAddon; public: - NS_DECL_THREADSAFE_ISUPPORTS - MemoryReporter(WorkerPrivate* aWorkerPrivate) - : mMutex(aWorkerPrivate->mMutex), mWorkerPrivate(aWorkerPrivate), + : MemoryMultiReporter("workers"), + mMutex(aWorkerPrivate->mMutex), mWorkerPrivate(aWorkerPrivate), mAlreadyMappedToAddon(false) { aWorkerPrivate->AssertIsOnWorkerThread(); @@ -1983,13 +1982,6 @@ public: NS_LITERAL_CSTRING(")/"); } - NS_IMETHOD - GetName(nsACString& aName) - { - aName.AssignLiteral("workers"); - return NS_OK; - } - NS_IMETHOD CollectReports(nsIMemoryReporterCallback* aCallback, nsISupports* aClosure) @@ -2072,8 +2064,6 @@ private: } }; -NS_IMPL_ISUPPORTS1(WorkerPrivate::MemoryReporter, nsIMemoryReporter) - template WorkerPrivateParent::WorkerPrivateParent( JSContext* aCx, diff --git a/gfx/src/nsFont.h b/gfx/src/nsFont.h index f579ae5c629..6e885ac30be 100644 --- a/gfx/src/nsFont.h +++ b/gfx/src/nsFont.h @@ -48,7 +48,7 @@ struct NS_GFX nsFont { // Force this font to not be considered a 'generic' font, even if // the name is the same as a CSS generic font family. - uint8_t systemFont; + bool systemFont; // The variant of the font (normal, small-caps) uint8_t variant; diff --git a/gfx/thebes/d3dkmtQueryStatistics.h b/gfx/thebes/d3dkmtQueryStatistics.h index 03c6601517c..9305f1dbddb 100644 --- a/gfx/thebes/d3dkmtQueryStatistics.h +++ b/gfx/thebes/d3dkmtQueryStatistics.h @@ -6,6 +6,9 @@ * Windows 8 RC SDK. The work for this file itself was based on the one in ProcessHacker at * http://processhacker.svn.sourceforge.net/viewvc/processhacker/2.x/trunk/plugins/ExtendedTools/d3dkmt.h?revision=4758&view=markup * For more details see Mozilla Bug 689870. + * [Bug 917496 indicates that some of these structs may not match reality, and + * therefore should not be trusted. See the reference to bug 917496 in + * gfxWindowsPlatform.cpp.] */ typedef struct _D3DKMTQS_COUNTER diff --git a/gfx/thebes/gfxASurface.cpp b/gfx/thebes/gfxASurface.cpp index c8b869b2b29..1b08a4987d1 100644 --- a/gfx/thebes/gfxASurface.cpp +++ b/gfx/thebes/gfxASurface.cpp @@ -631,21 +631,13 @@ PR_STATIC_ASSERT(uint32_t(CAIRO_SURFACE_TYPE_SKIA) == static int64_t gSurfaceMemoryUsed[gfxSurfaceTypeMax] = { 0 }; -class SurfaceMemoryReporter MOZ_FINAL : - public nsIMemoryReporter +class SurfaceMemoryReporter MOZ_FINAL : public MemoryMultiReporter { public: SurfaceMemoryReporter() + : MemoryMultiReporter("gfx-surface") { } - NS_DECL_ISUPPORTS - - NS_IMETHOD GetName(nsACString &name) - { - name.AssignLiteral("gfx-surface"); - return NS_OK; - } - NS_IMETHOD CollectReports(nsIMemoryReporterCallback *aCb, nsISupports *aClosure) { @@ -673,8 +665,6 @@ public: } }; -NS_IMPL_ISUPPORTS1(SurfaceMemoryReporter, nsIMemoryReporter) - void gfxASurface::RecordMemoryUsedForSurfaceType(gfxSurfaceType aType, int32_t aBytes) diff --git a/gfx/thebes/gfxFont.cpp b/gfx/thebes/gfxFont.cpp index 45886688bbe..f9cedc2daee 100644 --- a/gfx/thebes/gfxFont.cpp +++ b/gfx/thebes/gfxFont.cpp @@ -1360,17 +1360,8 @@ gfxFontFamily::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf, * shaped-word caches to free up memory. */ -NS_IMPL_ISUPPORTS1(gfxFontCache::MemoryReporter, nsIMemoryReporter) - NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(FontCacheMallocSizeOf) -NS_IMETHODIMP -gfxFontCache::MemoryReporter::GetName(nsACString &aName) -{ - aName.AssignLiteral("font-cache"); - return NS_OK; -} - NS_IMETHODIMP gfxFontCache::MemoryReporter::CollectReports (nsIMemoryReporterCallback* aCb, diff --git a/gfx/thebes/gfxFont.h b/gfx/thebes/gfxFont.h index b302e950436..fc43d51de72 100644 --- a/gfx/thebes/gfxFont.h +++ b/gfx/thebes/gfxFont.h @@ -950,12 +950,15 @@ public: FontCacheSizes* aSizes) const; protected: - class MemoryReporter MOZ_FINAL - : public nsIMemoryReporter + class MemoryReporter MOZ_FINAL : public mozilla::MemoryMultiReporter { public: - NS_DECL_ISUPPORTS - NS_DECL_NSIMEMORYREPORTER + MemoryReporter() + : MemoryMultiReporter("font-cache") + {} + + NS_IMETHOD CollectReports(nsIMemoryReporterCallback* aCb, + nsISupports* aClosure); }; // Observer for notifications that the font cache cares about diff --git a/gfx/thebes/gfxPlatformFontList.cpp b/gfx/thebes/gfxPlatformFontList.cpp index ed779ce2068..58c16b7c658 100644 --- a/gfx/thebes/gfxPlatformFontList.cpp +++ b/gfx/thebes/gfxPlatformFontList.cpp @@ -71,16 +71,11 @@ gfxFontListPrefObserver::Observe(nsISupports *aSubject, return NS_OK; } -NS_IMPL_ISUPPORTS1(gfxPlatformFontList::MemoryReporter, nsIMemoryReporter) - NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(FontListMallocSizeOf) -NS_IMETHODIMP -gfxPlatformFontList::MemoryReporter::GetName(nsACString &aName) -{ - aName.AssignLiteral("font-list"); - return NS_OK; -} +gfxPlatformFontList::MemoryReporter::MemoryReporter() + : MemoryMultiReporter("font-list") +{} NS_IMETHODIMP gfxPlatformFontList::MemoryReporter::CollectReports diff --git a/gfx/thebes/gfxPlatformFontList.h b/gfx/thebes/gfxPlatformFontList.h index 4f3858c1001..6b95f8b1efc 100644 --- a/gfx/thebes/gfxPlatformFontList.h +++ b/gfx/thebes/gfxPlatformFontList.h @@ -178,12 +178,12 @@ public: void RemoveCmap(const gfxCharacterMap *aCharMap); protected: - class MemoryReporter MOZ_FINAL - : public nsIMemoryReporter + class MemoryReporter MOZ_FINAL : public mozilla::MemoryMultiReporter { public: - NS_DECL_ISUPPORTS - NS_DECL_NSIMEMORYREPORTER + MemoryReporter(); + NS_IMETHOD CollectReports(nsIMemoryReporterCallback *aCb, + nsISupports *aClosure); }; gfxPlatformFontList(bool aNeedFullnamePostscriptNames = true); diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp index a82943cedc5..f8453504d5f 100644 --- a/gfx/thebes/gfxWindowsPlatform.cpp +++ b/gfx/thebes/gfxWindowsPlatform.cpp @@ -207,70 +207,63 @@ typedef HRESULT (WINAPI*D3D11CreateDeviceFunc)( ID3D11DeviceContext *ppImmediateContext ); -class GPUAdapterReporter : public nsIMemoryReporter { - +class GPUAdapterReporter : public MemoryMultiReporter +{ // Callers must Release the DXGIAdapter after use or risk mem-leak static bool GetDXGIAdapter(IDXGIAdapter **DXGIAdapter) { ID3D10Device1 *D2D10Device; IDXGIDevice *DXGIDevice; bool result = false; - + if (D2D10Device = mozilla::gfx::Factory::GetDirect3D10Device()) { if (D2D10Device->QueryInterface(__uuidof(IDXGIDevice), (void **)&DXGIDevice) == S_OK) { result = (DXGIDevice->GetAdapter(DXGIAdapter) == S_OK); DXGIDevice->Release(); } } - + return result; } - -public: - NS_DECL_ISUPPORTS - // nsIMemoryReporter abstract method implementation - NS_IMETHOD - GetName(nsACString &aName) - { - aName.AssignLiteral("gpuadapter"); - return NS_OK; - } - - // nsIMemoryReporter abstract method implementation +public: + GPUAdapterReporter() + : MemoryMultiReporter("gpu-adapter") + {} + NS_IMETHOD CollectReports(nsIMemoryReporterCallback* aCb, nsISupports* aClosure) { int32_t winVers, buildNum; HANDLE ProcessHandle = GetCurrentProcess(); - + int64_t dedicatedBytesUsed = 0; int64_t sharedBytesUsed = 0; int64_t committedBytesUsed = 0; IDXGIAdapter *DXGIAdapter; - + HMODULE gdi32Handle; PFND3DKMTQS queryD3DKMTStatistics; - + winVers = gfxWindowsPlatform::WindowsOSVersion(&buildNum); - + // GPU memory reporting is not available before Windows 7 - if (winVers < gfxWindowsPlatform::kWindows7) + if (winVers < gfxWindowsPlatform::kWindows7) return NS_OK; - + if (gdi32Handle = LoadLibrary(TEXT("gdi32.dll"))) queryD3DKMTStatistics = (PFND3DKMTQS)GetProcAddress(gdi32Handle, "D3DKMTQueryStatistics"); - + if (queryD3DKMTStatistics && GetDXGIAdapter(&DXGIAdapter)) { // Most of this block is understood thanks to wj32's work on Process Hacker - + DXGI_ADAPTER_DESC adapterDesc; D3DKMTQS queryStatistics; - + DXGIAdapter->GetDesc(&adapterDesc); DXGIAdapter->Release(); - + memset(&queryStatistics, 0, sizeof(D3DKMTQS)); queryStatistics.Type = D3DKMTQS_PROCESS; queryStatistics.AdapterLuid = adapterDesc.AdapterLuid; @@ -278,29 +271,29 @@ public: if (NT_SUCCESS(queryD3DKMTStatistics(&queryStatistics))) { committedBytesUsed = queryStatistics.QueryResult.ProcessInfo.SystemMemory.BytesAllocated; } - + memset(&queryStatistics, 0, sizeof(D3DKMTQS)); queryStatistics.Type = D3DKMTQS_ADAPTER; queryStatistics.AdapterLuid = adapterDesc.AdapterLuid; if (NT_SUCCESS(queryD3DKMTStatistics(&queryStatistics))) { ULONG i; ULONG segmentCount = queryStatistics.QueryResult.AdapterInfo.NbSegments; - + for (i = 0; i < segmentCount; i++) { memset(&queryStatistics, 0, sizeof(D3DKMTQS)); queryStatistics.Type = D3DKMTQS_SEGMENT; queryStatistics.AdapterLuid = adapterDesc.AdapterLuid; queryStatistics.QuerySegment.SegmentId = i; - + if (NT_SUCCESS(queryD3DKMTStatistics(&queryStatistics))) { bool aperture; - + // SegmentInformation has a different definition in Win7 than later versions if (winVers < gfxWindowsPlatform::kWindows8) aperture = queryStatistics.QueryResult.SegmentInfoWin7.Aperture; else aperture = queryStatistics.QueryResult.SegmentInfoWin8.Aperture; - + memset(&queryStatistics, 0, sizeof(D3DKMTQS)); queryStatistics.Type = D3DKMTQS_PROCESS_SEGMENT; queryStatistics.AdapterLuid = adapterDesc.AdapterLuid; @@ -320,9 +313,9 @@ public: } } } - + FreeLibrary(gdi32Handle); - + #define REPORT(_path, _amount, _desc) \ do { \ nsresult rv; \ @@ -342,13 +335,12 @@ public: REPORT("gpu-shared", sharedBytesUsed, "In-process memory that is shared with the GPU."); - + #undef REPORT return NS_OK; } }; -NS_IMPL_ISUPPORTS1(GPUAdapterReporter, nsIMemoryReporter) static __inline void BuildKeyNameFromFontName(nsAString &aName) @@ -385,13 +377,16 @@ gfxWindowsPlatform::gfxWindowsPlatform() UpdateRenderMode(); - mGPUAdapterReporter = new GPUAdapterReporter(); - NS_RegisterMemoryReporter(mGPUAdapterReporter); + // This reporter is disabled because it frequently gives bogus values. See + // bug 917496. + //mGPUAdapterReporter = new GPUAdapterReporter(); + //NS_RegisterMemoryReporter(mGPUAdapterReporter); + mGPUAdapterReporter = nullptr; } gfxWindowsPlatform::~gfxWindowsPlatform() { - NS_UnregisterMemoryReporter(mGPUAdapterReporter); + //NS_UnregisterMemoryReporter(mGPUAdapterReporter); mDeviceManager = nullptr; diff --git a/image/src/imgLoader.cpp b/image/src/imgLoader.cpp index 6dade7df6a4..e2d5123725c 100644 --- a/image/src/imgLoader.cpp +++ b/image/src/imgLoader.cpp @@ -50,21 +50,12 @@ using namespace mozilla::image; NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(ImagesMallocSizeOf) -class imgMemoryReporter MOZ_FINAL : - public nsIMemoryReporter +class imgMemoryReporter MOZ_FINAL : public MemoryMultiReporter { public: imgMemoryReporter() - { - } - - NS_DECL_ISUPPORTS - - NS_IMETHOD GetName(nsACString &name) - { - name.Assign("images"); - return NS_OK; - } + : MemoryMultiReporter("images") + {} NS_IMETHOD CollectReports(nsIMemoryReporterCallback *callback, nsISupports *closure) @@ -223,8 +214,6 @@ private: } }; -NS_IMPL_ISUPPORTS1(imgMemoryReporter, nsIMemoryReporter) - NS_IMPL_ISUPPORTS3(nsProgressNotificationProxy, nsIProgressEventSink, nsIChannelEventSink, diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index 8c5831fb98a..714b6ff0295 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -1326,13 +1326,7 @@ Neuter(JSContext *cx, unsigned argc, jsval *vp) return false; } - void *contents; - uint8_t *data; - if (!JS_StealArrayBufferContents(cx, obj, &contents, &data)) - return false; - - js_free(contents); - return true; + return JS_NeuterArrayBuffer(cx, obj); } static const JSFunctionSpecWithHelp TestingFunctions[] = { diff --git a/js/src/configure.in b/js/src/configure.in index f0a963ad587..1815b0764e4 100644 --- a/js/src/configure.in +++ b/js/src/configure.in @@ -4300,16 +4300,9 @@ if test "$JS_HAS_CTYPES" -a -z "$MOZ_NATIVE_FFI"; then ac_configure_args="$ac_configure_args --with-pic" fi if test "$CROSS_COMPILE"; then - case "$target" in - *-android*|*-linuxandroid*) - export AS CC CXX CPP LD AR RANLIB STRIP CPPFLAGS CFLAGS LDFLAGS + export AS CC CXX CPP LD AR RANLIB STRIP CPPFLAGS CFLAGS LDFLAGS - ac_configure_args="$ac_configure_args --build=$build --host=$target HOST_CC=\"$HOST_CC\"" - ;; - *) - ac_configure_args="$ac_configure_args --build=$build --host=$target HOST_CC=\"$HOST_CC\" CC=\"$CC\"" - ;; - esac + ac_configure_args="$ac_configure_args --build=$build --host=$target HOST_CC=\"$HOST_CC\"" fi if test "$_MSC_VER"; then # Use a wrapper script for cl and ml that looks more like gcc. diff --git a/js/src/devtools/rootAnalysis/annotations.js b/js/src/devtools/rootAnalysis/annotations.js index 148a5918227..45a7e047360 100644 --- a/js/src/devtools/rootAnalysis/annotations.js +++ b/js/src/devtools/rootAnalysis/annotations.js @@ -79,6 +79,7 @@ var ignoreCallees = { "mozilla::CycleCollectedJSRuntime.DescribeCustomObjects" : true, // During tracing, cannot GC. "mozilla::CycleCollectedJSRuntime.NoteCustomGCThingXPCOMChildren" : true, // During tracing, cannot GC. "nsIThreadManager.GetIsMainThread" : true, + "PLDHashTableOps.hashKey" : true, }; function fieldCallCannotGC(csu, fullfield) diff --git a/js/src/jit/BaselineCompiler.cpp b/js/src/jit/BaselineCompiler.cpp index 516525b4d55..396396147ed 100644 --- a/js/src/jit/BaselineCompiler.cpp +++ b/js/src/jit/BaselineCompiler.cpp @@ -2908,38 +2908,22 @@ BaselineCompiler::emit_JSOP_RUNONCE() return callVM(RunOnceScriptPrologueInfo); } -static bool -DoCreateRestParameter(JSContext *cx, BaselineFrame *frame, MutableHandleValue res) -{ - unsigned numFormals = frame->numFormalArgs() - 1; - unsigned numActuals = frame->numActualArgs(); - unsigned numRest = numActuals > numFormals ? numActuals - numFormals : 0; - Value *rest = frame->argv() + numFormals; - - JSObject *obj = NewDenseCopiedArray(cx, numRest, rest, nullptr); - if (!obj) - return false; - types::FixRestArgumentsType(cx, obj); - res.setObject(*obj); - return true; -} - -typedef bool(*DoCreateRestParameterFn)(JSContext *cx, BaselineFrame *, MutableHandleValue); -static const VMFunction DoCreateRestParameterInfo = - FunctionInfo(DoCreateRestParameter); - bool BaselineCompiler::emit_JSOP_REST() { frame.syncStack(0); - prepareVMCall(); - masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg()); - pushArg(R0.scratchReg()); + JSObject *templateObject = NewDenseUnallocatedArray(cx, 0, nullptr, TenuredObject); + if (!templateObject) + return false; + types::FixRestArgumentsType(cx, templateObject); - if (!callVM(DoCreateRestParameterInfo)) + // Call IC. + ICRest_Fallback::Compiler compiler(cx, templateObject); + if (!emitOpIC(compiler.getStub(&stubSpace_))) return false; + // Mark R0 as pushed stack value. frame.push(R0); return true; } diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp index 764acb14781..16a8769c262 100644 --- a/js/src/jit/BaselineIC.cpp +++ b/js/src/jit/BaselineIC.cpp @@ -9463,5 +9463,41 @@ ICGetProp_DOMProxyShadowed::ICGetProp_DOMProxyShadowed(IonCode *stubCode, pcOffset_(pcOffset) { } +// +// Rest_Fallback +// + +static bool DoRestFallback(JSContext *cx, ICRest_Fallback *stub, + BaselineFrame *frame, MutableHandleValue res) +{ + unsigned numFormals = frame->numFormalArgs() - 1; + unsigned numActuals = frame->numActualArgs(); + unsigned numRest = numActuals > numFormals ? numActuals - numFormals : 0; + Value *rest = frame->argv() + numFormals; + + JSObject *obj = NewDenseCopiedArray(cx, numRest, rest, nullptr); + if (!obj) + return false; + types::FixRestArgumentsType(cx, obj); + res.setObject(*obj); + return true; +} + +typedef bool (*DoRestFallbackFn)(JSContext *, ICRest_Fallback *, BaselineFrame *, + MutableHandleValue); +static const VMFunction DoRestFallbackInfo = + FunctionInfo(DoRestFallback); + +bool +ICRest_Fallback::Compiler::generateStubCode(MacroAssembler &masm) +{ + EmitRestoreTailCallReg(masm); + + masm.pushBaselineFramePtr(BaselineFrameReg, R0.scratchReg()); + masm.push(BaselineStubReg); + + return tailCallVM(DoRestFallbackInfo, masm); +} + } // namespace jit } // namespace js diff --git a/js/src/jit/BaselineIC.h b/js/src/jit/BaselineIC.h index 54fa61d19e9..de5750bebf3 100644 --- a/js/src/jit/BaselineIC.h +++ b/js/src/jit/BaselineIC.h @@ -5853,6 +5853,47 @@ class ICTypeOf_Typed : public ICFallbackStub }; }; +class ICRest_Fallback : public ICFallbackStub +{ + friend class ICStubSpace; + + HeapPtrObject templateObject_; + + ICRest_Fallback(IonCode *stubCode, JSObject *templateObject) + : ICFallbackStub(ICStub::Rest_Fallback, stubCode), templateObject_(templateObject) + { } + + public: + static const uint32_t MAX_OPTIMIZED_STUBS = 8; + + static inline ICRest_Fallback *New(ICStubSpace *space, IonCode *code, + JSObject *templateObject) { + if (!code) + return nullptr; + return space->allocate(code, templateObject); + } + + JSObject *templateObject() { + return templateObject_; + } + + class Compiler : public ICStubCompiler { + protected: + RootedObject templateObject; + bool generateStubCode(MacroAssembler &masm); + + public: + Compiler(JSContext *cx, JSObject *templateObject) + : ICStubCompiler(cx, ICStub::Rest_Fallback), + templateObject(cx, templateObject) + { } + + ICStub *getStub(ICStubSpace *space) { + return ICRest_Fallback::New(space, getStubCode(), templateObject); + } + }; +}; + // Stub for JSOP_RETSUB ("returning" from a |finally| block). class ICRetSub_Fallback : public ICFallbackStub { diff --git a/js/src/jit/BaselineInspector.cpp b/js/src/jit/BaselineInspector.cpp index d78d5c7bc11..ea996156d33 100644 --- a/js/src/jit/BaselineInspector.cpp +++ b/js/src/jit/BaselineInspector.cpp @@ -397,6 +397,8 @@ BaselineInspector::getTemplateObject(jsbytecode *pc) return stub->toNewArray_Fallback()->templateObject(); case ICStub::NewObject_Fallback: return stub->toNewObject_Fallback()->templateObject(); + case ICStub::Rest_Fallback: + return stub->toRest_Fallback()->templateObject(); case ICStub::Call_Scripted: if (JSObject *obj = stub->toCall_Scripted()->templateObject()) return obj; diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index d0672ac4e53..3190fa8dea5 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -4963,19 +4963,17 @@ IonBuilder::jsop_call(uint32_t argc, bool constructing) } JS_ASSERT_IF(gotLambda, originals.length() <= 1); - // If any call targets need to be cloned, clone them. Keep track of the - // originals as we need to case on them for poly inline. + // If any call targets need to be cloned, look for existing clones to use. + // Keep track of the originals as we need to case on them for poly inline. bool hasClones = false; ObjectVector targets; - RootedFunction fun(cx); - RootedScript scriptRoot(cx, script()); for (uint32_t i = 0; i < originals.length(); i++) { - fun = &originals[i]->as(); + JSFunction *fun = &originals[i]->as(); if (fun->hasScript() && fun->nonLazyScript()->shouldCloneAtCallsite) { - fun = CloneFunctionAtCallsite(cx, fun, scriptRoot, pc); - if (!fun) - return false; - hasClones = true; + if (JSFunction *clone = ExistingCloneFunctionAtCallsite(compartment, fun, script(), pc)) { + fun = clone; + hasClones = true; + } } if (!targets.append(fun)) return false; @@ -7473,23 +7471,14 @@ IonBuilder::jsop_arguments_length() return pushConstant(Int32Value(inlineCallInfo_->argv().length())); } -static JSObject * -CreateRestArgumentsTemplateObject(JSContext *cx, unsigned length) -{ - JSObject *templateObject = NewDenseUnallocatedArray(cx, length, nullptr, TenuredObject); - if (templateObject) - types::FixRestArgumentsType(cx, templateObject); - return templateObject; -} - bool IonBuilder::jsop_rest() { - // We don't know anything about the callee. + JSObject *templateObject = inspector->getTemplateObject(pc); + JS_ASSERT(templateObject->is()); + if (inliningDepth_ == 0) { - JSObject *templateObject = CreateRestArgumentsTemplateObject(cx, 0); - if (!templateObject) - return false; + // We don't know anything about the callee. MArgumentsLength *numActuals = MArgumentsLength::New(); current->add(numActuals); @@ -7505,9 +7494,6 @@ IonBuilder::jsop_rest() unsigned numActuals = inlineCallInfo_->argv().length(); unsigned numFormals = info().nargs() - 1; unsigned numRest = numActuals > numFormals ? numActuals - numFormals : 0; - JSObject *templateObject = CreateRestArgumentsTemplateObject(cx, numRest); - if (!templateObject) - return false; MNewArray *array = new MNewArray(numRest, templateObject, MNewArray::NewArray_Allocating); current->add(array); diff --git a/js/src/jit/IonBuilder.h b/js/src/jit/IonBuilder.h index ed105f58dfb..51c00142424 100644 --- a/js/src/jit/IonBuilder.h +++ b/js/src/jit/IonBuilder.h @@ -583,7 +583,7 @@ class IonBuilder : public MIRGenerator InliningStatus inlineNewParallelArray(CallInfo &callInfo); InliningStatus inlineParallelArray(CallInfo &callInfo); InliningStatus inlineParallelArrayTail(CallInfo &callInfo, - HandleFunction target, + JSFunction *target, MDefinition *ctor, types::TemporaryTypeSet *ctorTypes, uint32_t discards); diff --git a/js/src/jit/MCallOptimize.cpp b/js/src/jit/MCallOptimize.cpp index 52749763047..38e1e671a0b 100644 --- a/js/src/jit/MCallOptimize.cpp +++ b/js/src/jit/MCallOptimize.cpp @@ -1195,14 +1195,12 @@ IonBuilder::inlineNewParallelArray(CallInfo &callInfo) types::TemporaryTypeSet *ctorTypes = callInfo.getArg(0)->resultTypeSet(); JSObject *targetObj = ctorTypes ? ctorTypes->getSingleton() : nullptr; - RootedFunction target(cx); + JSFunction *target = nullptr; if (targetObj && targetObj->is()) target = &targetObj->as(); if (target && target->isInterpreted() && target->nonLazyScript()->shouldCloneAtCallsite) { - RootedScript scriptRoot(cx, script()); - target = CloneFunctionAtCallsite(cx, target, scriptRoot, pc); - if (!target) - return InliningStatus_Error; + if (JSFunction *clone = ExistingCloneFunctionAtCallsite(compartment, target, script(), pc)) + target = clone; } MDefinition *ctor = makeCallsiteClone( target, @@ -1220,15 +1218,13 @@ IonBuilder::inlineParallelArray(CallInfo &callInfo) return InliningStatus_NotInlined; uint32_t argc = callInfo.argc(); - RootedFunction target(cx, ParallelArrayObject::getConstructor(cx, argc)); + JSFunction *target = ParallelArrayObject::getConstructor(cx, argc); if (!target) return InliningStatus_Error; JS_ASSERT(target->nonLazyScript()->shouldCloneAtCallsite); - RootedScript script(cx, script_); - target = CloneFunctionAtCallsite(cx, target, script, pc); - if (!target) - return InliningStatus_Error; + if (JSFunction *clone = ExistingCloneFunctionAtCallsite(compartment, target, script(), pc)) + target = clone; MConstant *ctor = MConstant::New(ObjectValue(*target)); current->add(ctor); @@ -1238,7 +1234,7 @@ IonBuilder::inlineParallelArray(CallInfo &callInfo) IonBuilder::InliningStatus IonBuilder::inlineParallelArrayTail(CallInfo &callInfo, - HandleFunction target, + JSFunction *target, MDefinition *ctor, types::TemporaryTypeSet *ctorTypes, uint32_t discards) diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index 013f1fae599..b07d2ba5206 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -110,9 +110,10 @@ JSCompartment::sweepCallsiteClones() } JSFunction * -js::CloneFunctionAtCallsite(JSContext *cx, HandleFunction fun, HandleScript script, jsbytecode *pc) +js::ExistingCloneFunctionAtCallsite(JSCompartment *comp, JSFunction *fun, + JSScript *script, jsbytecode *pc) { - JS_ASSERT(cx->typeInferenceEnabled()); + JS_ASSERT(comp->zone()->types.inferenceEnabled); JS_ASSERT(fun->nonLazyScript()->shouldCloneAtCallsite); JS_ASSERT(!fun->nonLazyScript()->enclosingStaticScope()); JS_ASSERT(types::UseNewTypeForClone(fun)); @@ -126,23 +127,25 @@ js::CloneFunctionAtCallsite(JSContext *cx, HandleFunction fun, HandleScript scri typedef CallsiteCloneKey Key; typedef CallsiteCloneTable Table; - Table &table = cx->compartment()->callsiteClones; - if (!table.initialized() && !table.init()) + Table &table = comp->callsiteClones; + if (!table.initialized()) return nullptr; - uint32_t offset = pc - script->code; - void* originalScript = script; - void* originalFun = fun; - SkipRoot skipScript(cx, &originalScript); - SkipRoot skipFun(cx, &originalFun); - - Table::AddPtr p = table.lookupForAdd(Key(fun, script, offset)); - SkipRoot skipHash(cx, &p); /* Prevent the hash from being poisoned. */ + Table::Ptr p = table.lookup(Key(fun, script, pc - script->code)); if (p) return p->value; + return nullptr; +} + +JSFunction * +js::CloneFunctionAtCallsite(JSContext *cx, HandleFunction fun, HandleScript script, jsbytecode *pc) +{ + if (JSFunction *clone = ExistingCloneFunctionAtCallsite(cx->compartment(), fun, script, pc)) + return clone; + RootedObject parent(cx, fun->environment()); - RootedFunction clone(cx, CloneFunctionObject(cx, fun, parent)); + JSFunction *clone = CloneFunctionObject(cx, fun, parent); if (!clone) return nullptr; @@ -154,15 +157,14 @@ js::CloneFunctionAtCallsite(JSContext *cx, HandleFunction fun, HandleScript scri clone->nonLazyScript()->isCallsiteClone = true; clone->nonLazyScript()->setOriginalFunctionObject(fun); - Key key(fun, script, offset); + typedef CallsiteCloneKey Key; + typedef CallsiteCloneTable Table; - /* Recalculate the hash if script or fun have been moved. */ - if (script != originalScript || fun != originalFun) { - p = table.lookupForAdd(key); - JS_ASSERT(!p); - } + Table &table = cx->compartment()->callsiteClones; + if (!table.initialized() && !table.init()) + return nullptr; - if (!table.relookupOrAdd(p, key, clone.get())) + if (!table.putNew(Key(fun, script, pc - script->code), clone)) return nullptr; return clone; diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index cd3879104b9..90470910715 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -64,6 +64,10 @@ typedef HashMap CallsiteCloneTable; +JSFunction * +ExistingCloneFunctionAtCallsite(JSCompartment *comp, JSFunction *fun, + JSScript *script, jsbytecode *pc); + JSFunction *CloneFunctionAtCallsite(JSContext *cx, HandleFunction fun, HandleScript script, jsbytecode *pc); diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h index afcd92f049a..92a84cf57df 100644 --- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -1248,8 +1248,8 @@ JS_GetArrayBufferViewBuffer(JSObject *obj); /* * Set an ArrayBuffer's length to 0 and neuter all of its views. */ -extern JS_FRIEND_API(void) -JS_NeuterArrayBuffer(JSObject *obj, JSContext *cx); +extern JS_FRIEND_API(bool) +JS_NeuterArrayBuffer(JSContext *cx, JS::HandleObject obj); /* * Check whether obj supports JS_GetDataView* APIs. diff --git a/js/src/vm/TypedArrayObject.cpp b/js/src/vm/TypedArrayObject.cpp index b501fb0d673..439a7a29c6e 100644 --- a/js/src/vm/TypedArrayObject.cpp +++ b/js/src/vm/TypedArrayObject.cpp @@ -4031,12 +4031,12 @@ JS_GetArrayBufferData(JSObject *obj) } JS_FRIEND_API(bool) -JS_NeuterArrayBuffer(JSContext *cx, JSObject *obj) +JS_NeuterArrayBuffer(JSContext *cx, HandleObject obj) { - ArrayBufferObject &buffer = obj->as(); - if (!buffer.neuterViews(cx)) + Rooted buffer(cx, &obj->as()); + if (!buffer->neuterViews(cx)) return false; - buffer.neuter(cx); + buffer->neuter(cx); return true; } diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp index 3d5e48f05f5..acb6f297610 100644 --- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -2398,15 +2398,12 @@ ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats &rtStats, } // namespace xpc -class JSMainRuntimeCompartmentsReporter MOZ_FINAL : public nsIMemoryReporter +class JSMainRuntimeCompartmentsReporter MOZ_FINAL : public MemoryMultiReporter { public: - NS_DECL_THREADSAFE_ISUPPORTS - - NS_IMETHOD GetName(nsACString &name) { - name.AssignLiteral("js-main-runtime-compartments"); - return NS_OK; - } + JSMainRuntimeCompartmentsReporter() + : MemoryMultiReporter("js-main-runtime-compartments") + {} typedef js::Vector Paths; @@ -2445,8 +2442,6 @@ class JSMainRuntimeCompartmentsReporter MOZ_FINAL : public nsIMemoryReporter } }; -NS_IMPL_ISUPPORTS1(JSMainRuntimeCompartmentsReporter, nsIMemoryReporter) - NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(OrphanMallocSizeOf) namespace xpc { diff --git a/layout/reftests/w3c-css/submitted/reftest.list b/layout/reftests/w3c-css/submitted/reftest.list index b9832858621..4a21929c957 100644 --- a/layout/reftests/w3c-css/submitted/reftest.list +++ b/layout/reftests/w3c-css/submitted/reftest.list @@ -50,7 +50,7 @@ include multicol3/reftest.list # include transitions/reftest.list # User Interface Level 3 -# include ui3/reftest.list +include ui3/reftest.list # Values and Units Level 3 include values3/reftest.list diff --git a/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-001-ref.xht b/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-001-ref.xht new file mode 100644 index 00000000000..e886a0f05e3 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-001-ref.xht @@ -0,0 +1,40 @@ + + + + CSS Reference: Box Sizing - Border-Box with specified width + + + + + The two divs should be side-by-side, not one on top of another. No red should be visible. +
+
+
LEFT HALF
+
RIGHT HALF
+
+ + diff --git a/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-001.xht b/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-001.xht new file mode 100644 index 00000000000..f41214de953 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-001.xht @@ -0,0 +1,43 @@ + + + + CSS Test: Box Sizing - Border-Box with specified width + + + + + + + The two divs should be side-by-side, not one on top of another. No red should be visible. +
+
+
LEFT HALF
+
RIGHT HALF
+
+ + diff --git a/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-002-ref.xht b/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-002-ref.xht new file mode 100644 index 00000000000..7c6bc218a0b --- /dev/null +++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-002-ref.xht @@ -0,0 +1,41 @@ + + + + CSS Reference: Box Sizing - Border-Box with specified width + + + + + The two divs should be side-by-side, not one on top of another. No red should be visible. +
+
+
LEFT HALF
+
RIGHT HALF
+
+ + diff --git a/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-002.xht b/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-002.xht new file mode 100644 index 00000000000..8385cce059a --- /dev/null +++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-002.xht @@ -0,0 +1,44 @@ + + + + CSS Test: Box Sizing - Border-Box with specified width + + + + + + + The two divs should be side-by-side, not one on top of another. No red should be visible. +
+
+
LEFT HALF
+
RIGHT HALF
+
+ + diff --git a/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-003-ref.xht b/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-003-ref.xht new file mode 100644 index 00000000000..c468c5b5b99 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-003-ref.xht @@ -0,0 +1,43 @@ + + + + CSS Reference: Box Sizing - Border-Box with specified width/height + + + + + The two divs should be side-by-side, not one on top of another. No red should be visible. +
+
+
LEFT HALF
+
RIGHT HALF
+
+ + diff --git a/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-003.xht b/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-003.xht new file mode 100644 index 00000000000..57f78a8f10c --- /dev/null +++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-003.xht @@ -0,0 +1,46 @@ + + + + CSS Test: Box Sizing - Border-Box with specified width/height + + + + + + + The two divs should be side-by-side, not one on top of another. No red should be visible. +
+
+
LEFT HALF
+
RIGHT HALF
+
+ + diff --git a/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-004-ref.xht b/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-004-ref.xht new file mode 100644 index 00000000000..a635acd13e4 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-004-ref.xht @@ -0,0 +1,46 @@ + + + + CSS Reference: Box Sizing - Border-Box with min/max width/height + + + + + The two divs should be side-by-side, not one on top of another. No red should be visible. +
+
+
LEFT HALF
+
RIGHT HALF
+
+ + diff --git a/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-004.xht b/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-004.xht new file mode 100644 index 00000000000..9ffe7889a72 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-border-box-004.xht @@ -0,0 +1,49 @@ + + + + CSS Test: Box Sizing - Border-Box with min/max width/height + + + + + + + The two divs should be side-by-side, not one on top of another. No red should be visible. +
+
+
LEFT HALF
+
RIGHT HALF
+
+ + diff --git a/layout/reftests/w3c-css/submitted/ui3/box-sizing-content-box-001-ref.xht b/layout/reftests/w3c-css/submitted/ui3/box-sizing-content-box-001-ref.xht new file mode 100644 index 00000000000..ca3ff0f7ec0 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-content-box-001-ref.xht @@ -0,0 +1,41 @@ + + + + CSS Reference: Box Sizing - Content-Box with specified width/height + + + + + The two divs should be side-by-side, not one on top of another. No red should be visible. +
+
+
LEFT HALF
+
RIGHT HALF
+
+ + diff --git a/layout/reftests/w3c-css/submitted/ui3/box-sizing-content-box-001.xht b/layout/reftests/w3c-css/submitted/ui3/box-sizing-content-box-001.xht new file mode 100644 index 00000000000..b0ca31dbfe7 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-content-box-001.xht @@ -0,0 +1,44 @@ + + + + CSS Test: Box Sizing - Content-Box with specified width/height + + + + + + + The two divs should be side-by-side, not one on top of another. No red should be visible. +
+
+
LEFT HALF
+
RIGHT HALF
+
+ + diff --git a/layout/reftests/w3c-css/submitted/ui3/box-sizing-content-box-002-ref.xht b/layout/reftests/w3c-css/submitted/ui3/box-sizing-content-box-002-ref.xht new file mode 100644 index 00000000000..b280e57693c --- /dev/null +++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-content-box-002-ref.xht @@ -0,0 +1,42 @@ + + + + CSS Reference: Box Sizing - Content-Box with specified width/height + + + + + The two divs should be side-by-side, not one on top of another. No red should be visible. +
+
+
LEFT HALF
+
RIGHT HALF
+
+ + diff --git a/layout/reftests/w3c-css/submitted/ui3/box-sizing-content-box-002.xht b/layout/reftests/w3c-css/submitted/ui3/box-sizing-content-box-002.xht new file mode 100644 index 00000000000..120318fd382 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-content-box-002.xht @@ -0,0 +1,45 @@ + + + + CSS Test: Box Sizing - Content-Box with specified width/height + + + + + + + The two divs should be side-by-side, not one on top of another. No red should be visible. +
+
+
LEFT HALF
+
RIGHT HALF
+
+ + diff --git a/layout/reftests/w3c-css/submitted/ui3/box-sizing-content-box-003-ref.xht b/layout/reftests/w3c-css/submitted/ui3/box-sizing-content-box-003-ref.xht new file mode 100644 index 00000000000..042b5628aa8 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-content-box-003-ref.xht @@ -0,0 +1,43 @@ + + + + CSS Reference: Box Sizing - Content-Box with min/max width/height + + + + + The two divs should be side-by-side, not one on top of another. No red should be visible. +
+
+
LEFT HALF
+
RIGHT HALF
+
+ + diff --git a/layout/reftests/w3c-css/submitted/ui3/box-sizing-content-box-003.xht b/layout/reftests/w3c-css/submitted/ui3/box-sizing-content-box-003.xht new file mode 100644 index 00000000000..1146b54cfb0 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-content-box-003.xht @@ -0,0 +1,45 @@ + + + + CSS Test: Box Sizing - Content-Box with min/max width/height + + + + + + + The two divs should be side-by-side, not one on top of another. No red should be visible. +
+
+
LEFT HALF
+
RIGHT HALF
+
+ + diff --git a/layout/reftests/w3c-css/submitted/ui3/box-sizing-padding-box-001-ref.xht b/layout/reftests/w3c-css/submitted/ui3/box-sizing-padding-box-001-ref.xht new file mode 100644 index 00000000000..d9a1f41e4cc --- /dev/null +++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-padding-box-001-ref.xht @@ -0,0 +1,40 @@ + + + + CSS Reference: Box Sizing - Padding-Box with specified width/height + + + + + The two divs should be side-by-side, not one on top of another. No red should be visible. +
+
+
LEFT HALF
+
RIGHT HALF
+
+ + diff --git a/layout/reftests/w3c-css/submitted/ui3/box-sizing-padding-box-001.xht b/layout/reftests/w3c-css/submitted/ui3/box-sizing-padding-box-001.xht new file mode 100644 index 00000000000..76da3340f8f --- /dev/null +++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-padding-box-001.xht @@ -0,0 +1,43 @@ + + + + CSS Test: Box Sizing - Padding-Box with specified width/height + + + + + + + The two divs should be side-by-side, not one on top of another. No red should be visible. +
+
+
LEFT HALF
+
RIGHT HALF
+
+ + diff --git a/layout/reftests/w3c-css/submitted/ui3/box-sizing-padding-box-002-ref.xht b/layout/reftests/w3c-css/submitted/ui3/box-sizing-padding-box-002-ref.xht new file mode 100644 index 00000000000..06260223d31 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-padding-box-002-ref.xht @@ -0,0 +1,42 @@ + + + + CSS Reference: Box Sizing - Padding-Box with specified width/height + + + + + The two divs should be side-by-side, not one on top of another. No red should be visible. +
+
+
LEFT HALF
+
RIGHT HALF
+
+ + diff --git a/layout/reftests/w3c-css/submitted/ui3/box-sizing-padding-box-002.xht b/layout/reftests/w3c-css/submitted/ui3/box-sizing-padding-box-002.xht new file mode 100644 index 00000000000..5f5465e66c9 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-padding-box-002.xht @@ -0,0 +1,45 @@ + + + + CSS Test: Box Sizing - Padding-Box with specified width/height + + + + + + + The two divs should be side-by-side, not one on top of another. No red should be visible. +
+
+
LEFT HALF
+
RIGHT HALF
+
+ + diff --git a/layout/reftests/w3c-css/submitted/ui3/box-sizing-padding-box-003-ref.xht b/layout/reftests/w3c-css/submitted/ui3/box-sizing-padding-box-003-ref.xht new file mode 100644 index 00000000000..d3ba96f37e4 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-padding-box-003-ref.xht @@ -0,0 +1,42 @@ + + + + CSS Reference: Box Sizing - Padding-Box with min/max width/height + + + + + The two divs should be side-by-side, not one on top of another. No red should be visible. +
+
+
LEFT HALF
+
RIGHT HALF
+
+ + diff --git a/layout/reftests/w3c-css/submitted/ui3/box-sizing-padding-box-003.xht b/layout/reftests/w3c-css/submitted/ui3/box-sizing-padding-box-003.xht new file mode 100644 index 00000000000..fee74d81f8d --- /dev/null +++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-padding-box-003.xht @@ -0,0 +1,49 @@ + + + + CSS Test: Box Sizing - Padding-Box with min/max width/height + + + + + + + The two divs should be side-by-side, not one on top of another. No red should be visible. +
+
+
LEFT HALF
+
RIGHT HALF
+
+ + diff --git a/layout/reftests/w3c-css/submitted/ui3/box-sizing-replaced-001-ref.xht b/layout/reftests/w3c-css/submitted/ui3/box-sizing-replaced-001-ref.xht new file mode 100644 index 00000000000..815813c51e7 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-replaced-001-ref.xht @@ -0,0 +1,52 @@ + + + + CSS Reference: Min/Max Height and Width Constraints on Replaced Elements with Box-Sizing + + + + + + + +
All rectangles should be the same size.
+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+ + diff --git a/layout/reftests/w3c-css/submitted/ui3/box-sizing-replaced-001.xht b/layout/reftests/w3c-css/submitted/ui3/box-sizing-replaced-001.xht new file mode 100644 index 00000000000..28a5bad36ef --- /dev/null +++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-replaced-001.xht @@ -0,0 +1,156 @@ + + + + CSS Test: Min/Max Height and Width Constraints on Replaced Elements with Box-Sizing + + + + + + + + + +
All rectangles should be the same size.
+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+ + diff --git a/layout/reftests/w3c-css/submitted/ui3/box-sizing-replaced-002-ref.xht b/layout/reftests/w3c-css/submitted/ui3/box-sizing-replaced-002-ref.xht new file mode 100644 index 00000000000..64204a68a76 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-replaced-002-ref.xht @@ -0,0 +1,53 @@ + + + + CSS Reference: Min/Max Height and Width Constraints on Replaced Elements with Box-Sizing + + + + + + + +
All rectangles should be the same size.
+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+ + diff --git a/layout/reftests/w3c-css/submitted/ui3/box-sizing-replaced-002.xht b/layout/reftests/w3c-css/submitted/ui3/box-sizing-replaced-002.xht new file mode 100644 index 00000000000..d217dbb689d --- /dev/null +++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-replaced-002.xht @@ -0,0 +1,157 @@ + + + + CSS Test: Min/Max Height and Width Constraints on Replaced Elements with Box-Sizing + + + + + + + + + +
All rectangles should be the same size.
+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+ + diff --git a/layout/reftests/w3c-css/submitted/ui3/box-sizing-replaced-003-ref.xht b/layout/reftests/w3c-css/submitted/ui3/box-sizing-replaced-003-ref.xht new file mode 100644 index 00000000000..85524daf4a9 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-replaced-003-ref.xht @@ -0,0 +1,48 @@ + + + + CSS Reference: Min/Max Height and Width Constraints on Replaced Elements with Box-Sizing + + + + + + + +
All rectangles should be the same size.
+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+ + diff --git a/layout/reftests/w3c-css/submitted/ui3/box-sizing-replaced-003.xht b/layout/reftests/w3c-css/submitted/ui3/box-sizing-replaced-003.xht new file mode 100644 index 00000000000..085c2719cfa --- /dev/null +++ b/layout/reftests/w3c-css/submitted/ui3/box-sizing-replaced-003.xht @@ -0,0 +1,155 @@ + + + + CSS Test: Min/Max Height and Width Constraints on Replaced Elements with Box-Sizing + + + + + + + + + +
All rectangles should be the same size.
+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+

FAIL

+ + diff --git a/layout/reftests/w3c-css/submitted/ui3/reftest.list b/layout/reftests/w3c-css/submitted/ui3/reftest.list new file mode 100644 index 00000000000..f5d9ef53267 --- /dev/null +++ b/layout/reftests/w3c-css/submitted/ui3/reftest.list @@ -0,0 +1,13 @@ +== box-sizing-border-box-001.xht box-sizing-border-box-001-ref.xht +== box-sizing-border-box-002.xht box-sizing-border-box-002-ref.xht +== box-sizing-border-box-003.xht box-sizing-border-box-003-ref.xht +== box-sizing-border-box-004.xht box-sizing-border-box-004-ref.xht +== box-sizing-content-box-001.xht box-sizing-content-box-001-ref.xht +== box-sizing-content-box-002.xht box-sizing-content-box-002-ref.xht +== box-sizing-content-box-003.xht box-sizing-content-box-003-ref.xht +== box-sizing-padding-box-001.xht box-sizing-padding-box-001-ref.xht +== box-sizing-padding-box-002.xht box-sizing-padding-box-002-ref.xht +== box-sizing-padding-box-003.xht box-sizing-padding-box-003-ref.xht +== box-sizing-replaced-001.xht box-sizing-replaced-001-ref.xht +== box-sizing-replaced-002.xht box-sizing-replaced-002-ref.xht +== box-sizing-replaced-003.xht box-sizing-replaced-003-ref.xht diff --git a/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-1.png b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-1.png new file mode 100644 index 00000000000..d6946724d9e Binary files /dev/null and b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-1.png differ diff --git a/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-10.png b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-10.png new file mode 100644 index 00000000000..bfdca3e6f35 Binary files /dev/null and b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-10.png differ diff --git a/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-11.png b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-11.png new file mode 100644 index 00000000000..38ee90dda0f Binary files /dev/null and b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-11.png differ diff --git a/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-12.png b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-12.png new file mode 100644 index 00000000000..87433d4d7b9 Binary files /dev/null and b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-12.png differ diff --git a/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-13.png b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-13.png new file mode 100644 index 00000000000..c07d66e7881 Binary files /dev/null and b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-13.png differ diff --git a/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-14.png b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-14.png new file mode 100644 index 00000000000..e89dbe97586 Binary files /dev/null and b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-14.png differ diff --git a/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-15.png b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-15.png new file mode 100644 index 00000000000..717ea111b6f Binary files /dev/null and b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-15.png differ diff --git a/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-16.png b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-16.png new file mode 100644 index 00000000000..0a49bbf1c33 Binary files /dev/null and b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-16.png differ diff --git a/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-17.png b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-17.png new file mode 100644 index 00000000000..a2ee273d798 Binary files /dev/null and b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-17.png differ diff --git a/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-18.png b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-18.png new file mode 100644 index 00000000000..d18f4534179 Binary files /dev/null and b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-18.png differ diff --git a/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-19.png b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-19.png new file mode 100644 index 00000000000..8900f36c41c Binary files /dev/null and b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-19.png differ diff --git a/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-2.png b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-2.png new file mode 100644 index 00000000000..58338097fe2 Binary files /dev/null and b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-2.png differ diff --git a/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-3.png b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-3.png new file mode 100644 index 00000000000..e5e7d6e8a8c Binary files /dev/null and b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-3.png differ diff --git a/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-4.png b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-4.png new file mode 100644 index 00000000000..c099ae4271a Binary files /dev/null and b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-4.png differ diff --git a/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-5.png b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-5.png new file mode 100644 index 00000000000..9d9d8105ff2 Binary files /dev/null and b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-5.png differ diff --git a/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-6.png b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-6.png new file mode 100644 index 00000000000..781f894a5ec Binary files /dev/null and b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-6.png differ diff --git a/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-7.png b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-7.png new file mode 100644 index 00000000000..3f91a11f8e2 Binary files /dev/null and b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-7.png differ diff --git a/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-8.png b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-8.png new file mode 100644 index 00000000000..69951ec2571 Binary files /dev/null and b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-8.png differ diff --git a/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-9.png b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-9.png new file mode 100644 index 00000000000..3ac586daa5a Binary files /dev/null and b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max-9.png differ diff --git a/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max.png b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max.png new file mode 100644 index 00000000000..3ef233005ae Binary files /dev/null and b/layout/reftests/w3c-css/submitted/ui3/support/replaced-min-max.png differ diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index 7602b03c3cc..95e58f5c4f9 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -230,7 +230,8 @@ nsChangeHint nsStyleFont::CalcFontDifference(const nsFont& aFont1, const nsFont& (aFont1.variantNumeric == aFont2.variantNumeric) && (aFont1.variantPosition == aFont2.variantPosition) && (aFont1.fontFeatureSettings == aFont2.fontFeatureSettings) && - (aFont1.languageOverride == aFont2.languageOverride)) { + (aFont1.languageOverride == aFont2.languageOverride) && + (aFont1.systemFont == aFont2.systemFont)) { if ((aFont1.decorations == aFont2.decorations)) { return NS_STYLE_HINT_NONE; } diff --git a/modules/libpref/src/Preferences.cpp b/modules/libpref/src/Preferences.cpp index bd5005d36ab..0160eb9c511 100644 --- a/modules/libpref/src/Preferences.cpp +++ b/modules/libpref/src/Preferences.cpp @@ -208,13 +208,16 @@ Preferences::SizeOfIncludingThisAndOtherStuff(mozilla::MallocSizeOf aMallocSizeO return n; } -NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(PreferencesMallocSizeOf) - -class PreferencesReporter MOZ_FINAL : public nsIMemoryReporter +class PreferenceServiceReporter MOZ_FINAL : public MemoryMultiReporter { public: - NS_DECL_ISUPPORTS - NS_DECL_NSIMEMORYREPORTER + PreferenceServiceReporter() + : MemoryMultiReporter("preference-service") + {} + + NS_IMETHOD CollectReports(nsIMemoryReporterCallback* aCallback, + nsISupports* aData); + protected: static const uint32_t kSuspectReferentCount = 1000; static PLDHashOperator CountReferents(PrefCallback* aKey, @@ -222,15 +225,6 @@ protected: void* aClosure); }; -NS_IMPL_ISUPPORTS1(PreferencesReporter, nsIMemoryReporter) - -NS_IMETHODIMP -PreferencesReporter::GetName(nsACString& aName) -{ - aName.AssignLiteral("preference-service"); - return NS_OK; -} - struct PreferencesReferentCount { PreferencesReferentCount() : numStrong(0), numWeakAlive(0), numWeakDead(0) {} size_t numStrong; @@ -242,9 +236,9 @@ struct PreferencesReferentCount { }; PLDHashOperator -PreferencesReporter::CountReferents(PrefCallback* aKey, - nsAutoPtr& aCallback, - void* aClosure) +PreferenceServiceReporter::CountReferents(PrefCallback* aKey, + nsAutoPtr& aCallback, + void* aClosure) { PreferencesReferentCount* referentCount = static_cast(aClosure); @@ -279,8 +273,8 @@ PreferencesReporter::CountReferents(PrefCallback* aKey, } NS_IMETHODIMP -PreferencesReporter::CollectReports(nsIMemoryReporterCallback* aCb, - nsISupports* aClosure) +PreferenceServiceReporter::CollectReports(nsIMemoryReporterCallback* aCb, + nsISupports* aClosure) { #define REPORT(_path, _kind, _units, _amount, _desc) \ do { \ @@ -293,7 +287,7 @@ PreferencesReporter::CollectReports(nsIMemoryReporterCallback* aCb, REPORT(NS_LITERAL_CSTRING("explicit/preferences"), nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES, - Preferences::SizeOfIncludingThisAndOtherStuff(PreferencesMallocSizeOf), + Preferences::SizeOfIncludingThisAndOtherStuff(MallocSizeOf), "Memory used by the preferences system."); nsPrefBranch* rootBranch = @@ -347,7 +341,7 @@ class AddPreferencesMemoryReporterRunnable : public nsRunnable { NS_IMETHOD Run() { - return NS_RegisterMemoryReporter(new PreferencesReporter()); + return NS_RegisterMemoryReporter(new PreferenceServiceReporter()); } }; } // anonymous namespace diff --git a/modules/libpref/src/nsPrefBranch.h b/modules/libpref/src/nsPrefBranch.h index b9477f050ce..8884e60a284 100644 --- a/modules/libpref/src/nsPrefBranch.h +++ b/modules/libpref/src/nsPrefBranch.h @@ -24,13 +24,13 @@ #include "mozilla/MemoryReporting.h" namespace mozilla { -class PreferencesReporter; +class PreferenceServiceReporter; } // namespace mozilla; class nsPrefBranch; class PrefCallback : public PLDHashEntryHdr { - friend class mozilla::PreferencesReporter; + friend class mozilla::PreferenceServiceReporter; public: typedef PrefCallback* KeyType; @@ -178,7 +178,7 @@ class nsPrefBranch : public nsIPrefBranchInternal, public nsIObserver, public nsSupportsWeakReference { - friend class mozilla::PreferencesReporter; + friend class mozilla::PreferenceServiceReporter; public: NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSIPREFBRANCH diff --git a/python/mozboot/mozboot/centos.py b/python/mozboot/mozboot/centos.py index 144d9438919..0158c6a76ae 100644 --- a/python/mozboot/mozboot/centos.py +++ b/python/mozboot/mozboot/centos.py @@ -34,6 +34,7 @@ class CentOSBootstrapper(BaseBootstrapper): 'libXt-devel', 'mercurial', 'mesa-libGL-devel', + 'pulseaudio-libs-devel', 'wireless-tools-devel', 'yasm') diff --git a/python/mozboot/mozboot/debian.py b/python/mozboot/mozboot/debian.py index bd2f47ba6cf..2c1b8d67267 100644 --- a/python/mozboot/mozboot/debian.py +++ b/python/mozboot/mozboot/debian.py @@ -21,6 +21,7 @@ class DebianBootstrapper(BaseBootstrapper): 'libgtk2.0-dev', 'libiw-dev', 'libnotify-dev', + 'libpulse-dev', 'libxt-dev', 'mercurial', 'mesa-common-dev', diff --git a/python/mozboot/mozboot/fedora.py b/python/mozboot/mozboot/fedora.py index 0efc55733c9..f6471f9fa40 100644 --- a/python/mozboot/mozboot/fedora.py +++ b/python/mozboot/mozboot/fedora.py @@ -29,6 +29,7 @@ class FedoraBootstrapper(BaseBootstrapper): 'libXt-devel', 'mercurial', 'mesa-libGL-devel', + 'pulseaudio-libs-devel', 'wireless-tools-devel', 'yasm') diff --git a/storage/src/mozStorageService.cpp b/storage/src/mozStorageService.cpp index b67fe1da4ad..caf1379db3f 100644 --- a/storage/src/mozStorageService.cpp +++ b/storage/src/mozStorageService.cpp @@ -59,7 +59,7 @@ StorageSQLiteDistinguishedAmount() return ::sqlite3_memory_used(); } -class StorageSQLiteReporter MOZ_FINAL : public nsIMemoryReporter +class StorageSQLiteReporter MOZ_FINAL : public MemoryMultiReporter { private: Service *mService; // a weakref because Service contains a strongref to this @@ -68,10 +68,9 @@ private: nsCString mSchemaDesc; public: - NS_DECL_THREADSAFE_ISUPPORTS - StorageSQLiteReporter(Service *aService) - : mService(aService) + : MemoryMultiReporter("storage-sqlite") + , mService(aService) { mStmtDesc = NS_LITERAL_CSTRING( "Memory (approximate) used by all prepared statements used by " @@ -86,12 +85,6 @@ public: "associated with connections to this database."); } - NS_IMETHOD GetName(nsACString &aName) - { - aName.AssignLiteral("storage-sqlite-multi"); - return NS_OK; - } - // Warning: To get a Connection's measurements requires holding its lock. // There may be a delay getting the lock if another thread is accessing the // Connection. This isn't very nice if CollectReports is called from the @@ -204,11 +197,6 @@ private: } }; -NS_IMPL_ISUPPORTS1( - StorageSQLiteReporter, - nsIMemoryReporter -) - //////////////////////////////////////////////////////////////////////////////// //// Service diff --git a/testing/testsuite-targets.mk b/testing/testsuite-targets.mk index ec0cec02e2d..5966af5e94e 100644 --- a/testing/testsuite-targets.mk +++ b/testing/testsuite-targets.mk @@ -90,8 +90,12 @@ endif mochitest-remote: DM_TRANS?=adb mochitest-remote: - @if [ ! -f ${MOZ_HOST_BIN}/xpcshell ]; then \ - echo "please prepare your host with the environment variable MOZ_HOST_BIN"; \ + @if [ "${MOZ_HOST_BIN}" = "" ]; then \ + echo "environment variable MOZ_HOST_BIN must be set to a directory containing host xpcshell"; \ + elif [ ! -d ${MOZ_HOST_BIN} ]; then \ + echo "MOZ_HOST_BIN does not specify a directory"; \ + elif [ ! -f ${MOZ_HOST_BIN}/xpcshell ]; then \ + echo "xpcshell not found in MOZ_HOST_BIN"; \ elif [ "${TEST_DEVICE}" = "" -a "$(DM_TRANS)" != "adb" ]; then \ echo "please prepare your host with the environment variable TEST_DEVICE"; \ else \ @@ -103,8 +107,12 @@ mochitest-robotium: mochitest-robocop mochitest-robocop: DM_TRANS?=adb mochitest-robocop: - @if [ ! -f ${MOZ_HOST_BIN}/xpcshell ]; then \ - echo "please prepare your host with the environment variable MOZ_HOST_BIN"; \ + @if [ "${MOZ_HOST_BIN}" = "" ]; then \ + echo "environment variable MOZ_HOST_BIN must be set to a directory containing host xpcshell"; \ + elif [ ! -d ${MOZ_HOST_BIN} ]; then \ + echo "MOZ_HOST_BIN does not specify a directory"; \ + elif [ ! -f ${MOZ_HOST_BIN}/xpcshell ]; then \ + echo "xpcshell not found in MOZ_HOST_BIN"; \ elif [ "${TEST_DEVICE}" = "" -a "$(DM_TRANS)" != "adb" ]; then \ echo "please prepare your host with the environment variable TEST_DEVICE"; \ else \ @@ -212,8 +220,12 @@ reftest: reftest-remote: TEST_PATH?=layout/reftests/reftest.list reftest-remote: DM_TRANS?=adb reftest-remote: - @if [ ! -f ${MOZ_HOST_BIN}/xpcshell ]; then \ - echo "please prepare your host with the environment variable MOZ_HOST_BIN"; \ + @if [ "${MOZ_HOST_BIN}" = "" ]; then \ + echo "environment variable MOZ_HOST_BIN must be set to a directory containing host xpcshell"; \ + elif [ ! -d ${MOZ_HOST_BIN} ]; then \ + echo "MOZ_HOST_BIN does not specify a directory"; \ + elif [ ! -f ${MOZ_HOST_BIN}/xpcshell ]; then \ + echo "xpcshell not found in MOZ_HOST_BIN"; \ elif [ "${TEST_DEVICE}" = "" -a "$(DM_TRANS)" != "adb" ]; then \ echo "please prepare your host with the environment variable TEST_DEVICE"; \ else \ @@ -224,8 +236,12 @@ reftest-remote: reftest-b2g: TEST_PATH?=layout/reftests/reftest.list reftest-b2g: - @if [ ! -f ${MOZ_HOST_BIN}/xpcshell ]; then \ - echo "please set the MOZ_HOST_BIN environment variable"; \ + @if [ "${MOZ_HOST_BIN}" = "" ]; then \ + echo "environment variable MOZ_HOST_BIN must be set to a directory containing host xpcshell"; \ + elif [ ! -d ${MOZ_HOST_BIN} ]; then \ + echo "MOZ_HOST_BIN does not specify a directory"; \ + elif [ ! -f ${MOZ_HOST_BIN}/xpcshell ]; then \ + echo "xpcshell not found in MOZ_HOST_BIN"; \ elif [ "${B2G_PATH}" = "" -o "${ADB_PATH}" = "" ]; then \ echo "please set the B2G_PATH and ADB_PATH environment variables"; \ else \ diff --git a/toolkit/components/aboutmemory/content/aboutMemory.js b/toolkit/components/aboutmemory/content/aboutMemory.js index 639289a7d33..0c7cee1d296 100644 --- a/toolkit/components/aboutmemory/content/aboutMemory.js +++ b/toolkit/components/aboutmemory/content/aboutMemory.js @@ -48,11 +48,6 @@ XPCOMUtils.defineLazyGetter(this, "nsGzipConverter", let gMgr = Cc["@mozilla.org/memory-reporter-manager;1"] .getService(Ci.nsIMemoryReporterManager); -// We need to know about "child-memory-reporter-update" events from child -// processes. -Services.obs.addObserver(updateAboutMemoryFromReporters, - "child-memory-reporter-update", false); - let gUnnamedProcessStr = "Main Process"; let gIsDiff = false; @@ -120,8 +115,6 @@ function debug(x) function onUnload() { - Services.obs.removeObserver(updateAboutMemoryFromReporters, - "child-memory-reporter-update"); } //--------------------------------------------------------------------------- @@ -388,11 +381,6 @@ function doMMU() function doMeasure() { - // Notify any children that they should measure memory consumption, then - // update the page. If any reports come back from children, - // updateAboutMemoryFromReporters() will be called again and the page will - // regenerate. - Services.obs.notifyObservers(null, "child-memory-reporter-request", null); updateAboutMemoryFromReporters(); } @@ -402,10 +390,7 @@ function doMeasure() */ function updateAboutMemoryFromReporters() { - // First, clear the contents of main. Necessary because - // updateAboutMemoryFromReporters() might be called more than once due to the - // "child-memory-reporter-update" observer. - updateMainAndFooter("", SHOW_FOOTER); + updateMainAndFooter("Measuring...", HIDE_FOOTER); try { let processLiveMemoryReports = @@ -416,12 +401,13 @@ function updateAboutMemoryFromReporters() aDescription, /* presence = */ undefined); } - let e = gMgr.enumerateReporters(); - while (e.hasMoreElements()) { - let mr = e.getNext().QueryInterface(Ci.nsIMemoryReporter); - mr.collectReports(handleReport, null); + let displayReportsAndFooter = function() { + updateMainAndFooter("", SHOW_FOOTER); + aDisplayReports(); } - aDisplayReports(); + + gMgr.getReports(handleReport, null, + displayReportsAndFooter, null); } // Process the reports from the live memory reporters. @@ -1841,9 +1827,11 @@ function saveReportsToFile() let dumper = Cc["@mozilla.org/memory-info-dumper;1"] .getService(Ci.nsIMemoryInfoDumper); - dumper.dumpMemoryReportsToNamedFile(fp.file.path); + let finishDumping = () => { + updateMainAndFooter("Saved reports to " + fp.file.path, HIDE_FOOTER); + } - updateMainAndFooter("Saved reports to " + fp.file.path, HIDE_FOOTER); + dumper.dumpMemoryReportsToNamedFile(fp.file.path, finishDumping, null); } }; fp.open(fpCallback); diff --git a/toolkit/components/aboutmemory/tests/Makefile.in b/toolkit/components/aboutmemory/tests/Makefile.in deleted file mode 100644 index 5af1a06954a..00000000000 --- a/toolkit/components/aboutmemory/tests/Makefile.in +++ /dev/null @@ -1,12 +0,0 @@ -# -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -ifndef MOZ_ASAN -MOCHITEST_CHROME_FILES += \ - remote.xul \ - test_memoryReporters.xul \ - test_memoryReporters2.xul \ - $(NULL) -endif diff --git a/toolkit/components/aboutmemory/tests/chrome.ini b/toolkit/components/aboutmemory/tests/chrome.ini index dec13aef2e1..54328f8e5de 100644 --- a/toolkit/components/aboutmemory/tests/chrome.ini +++ b/toolkit/components/aboutmemory/tests/chrome.ini @@ -4,9 +4,13 @@ support-files = memory-reports-diff1.json memory-reports-diff2.json memory-reports-good.json + remote.xul [test_aboutmemory.xul] [test_aboutmemory2.xul] [test_aboutmemory3.xul] [test_aboutmemory4.xul] +[test_aboutmemory5.xul] +[test_memoryReporters.xul] +[test_memoryReporters2.xul] [test_sqliteMultiReporter.xul] diff --git a/toolkit/components/aboutmemory/tests/test_aboutmemory3.xul b/toolkit/components/aboutmemory/tests/test_aboutmemory3.xul index 72bf8351d18..21d383b4f6f 100644 --- a/toolkit/components/aboutmemory/tests/test_aboutmemory3.xul +++ b/toolkit/components/aboutmemory/tests/test_aboutmemory3.xul @@ -108,21 +108,60 @@ let e = document.createEvent('Event'); e.initEvent('change', true, true); - if (!aFilename2) { - if (aDumpFirst) { - let dumper = Cc["@mozilla.org/memory-info-dumper;1"]. - getService(Ci.nsIMemoryInfoDumper); + function check() { + // Initialize the clipboard contents. + SpecialPowers.clipboardCopyString("initial clipboard value"); - dumper.dumpMemoryReportsToNamedFile(filePath, - /* minimizeMemoryUsage = */ false, - /* dumpChildProcesses = */ false); + let numFailures = 0, maxFailures = 30; + + // Because the file load is async, we don't know when it will finish and + // the output will show up. So we poll. + function copyPasteAndCheck() { + // Copy and paste frame contents, and filter out non-deterministic + // differences. + synthesizeKey("A", {accelKey: true}); + synthesizeKey("C", {accelKey: true}); + let actual = SpecialPowers.getClipboardData("text/unicode"); + actual = actual.replace(/\(pid \d+\)/g, "(pid NNN)"); + + if (actual === aExpected) { + SimpleTest.ok(true, "Clipboard has the expected contents"); + aNext(); + } else { + numFailures++; + if (numFailures === maxFailures) { + ok(false, "pasted text doesn't match"); + dump("******EXPECTED******\n"); + dump(aExpected); + dump("*******ACTUAL*******\n"); + dump(actual); + dump("********************\n"); + finish(); + } else { + setTimeout(copyPasteAndCheck, 100); + } + } + } + copyPasteAndCheck(); + } + + if (!aFilename2) { + function loadAndCheck() { + let fileInput1 = + frame.contentWindow.document.getElementById("fileInput1"); + fileInput1.value = filePath; // this works because it's a chrome test + + fileInput1.dispatchEvent(e); + check(); } - let fileInput1 = - frame.contentWindow.document.getElementById("fileInput1"); - fileInput1.value = filePath; // this works because it's a chrome test - - fileInput1.dispatchEvent(e); + if (aDumpFirst) { + let dumper = Cc["@mozilla.org/memory-info-dumper;1"]. + getService(Ci.nsIMemoryInfoDumper); + dumper.dumpMemoryReportsToNamedFile(filePath, loadAndCheck, null); + } else { + loadAndCheck(); + } } else { let fileInput2 = @@ -144,42 +183,9 @@ let e2 = document.createEvent('Event'); e2.initEvent('change', true, true); fileInput2.dispatchEvent(e); + + check(); } - - // Initialize the clipboard contents. - SpecialPowers.clipboardCopyString("initial clipboard value"); - - let numFailures = 0, maxFailures = 30; - - // Because the file load is async, we don't know when it will finish and - // the output will show up. So we poll. - function copyPasteAndCheck() { - // Copy and paste frame contents, and filter out non-deterministic - // differences. - synthesizeKey("A", {accelKey: true}); - synthesizeKey("C", {accelKey: true}); - let actual = SpecialPowers.getClipboardData("text/unicode"); - actual = actual.replace(/\(pid \d+\)/g, "(pid NNN)"); - - if (actual === aExpected) { - SimpleTest.ok(true, "Clipboard has the expected contents"); - aNext(); - } else { - numFailures++; - if (numFailures === maxFailures) { - ok(false, "pasted text doesn't match"); - dump("******EXPECTED******\n"); - dump(aExpected); - dump("*******ACTUAL*******\n"); - dump(actual); - dump("********************\n"); - finish(); - } else { - setTimeout(copyPasteAndCheck, 100); - } - } - } - copyPasteAndCheck(); } // Returns a function that chains together multiple test() calls. diff --git a/toolkit/components/aboutmemory/tests/test_aboutmemory5.xul b/toolkit/components/aboutmemory/tests/test_aboutmemory5.xul new file mode 100644 index 00000000000..50a464310cc --- /dev/null +++ b/toolkit/components/aboutmemory/tests/test_aboutmemory5.xul @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + diff --git a/toolkit/components/aboutmemory/tests/test_memoryReporters.xul b/toolkit/components/aboutmemory/tests/test_memoryReporters.xul index 2573f28a8bd..0f6deb4bf51 100644 --- a/toolkit/components/aboutmemory/tests/test_memoryReporters.xul +++ b/toolkit/components/aboutmemory/tests/test_memoryReporters.xul @@ -179,12 +179,12 @@ dummy = r.name; } - function checkSpecialReport(aName, aAmounts) + function checkSpecialReport(aName, aAmounts, aCanBeUnreasonable) { ok(aAmounts.length == 1, aName + " has " + aAmounts.length + " report"); let n = aAmounts[0]; // Check the size is reasonable -- i.e. not ridiculously large or small. - ok(100 * 1000 <= n && n <= 10 * 1000 * 1000 * 1000, + ok((100 * 1000 <= n && n <= 10 * 1000 * 1000 * 1000) || aCanBeUnreasonable, aName + "'s size is reasonable"); } @@ -192,7 +192,8 @@ if (haveExplicit) { checkSpecialReport("heap-allocated", heapAllocatedAmounts); } - checkSpecialReport("vsize", vsizeAmounts); + // vsize may be unreasonable if ASAN is enabled + checkSpecialReport("vsize", vsizeAmounts, /*canBeUnreasonable*/true); checkSpecialReport("resident", residentAmounts); checkSpecialReport("js-main-runtime-gc-heap-committed/used/gc-things", jsGcHeapAmounts); diff --git a/toolkit/components/aboutmemory/tests/test_memoryReporters2.xul b/toolkit/components/aboutmemory/tests/test_memoryReporters2.xul index 2be3d7c468f..2c1e726821b 100644 --- a/toolkit/components/aboutmemory/tests/test_memoryReporters2.xul +++ b/toolkit/components/aboutmemory/tests/test_memoryReporters2.xul @@ -19,15 +19,11 @@ SimpleTest.waitForExplicitFinish(); - // We want to know when a remote process sends us an update. - let os = Cc["@mozilla.org/observer-service;1"] - .getService(Ci.nsIObserverService); - os.addObserver(childMemoryReporterUpdate, "child-memory-reporter-update", false); - let numRemotes = 3; + let numReady = 0; - // Create some remote processes, and set up message-passing so that go() is - // called once per process, once it is fully initialized. + // Create some remote processes, and set up message-passing so that + // we know when each child is fully initialized. let remotes = []; SpecialPowers.pushPrefEnv({"set": [["dom.ipc.processCount", 3]]}, function() { for (let i = 0; i < numRemotes; i++) { @@ -39,47 +35,40 @@ let mm = remoteBrowser.messageManager; mm.addMessageListener("test:ready", function readyHandler() { mm.removeMessageListener("test:ready", readyHandler); - remoteReady(); + numReady++; + if (numReady == numRemotes) { + // All the remote processes are ready. Do memory reporting. + doReports(); + } }); mm.loadFrameScript("data:," + encodeURI("sendAsyncMessage('test:ready');"), true); }); } }); - let numReady = 0; + let mgr = Cc["@mozilla.org/memory-reporter-manager;1"]. + getService(Ci.nsIMemoryReporterManager); - function remoteReady() + function doReports() { - numReady++; - if (numReady == numRemotes) { - // All the remote processes are ready. Ask them for memory reports. - os.notifyObservers(null, "child-memory-reporter-request", null); - } - } + let residents = {}; - let numUpdates = 0; - - function childMemoryReporterUpdate() - { - numUpdates++; - if (numUpdates == numRemotes) { - // All the remote processes have reported back. Check reports. - let vsizes = {}; - - // Get all the reports. - let mgr = Cc["@mozilla.org/memory-reporter-manager;1"]. - getService(Ci.nsIMemoryReporterManager); - let e = mgr.enumerateReporters(); - while (e.hasMoreElements()) { - let r = e.getNext().QueryInterface(Ci.nsIMemoryReporter); - r.collectReports(function(aProcess, aPath, aKind, aUnits, aAmount, aDesc) { - if (aPath === "vsize") { - ok(100 * 1000 <= aAmount && aAmount <= 10 * 1000 * 1000 * 1000, - "vsize is reasonable"); - vsizes[aProcess] = aAmount; - } - }, null); + let handleReport = function(aProcess, aPath, aKind, aUnits, aAmount, aDesc) { + if (aPath === "resident") { + ok(100 * 1000 <= aAmount && aAmount <= 10 * 1000 * 1000 * 1000, + "resident is reasonable"); + residents[aProcess] = aAmount; } + } + + let processReports = function() { + // First, test a failure case: calling getReports() before the previous + // getReports() has finished should silently abort. (And the arguments + // won't be used.) + mgr.getReports( + () => ok(false, "handleReport called for nested getReports() call"), + null, null, null + ); // Close the remote processes. for (let i = 0; i < numRemotes; i++) { @@ -88,8 +77,8 @@ // Check the results. - let processes = Object.keys(vsizes); - ok(processes.length == numRemotes + 1, "correct vsize count"); + let processes = Object.keys(residents); + ok(processes.length == numRemotes + 1, "correct resident count"); let numEmptyProcesses = 0, numNonEmptyProcesses = 0; for (let i = 0; i < processes.length; i++) { @@ -107,6 +96,9 @@ SimpleTest.finish(); } + + mgr.getReports(handleReport, null, processReports, null); } + ]]> diff --git a/xpcom/base/nsCycleCollector.cpp b/xpcom/base/nsCycleCollector.cpp index 1bcd577a9e5..ba01e6f0f6c 100644 --- a/xpcom/base/nsCycleCollector.cpp +++ b/xpcom/base/nsCycleCollector.cpp @@ -2387,21 +2387,14 @@ nsCycleCollector::CollectWhite() // Memory reporter //////////////////////// -class CycleCollectorReporter MOZ_FINAL : public nsIMemoryReporter +class CycleCollectorReporter MOZ_FINAL : public MemoryMultiReporter { public: CycleCollectorReporter(nsCycleCollector* aCollector) - : mCollector(aCollector) + : MemoryMultiReporter("cycle-collector"), + mCollector(aCollector) {} - NS_DECL_ISUPPORTS - - NS_IMETHOD GetName(nsACString& name) - { - name.AssignLiteral("cycle-collector"); - return NS_OK; - } - NS_IMETHOD CollectReports(nsIMemoryReporterCallback* aCb, nsISupports* aClosure) { @@ -2461,8 +2454,6 @@ class CycleCollectorReporter MOZ_FINAL : public nsIMemoryReporter nsCycleCollector* mCollector; }; -NS_IMPL_ISUPPORTS1(CycleCollectorReporter, nsIMemoryReporter) - //////////////////////////////////////////////////////////////////////// // Collector implementation diff --git a/xpcom/base/nsIMemoryInfoDumper.idl b/xpcom/base/nsIMemoryInfoDumper.idl index 7042f778e97..6566c1d52ab 100644 --- a/xpcom/base/nsIMemoryInfoDumper.idl +++ b/xpcom/base/nsIMemoryInfoDumper.idl @@ -5,13 +5,18 @@ #include "nsISupports.idl" -[scriptable, builtinclass, uuid(3FFA5113-2A10-43BB-923B-6A2FAF67BE97)] +[scriptable, function, uuid(2dea18fc-fbfa-4bf7-ad45-0efaf5495f5e)] +interface nsIFinishDumpingCallback : nsISupports +{ + void callback(in nsISupports data); +}; + +[scriptable, builtinclass, uuid(fd5de30a-e3d6-4965-8244-86709e1ed23b)] interface nsIMemoryInfoDumper : nsISupports { /** - * This dumps gzipped memory reports for this process. If a file of the - * given name exists, it will be overwritten. Nothing is done for any child - * processes (and their children, recursively). + * This dumps gzipped memory reports for this process and its child + * processes. If a file of the given name exists, it will be overwritten. * * @param aFilename The output file. * @@ -83,17 +88,19 @@ interface nsIMemoryInfoDumper : nsISupports * } * } */ - void dumpMemoryReportsToNamedFile(in AString aFilename); + void dumpMemoryReportsToNamedFile(in AString aFilename, + in nsIFinishDumpingCallback aFinishDumping, + in nsISupports aFinishDumpingData); /** * Similar to dumpMemoryReportsToNamedFile, this method dumps gzipped memory - * reports for this process and possibly our child processes (and their + * reports for this process and possibly its child processes (and their * children, recursively) to a file in the tmp directory called * memory-reports--.json.gz (or something similar, such as * memory-reports---1.json.gz; no existing file will be * overwritten). * - * If DMD is enabled, this method also dump gzipped DMD output to a file in + * If DMD is enabled, this method also dumps gzipped DMD output to a file in * the tmp directory called dmd--.txt.gz (or something * similar; again, no existing file will be overwritten). * diff --git a/xpcom/base/nsIMemoryReporter.idl b/xpcom/base/nsIMemoryReporter.idl index 56943cc3fd3..4a6a551ba45 100644 --- a/xpcom/base/nsIMemoryReporter.idl +++ b/xpcom/base/nsIMemoryReporter.idl @@ -179,13 +179,19 @@ interface nsIMemoryReporter : nsISupports const int32_t UNITS_PERCENTAGE = 3; }; -[scriptable, builtinclass, uuid(4db7040a-16f9-4249-879b-fe72729c7ef5)] +[scriptable, function, uuid(548b3909-c04d-4ca6-8466-b8bee3837457)] +interface nsIFinishReportingCallback : nsISupports +{ + void callback(in nsISupports data); +}; + +[scriptable, builtinclass, uuid(a1292276-726b-4ef5-a017-5a455d6664dd)] interface nsIMemoryReporterManager : nsISupports { /* - * Return an enumerator of nsIMemoryReporters that are currently registered. + * Initialize. */ - nsISimpleEnumerator enumerateReporters(); + void init(); /* * Register the given nsIMemoryReporter. After a reporter is registered, @@ -207,9 +213,30 @@ interface nsIMemoryReporterManager : nsISupports void registerReporterEvenIfBlocked(in nsIMemoryReporter aReporter); /* - * Initialize. + * Return an enumerator of nsIMemoryReporters that are currently registered + * in the current process. WARNING: this does not do anything with child + * processes. Use getReports() if you want measurements from child + * processes. */ - void init(); + nsISimpleEnumerator enumerateReporters(); + + /* + * Get memory reports for the current process and all child processes. + * |handleReport| is called for each report, and |finishReporting| is called + * once all reports have been handled. + * + * |finishReporting| is called even if, for example, some child processes + * fail to report back. However, calls to this method will silently and + * immediately abort -- and |finishReporting| will not be called -- if a + * previous getReports() call is still in flight, i.e. if it has not yet + * finished invoking |finishReporting|. The silent abort is because the + * in-flight request will finish soon, and the caller would very likely just + * catch and ignore any error anyway. + */ + void getReports(in nsIMemoryReporterCallback handleReport, + in nsISupports handleReportData, + in nsIFinishReportingCallback finishReporting, + in nsISupports finishReportingData); /* * The memory reporter manager, for the most part, treats reporters @@ -332,9 +359,14 @@ interface nsIMemoryReporterManager : nsISupports #include "js/TypeDecls.h" #include "nsStringGlue.h" +#include "nsTArray.h" class nsPIDOMWindow; +// nsIHandleReportCallback is a better name, but keep nsIMemoryReporterCallback +// around for backwards compatibility. +typedef nsIMemoryReporterCallback nsIHandleReportCallback; + // Note that the memory reporters are held in an nsCOMArray, which means // that individual reporters should be referenced with |nsIMemoryReporter *| // instead of nsCOMPtr. @@ -396,8 +428,9 @@ nsresult RegisterNonJSSizeOfTab(NonJSSizeOfTabFn aSizeOfTabFn); #if defined(MOZ_DMD) namespace mozilla { namespace dmd { -// This runs all the memory reporters but does nothing with the results; i.e. -// it does the minimal amount of work possible for DMD to do its thing. +// This runs all the memory reporters in the current process but does nothing +// with the results; i.e. it does the minimal amount of work possible for DMD +// to do its thing. It does nothing with child processes. void RunReporters(); } } @@ -459,18 +492,18 @@ namespace mozilla { // memory uni-reporters. You just need to provide the following. // - The constant values: nameAndPath (which serves as both the reporters name, // and the path in its single report), kind, units, and description. They -// are passed to the MemoryUniReporter constructor. -// - A (private) Amount() or (public) GetAmount() method. It can use the +// are arguments to the MemoryUniReporter constructor. +// - A private Amount() or public GetAmount() method. It can use the // MallocSizeOf method if necessary. (There is also // MallocSizeOfOn{Alloc,Free}, which can be useful.) Use Amount() if the // reporter is infallible, and GetAmount() otherwise. (If you fail to // provide one or the other, you'll get assertion failures when the memory // reporter runs.) // -// The class name of subclasses should match the path, minus the "explicit" -// (if present), and with "Reporter" at the end. For example: -// - "explicit/dom/xyzzy" --> DOMXyzzyReporter -// - "js-compartments/system" --> JSCompartmentsSystemReporter +// The class name of subclasses should match the nameAndPath, minus the +// "explicit" (if present), and with "Reporter" at the end. For example: +// - nameAndPath == "explicit/dom/xyzzy" --> DOMXyzzyReporter +// - nameAndPath == "js-compartments/system" --> JSCompartmentsSystemReporter // class MemoryUniReporter : public nsIMemoryReporter { @@ -528,6 +561,46 @@ protected: const nsCString mDescription; }; +// The following base class reduces the amount of boilerplate code required for +// memory multi-reporters. You just need to provide the following. +// - The constant value: name. It is an argument to the MemoryMultiReporter +// constructor. The name of each multi-reporter should be unique. +// - A public CollectReports() method. It can use the MallocSizeOf method if +// necessary. (There is also MallocSizeOfOn{Alloc,Free}, which can be +// useful.) +// +// The class name of subclasses should match the name, with "Reporter" at +// the end. For example: +// - name == "foo" --> FooMultiReporter +// +class MemoryMultiReporter : public nsIMemoryReporter +{ +public: + MemoryMultiReporter(const char* aName) + : mName(aName) + {} + + virtual ~MemoryMultiReporter() {} + + NS_DECL_THREADSAFE_ISUPPORTS + + NS_IMETHOD GetName(nsACString& aName) + { + aName.Assign(mName); + return NS_OK; + } + + NS_IMETHOD CollectReports(nsIMemoryReporterCallback* aCb, + nsISupports* aClosure) = 0; + +protected: + NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(MallocSizeOf) + NS_MEMORY_REPORTER_MALLOC_SIZEOF_ON_ALLOC_FUN(MallocSizeOfOnAlloc) + NS_MEMORY_REPORTER_MALLOC_SIZEOF_ON_FREE_FUN(MallocSizeOfOnFree) + + const nsCString mName; +}; + } // namespace mozilla %} diff --git a/xpcom/base/nsMemoryInfoDumper.cpp b/xpcom/base/nsMemoryInfoDumper.cpp index 82d046a5d6a..c5ae19f0840 100644 --- a/xpcom/base/nsMemoryInfoDumper.cpp +++ b/xpcom/base/nsMemoryInfoDumper.cpp @@ -610,32 +610,33 @@ namespace mozilla { } while (0) static nsresult -DumpReport(nsIGZFileWriter *aWriter, bool *aIsFirstPtr, +DumpReport(nsIGZFileWriter *aWriter, bool aIsFirst, const nsACString &aProcess, const nsACString &aPath, int32_t aKind, int32_t aUnits, int64_t aAmount, const nsACString &aDescription) { - // We only want to dump reports for this process. If |aProcess| is - // non-nullptr that means we've received it from another process in response - // to a "child-memory-reporter-request" event; ignore such reports. - if (!aProcess.IsEmpty()) { - return NS_OK; - } + DUMP(aWriter, aIsFirst ? "[" : ","); - DUMP(aWriter, *aIsFirstPtr ? "[" : ","); - *aIsFirstPtr = false; - - // Generate the process identifier, which is of the form "$PROCESS_NAME - // (pid $PID)", or just "(pid $PID)" if we don't have a process name. If - // we're the main process, we let $PROCESS_NAME be "Main Process". nsAutoCString process; - if (XRE_GetProcessType() == GeckoProcessType_Default) { - // We're the main process. - process.AssignLiteral("Main Process "); - } else if (ContentChild *cc = ContentChild::GetSingleton()) { - // Try to get the process name from ContentChild. - cc->GetProcessName(process); + if (aProcess.IsEmpty()) { + // If the process is empty, the report originated with the process doing + // the dumping. In that case, generate the process identifier, which is of + // the form "$PROCESS_NAME (pid $PID)", or just "(pid $PID)" if we don't + // have a process name. If we're the main process, we let $PROCESS_NAME be + // "Main Process". + if (XRE_GetProcessType() == GeckoProcessType_Default) { + // We're the main process. + process.AssignLiteral("Main Process"); + } else if (ContentChild *cc = ContentChild::GetSingleton()) { + // Try to get the process name from ContentChild. + cc->GetProcessName(process); + } + ContentChild::AppendProcessId(process); + + } else { + // Otherwise, the report originated with another process and already has a + // process name. Just use that. + process = aProcess; } - ContentChild::AppendProcessId(process); DUMP(aWriter, "\n {\"process\": \""); DUMP(aWriter, process); @@ -666,12 +667,12 @@ DumpReport(nsIGZFileWriter *aWriter, bool *aIsFirstPtr, return NS_OK; } -class DumpReporterCallback MOZ_FINAL : public nsIMemoryReporterCallback +class DumpReportCallback MOZ_FINAL : public nsIHandleReportCallback { public: NS_DECL_ISUPPORTS - DumpReporterCallback() : mIsFirst(true) {} + DumpReportCallback() : mIsFirst(true) {} NS_IMETHOD Callback(const nsACString &aProcess, const nsACString &aPath, int32_t aKind, int32_t aUnits, int64_t aAmount, @@ -681,15 +682,17 @@ public: nsCOMPtr writer = do_QueryInterface(aData); NS_ENSURE_TRUE(writer, NS_ERROR_FAILURE); - return DumpReport(writer, &mIsFirst, aProcess, aPath, aKind, aUnits, - aAmount, aDescription); + nsresult rv = DumpReport(writer, mIsFirst, aProcess, aPath, aKind, aUnits, + aAmount, aDescription); + mIsFirst = false; + return rv; } private: bool mIsFirst; }; -NS_IMPL_ISUPPORTS1(DumpReporterCallback, nsIMemoryReporterCallback) +NS_IMPL_ISUPPORTS1(DumpReportCallback, nsIHandleReportCallback) } // namespace mozilla @@ -785,7 +788,7 @@ DMDWrite(void* aState, const char* aFmt, va_list ap) #endif static nsresult -DumpProcessMemoryReportsToGZFileWriter(nsIGZFileWriter *aWriter) +DumpHeader(nsIGZFileWriter* aWriter) { // Increment this number if the format changes. // @@ -804,22 +807,39 @@ DumpProcessMemoryReportsToGZFileWriter(nsIGZFileWriter *aWriter) DUMP(aWriter, ",\n"); DUMP(aWriter, " \"reports\": "); - // Process reporters. - bool more; - nsCOMPtr e; - mgr->EnumerateReporters(getter_AddRefs(e)); - nsRefPtr cb = new DumpReporterCallback(); - while (NS_SUCCEEDED(e->HasMoreElements(&more)) && more) { - nsCOMPtr r; - e->GetNext(getter_AddRefs(r)); - r->CollectReports(cb, aWriter); - } + return NS_OK; +} +static nsresult +DumpFooter(nsIGZFileWriter* aWriter) +{ DUMP(aWriter, "\n ]\n}\n"); return NS_OK; } +static nsresult +DumpProcessMemoryReportsToGZFileWriter(nsIGZFileWriter* aWriter) +{ + nsresult rv = DumpHeader(aWriter); + NS_ENSURE_SUCCESS(rv, rv); + + // Process reporters. + bool more; + nsCOMPtr e; + nsCOMPtr mgr = + do_GetService("@mozilla.org/memory-reporter-manager;1"); + mgr->EnumerateReporters(getter_AddRefs(e)); + nsRefPtr dumpReport = new DumpReportCallback(); + while (NS_SUCCEEDED(e->HasMoreElements(&more)) && more) { + nsCOMPtr r; + e->GetNext(getter_AddRefs(r)); + r->CollectReports(dumpReport, aWriter); + } + + return DumpFooter(aWriter); +} + nsresult DumpProcessMemoryInfoToTempDir(const nsAString& aIdentifier) { @@ -977,8 +997,45 @@ nsMemoryInfoDumper::DumpMemoryInfoToTempDir(const nsAString& aIdentifier, return DumpProcessMemoryInfoToTempDir(identifier); } +// This dumps the JSON footer and closes the file, and then calls the given +// nsIFinishDumpingCallback. +class FinishReportingCallback MOZ_FINAL : public nsIFinishReportingCallback +{ +public: + NS_DECL_ISUPPORTS + + FinishReportingCallback(nsIFinishDumpingCallback* aFinishDumping, + nsISupports* aFinishDumpingData) + : mFinishDumping(aFinishDumping) + , mFinishDumpingData(aFinishDumpingData) + {} + + NS_IMETHOD Callback(nsISupports* aData) + { + nsCOMPtr writer = do_QueryInterface(aData); + NS_ENSURE_TRUE(writer, NS_ERROR_FAILURE); + + nsresult rv = DumpFooter(writer); + NS_ENSURE_SUCCESS(rv, rv); + + rv = writer->Finish(); + NS_ENSURE_SUCCESS(rv, rv); + + return mFinishDumping->Callback(mFinishDumpingData); + } + +private: + nsCOMPtr mFinishDumping; + nsCOMPtr mFinishDumpingData; +}; + +NS_IMPL_ISUPPORTS1(FinishReportingCallback, nsIFinishReportingCallback) + NS_IMETHODIMP -nsMemoryInfoDumper::DumpMemoryReportsToNamedFile(const nsAString& aFilename) +nsMemoryInfoDumper::DumpMemoryReportsToNamedFile( + const nsAString& aFilename, + nsIFinishDumpingCallback* aFinishDumping, + nsISupports* aFinishDumpingData) { MOZ_ASSERT(!aFilename.IsEmpty()); @@ -1006,12 +1063,16 @@ nsMemoryInfoDumper::DumpMemoryReportsToNamedFile(const nsAString& aFilename) rv = mrWriter->Init(mrFile); NS_ENSURE_SUCCESS(rv, rv); - DumpProcessMemoryReportsToGZFileWriter(mrWriter); - - rv = mrWriter->Finish(); + rv = DumpHeader(mrWriter); NS_ENSURE_SUCCESS(rv, rv); - return NS_OK; + // Process reports and finish up. + nsRefPtr dumpReport = new DumpReportCallback(); + nsRefPtr finishReporting = + new FinishReportingCallback(aFinishDumping, aFinishDumpingData); + nsCOMPtr mgr = + do_GetService("@mozilla.org/memory-reporter-manager;1"); + return mgr->GetReports(dumpReport, mrWriter, finishReporting, mrWriter); } #undef DUMP diff --git a/xpcom/base/nsMemoryReporterManager.cpp b/xpcom/base/nsMemoryReporterManager.cpp index 373be344be9..bf3f6ec5914 100644 --- a/xpcom/base/nsMemoryReporterManager.cpp +++ b/xpcom/base/nsMemoryReporterManager.cpp @@ -11,6 +11,7 @@ #include "nsServiceManagerUtils.h" #include "nsMemoryReporterManager.h" #include "nsISimpleEnumerator.h" +#include "nsITimer.h" #include "nsThreadUtils.h" #include "nsIDOMWindow.h" #include "nsPIDOMWindow.h" @@ -23,6 +24,7 @@ #include "mozilla/PodOperations.h" #include "mozilla/Services.h" #include "mozilla/Telemetry.h" +#include "mozilla/dom/PMemoryReportRequestParent.h" // for dom::MemoryReport #ifndef XP_WIN #include @@ -665,21 +667,14 @@ private: namespace mozilla { namespace dmd { -class DMDReporter MOZ_FINAL : public nsIMemoryReporter +class DMDReporter MOZ_FINAL : public MemoryMultiReporter { public: DMDReporter() + : MemoryMultiReporter("dmd") {} - NS_DECL_ISUPPORTS - - NS_IMETHOD GetName(nsACString& aName) - { - aName.Assign("dmd"); - return NS_OK; - } - - NS_IMETHOD CollectReports(nsIMemoryReporterCallback* aCallback, + NS_IMETHOD CollectReports(nsIHandleReport* aHandleReport, nsISupports* aData) { dmd::Sizes sizes; @@ -688,10 +683,10 @@ public: #define REPORT(_path, _amount, _desc) \ do { \ nsresult rv; \ - rv = aCallback->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path), \ - nsIMemoryReporter::KIND_HEAP, \ - nsIMemoryReporter::UNITS_BYTES, _amount, \ - NS_LITERAL_CSTRING(_desc), aData); \ + rv = aHandleReport->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path), \ + nsIMemoryReporter::KIND_HEAP, \ + nsIMemoryReporter::UNITS_BYTES, _amount, \ + NS_LITERAL_CSTRING(_desc), aData); \ NS_ENSURE_SUCCESS(rv, rv); \ } while (0) @@ -719,8 +714,6 @@ public: } }; -NS_IMPL_ISUPPORTS1(DMDReporter, nsIMemoryReporter) - } // namespace dmd } // namespace mozilla @@ -845,10 +838,11 @@ HashtableEnumerator::GetNext(nsISupports** aNext) nsMemoryReporterManager::nsMemoryReporterManager() : mMutex("nsMemoryReporterManager::mMutex"), - mIsRegistrationBlocked(false) + mIsRegistrationBlocked(false), + mNumChildProcesses(0), + mNextGeneration(1), + mGetReportsState(nullptr) { - PodZero(&mAmountFns); - PodZero(&mSizeOfTabFns); } nsMemoryReporterManager::~nsMemoryReporterManager() @@ -858,8 +852,8 @@ nsMemoryReporterManager::~nsMemoryReporterManager() NS_IMETHODIMP nsMemoryReporterManager::EnumerateReporters(nsISimpleEnumerator** aResult) { - // Memory reporters are not necessarily threadsafe, so EnumerateReporters() - // must be called from the main thread. + // Memory reporters are not necessarily threadsafe, so this function must + // be called from the main thread. if (!NS_IsMainThread()) { MOZ_CRASH(); } @@ -872,6 +866,220 @@ nsMemoryReporterManager::EnumerateReporters(nsISimpleEnumerator** aResult) return NS_OK; } +//#define DEBUG_CHILD_PROCESS_MEMORY_REPORTING 1 + +#ifdef DEBUG_CHILD_PROCESS_MEMORY_REPORTING +#define MEMORY_REPORTING_LOG(format, ...) \ + fprintf(stderr, "++++ MEMORY REPORTING: " format, ##__VA_ARGS__); +#else +#define MEMORY_REPORTING_LOG(...) +#endif + +void +nsMemoryReporterManager::IncrementNumChildProcesses() +{ + if (!NS_IsMainThread()) { + MOZ_CRASH(); + } + mNumChildProcesses++; + MEMORY_REPORTING_LOG("IncrementNumChildProcesses --> %d\n", + mNumChildProcesses); +} + +void +nsMemoryReporterManager::DecrementNumChildProcesses() +{ + if (!NS_IsMainThread()) { + MOZ_CRASH(); + } + MOZ_ASSERT(mNumChildProcesses > 0); + mNumChildProcesses--; + MEMORY_REPORTING_LOG("DecrementNumChildProcesses --> %d\n", + mNumChildProcesses); +} + +NS_IMETHODIMP +nsMemoryReporterManager::GetReports( + nsIHandleReportCallback* aHandleReport, + nsISupports* aHandleReportData, + nsIFinishReportingCallback* aFinishReporting, + nsISupports* aFinishReportingData) +{ + // Memory reporters are not necessarily threadsafe, so this function must + // be called from the main thread. + if (!NS_IsMainThread()) { + MOZ_CRASH(); + } + + uint32_t generation = mNextGeneration++; + + if (mGetReportsState) { + // A request is in flight. Don't start another one. And don't report + // an error; just ignore it, and let the in-flight request finish. + MEMORY_REPORTING_LOG("GetReports (gen=%u, s->gen=%u): abort\n", + generation, mGetReportsState->mGeneration); + return NS_OK; + } + + MEMORY_REPORTING_LOG("GetReports (gen=%u, %d child(ren) present)\n", + generation, mNumChildProcesses); + + if (mNumChildProcesses > 0) { + // Request memory reports from child processes. We do this *before* + // collecting reports for this process so each process can collect + // reports in parallel. + nsCOMPtr obs = + do_GetService("@mozilla.org/observer-service;1"); + NS_ENSURE_STATE(obs); + + // Casting the uint32_t generation to |const PRUnichar*| is a hack, but + // simpler than converting the number to an actual string. + obs->NotifyObservers(nullptr, "child-memory-reporter-request", + (const PRUnichar*)(uintptr_t)generation); + + nsCOMPtr timer = do_CreateInstance(NS_TIMER_CONTRACTID); + NS_ENSURE_TRUE(timer, NS_ERROR_FAILURE); + nsresult rv = timer->InitWithFuncCallback(TimeoutCallback, + this, kTimeoutLengthMS, + nsITimer::TYPE_ONE_SHOT); + NS_ENSURE_SUCCESS(rv, rv); + + mGetReportsState = new GetReportsState(generation, + timer, + mNumChildProcesses, + aHandleReport, + aHandleReportData, + aFinishReporting, + aFinishReportingData); + } + + // Get reports for this process. + nsRefPtr e; + { + mozilla::MutexAutoLock autoLock(mMutex); + e = new HashtableEnumerator(mReporters); + } + bool more; + while (NS_SUCCEEDED(e->HasMoreElements(&more)) && more) { + nsCOMPtr r; + e->GetNext(getter_AddRefs(r)); + r->CollectReports(aHandleReport, aHandleReportData); + } + + // If there are no child processes, we can finish up immediately. + return (mNumChildProcesses == 0) + ? aFinishReporting->Callback(aFinishReportingData) + : NS_OK; +} + +// This function has no return value. If something goes wrong, there's no +// clear place to report the problem to, but that's ok -- we will end up +// hitting the timeout and executing TimeoutCallback(). +void +nsMemoryReporterManager::HandleChildReports( + const uint32_t& aGeneration, + const InfallibleTArray& aChildReports) +{ + // Memory reporting only happens on the main thread. + if (!NS_IsMainThread()) { + MOZ_CRASH(); + } + + GetReportsState* s = mGetReportsState; + + if (!s) { + // If we reach here, either: + // + // - A child process reported back too late, and no subsequent request + // is in flight. + // + // - (Unlikely) A "child-memory-reporter-request" notification was + // triggered from somewhere other than GetReports(), causing child + // processes to report back when the nsMemoryReporterManager wasn't + // expecting it. + // + // Either way, there's nothing to be done. Just ignore it. + MEMORY_REPORTING_LOG( + "HandleChildReports: no request in flight (aGen=%u)\n", + aGeneration); + return; + } + + if (aGeneration != s->mGeneration) { + // If we reach here, a child process must have reported back, too late, + // while a subsequent (higher-numbered) request is in flight. Again, + // ignore it. + MOZ_ASSERT(aGeneration < s->mGeneration); + MEMORY_REPORTING_LOG( + "HandleChildReports: gen mismatch (aGen=%u, s->gen=%u)\n", + aGeneration, s->mGeneration); + return; + } + + // Process the reports from the child process. + for (uint32_t i = 0; i < aChildReports.Length(); i++) { + const dom::MemoryReport& r = aChildReports[i]; + + // Child reports should have a non-empty process. + MOZ_ASSERT(!r.process().IsEmpty()); + + // If the call fails, ignore and continue. + s->mHandleReport->Callback(r.process(), r.path(), r.kind(), + r.units(), r.amount(), r.desc(), + s->mHandleReportData); + } + + // If all the child processes have reported, we can cancel the timer and + // finish up. Otherwise, just return. + + s->mNumChildProcessesCompleted++; + MEMORY_REPORTING_LOG("HandleChildReports (aGen=%u): completed child %d\n", + aGeneration, s->mNumChildProcessesCompleted); + + if (s->mNumChildProcessesCompleted == s->mNumChildProcesses) { + s->mTimer->Cancel(); + FinishReporting(); + } +} + +/* static */ void +nsMemoryReporterManager::TimeoutCallback(nsITimer* aTimer, void* aData) +{ + nsMemoryReporterManager* mgr = + static_cast(aData); + + MOZ_ASSERT(mgr->mGetReportsState); + MEMORY_REPORTING_LOG("TimeoutCallback (s->gen=%u)\n", + mgr->mGetReportsState->mGeneration); + + // We don't bother sending any kind of cancellation message to the child + // processes that haven't reported back. + + mgr->FinishReporting(); +} + +void +nsMemoryReporterManager::FinishReporting() +{ + // Memory reporting only happens on the main thread. + if (!NS_IsMainThread()) { + MOZ_CRASH(); + } + + MOZ_ASSERT(mGetReportsState); + MEMORY_REPORTING_LOG("FinishReporting (s->gen=%u)\n", + mGetReportsState->mGeneration); + + // Call this before deleting |mGetReportsState|. That way, if + // |mFinishReportData| calls GetReports(), it will silently abort, as + // required. + (void)mGetReportsState->mFinishReporting->Callback( + mGetReportsState->mFinishReportingData); + + delete mGetReportsState; + mGetReportsState = nullptr; +} + static void DebugAssertRefcountIsNonZero(nsISupports* aObj) { @@ -975,7 +1183,7 @@ public: }; NS_IMPL_ISUPPORTS0(Int64Wrapper) -class ExplicitCallback MOZ_FINAL : public nsIMemoryReporterCallback +class ExplicitCallback MOZ_FINAL : public nsIHandleReportCallback { public: NS_DECL_ISUPPORTS @@ -1002,7 +1210,7 @@ public: return NS_OK; } }; -NS_IMPL_ISUPPORTS1(ExplicitCallback, nsIMemoryReporterCallback) +NS_IMPL_ISUPPORTS1(ExplicitCallback, nsIHandleReportCallback) NS_IMETHODIMP nsMemoryReporterManager::GetExplicit(int64_t* aAmount) @@ -1020,7 +1228,7 @@ nsMemoryReporterManager::GetExplicit(int64_t* aAmount) // method which did this more efficiently, but it ended up being more // trouble than it was worth. - nsRefPtr cb = new ExplicitCallback(); + nsRefPtr handleReport = new ExplicitCallback(); nsRefPtr wrappedExplicitSize = new Int64Wrapper(); nsCOMPtr e; @@ -1028,7 +1236,7 @@ nsMemoryReporterManager::GetExplicit(int64_t* aAmount) while (NS_SUCCEEDED(e->HasMoreElements(&more)) && more) { nsCOMPtr r; e->GetNext(getter_AddRefs(r)); - r->CollectReports(cb, wrappedExplicitSize); + r->CollectReports(handleReport, wrappedExplicitSize); } *aAmount = wrappedExplicitSize->mValue; @@ -1325,6 +1533,7 @@ nsMemoryReporterManager::SizeOfTab(nsIDOMWindow* aTopWindow, // thread-safe just to be safe. Memory reporters are created and destroyed // infrequently enough that the performance cost should be negligible. NS_IMPL_ISUPPORTS1(MemoryUniReporter, nsIMemoryReporter) +NS_IMPL_ISUPPORTS1(MemoryMultiReporter, nsIMemoryReporter) nsresult NS_RegisterMemoryReporter(nsIMemoryReporter* aReporter) @@ -1349,10 +1558,8 @@ NS_UnregisterMemoryReporter(nsIMemoryReporter* aReporter) namespace mozilla { #define GET_MEMORY_REPORTER_MANAGER(mgr) \ - nsCOMPtr imgr = \ - do_GetService("@mozilla.org/memory-reporter-manager;1"); \ nsRefPtr mgr = \ - static_cast(imgr.get()); \ + nsMemoryReporterManager::GetOrCreate(); \ if (!mgr) { \ return NS_ERROR_FAILURE; \ } @@ -1418,7 +1625,7 @@ DEFINE_REGISTER_SIZE_OF_TAB(NonJS); namespace mozilla { namespace dmd { -class NullReporterCallback : public nsIMemoryReporterCallback +class DoNothingCallback : public nsIHandleReportCallback { public: NS_DECL_ISUPPORTS @@ -1433,8 +1640,8 @@ public: } }; NS_IMPL_ISUPPORTS1( - NullReporterCallback -, nsIMemoryReporterCallback + DoNothingCallback +, nsIHandleReportCallback ) void @@ -1443,7 +1650,7 @@ RunReporters() nsCOMPtr mgr = do_GetService("@mozilla.org/memory-reporter-manager;1"); - nsRefPtr cb = new NullReporterCallback(); + nsRefPtr doNothing = new DoNothingCallback(); bool more; nsCOMPtr e; @@ -1451,7 +1658,7 @@ RunReporters() while (NS_SUCCEEDED(e->HasMoreElements(&more)) && more) { nsCOMPtr r; e->GetNext(getter_AddRefs(r)); - r->CollectReports(cb, nullptr); + r->CollectReports(doNothing, nullptr); } } diff --git a/xpcom/base/nsMemoryReporterManager.h b/xpcom/base/nsMemoryReporterManager.h index af46957a43a..f2107ceef7a 100644 --- a/xpcom/base/nsMemoryReporterManager.h +++ b/xpcom/base/nsMemoryReporterManager.h @@ -11,6 +11,14 @@ using mozilla::Mutex; +class nsITimer; + +namespace mozilla { +namespace dom { +class MemoryReport; +} +} + class nsMemoryReporterManager : public nsIMemoryReporterManager { public: @@ -20,6 +28,93 @@ public: nsMemoryReporterManager(); virtual ~nsMemoryReporterManager(); + // Gets the memory reporter manager service. + static nsMemoryReporterManager* GetOrCreate() + { + nsCOMPtr imgr = + do_GetService("@mozilla.org/memory-reporter-manager;1"); + return static_cast(imgr.get()); + } + + void IncrementNumChildProcesses(); + void DecrementNumChildProcesses(); + + // Inter-process memory reporting proceeds as follows. + // + // - GetReports() (declared within NS_DECL_NSIMEMORYREPORTERMANAGER) + // synchronously gets memory reports for the current process, tells all + // child processes to get memory reports, and sets up some state + // (mGetReportsState) for when the child processes report back, including a + // timer. Control then returns to the main event loop. + // + // - HandleChildReports() is called (asynchronously) once per child process + // that reports back. If all child processes report back before time-out, + // the timer is cancelled. (The number of child processes is part of the + // saved request state.) + // + // - TimeoutCallback() is called (asynchronously) if all the child processes + // don't respond within the time threshold. + // + // - FinishReporting() finishes things off. It is *always* called -- either + // from HandleChildReports() (if all child processes have reported back) or + // from TimeoutCallback() (if time-out occurs). + // + // All operations occur on the main thread. + // + // The above sequence of steps is a "request". A partially-completed request + // is described as "in flight". + // + // Each request has a "generation", a unique number that identifies it. This + // is used to ensure that each reports from a child process corresponds to + // the appropriate request from the parent process. (It's easier to + // implement a generation system than to implement a child report request + // cancellation mechanism.) + // + // Failures are mostly ignored, because it's (a) typically the most sensible + // thing to do, and (b) often hard to do anything else. The following are + // the failure cases of note. + // + // - If a request is made while the previous request is in flight, the new + // request is ignored, as per getReports()'s specification. No error is + // reported, because the previous request will complete soon enough. + // + // - If one or more child processes fail to respond within the time limit, + // things will proceed as if they don't exist. No error is reported, + // because partial information is better than nothing. + // + // - If a child process reports after the time-out occurs, it is ignored. + // (Generation checking will ensure it is ignored even if a subsequent + // request is in flight; this is the main use of generations.) No error + // is reported, because there's nothing sensible to be done about it at + // this late stage. + // + // Now, what what happens if a child process is created/destroyed in the + // middle of a request? Well, GetReportsState contains a copy of + // mNumChildProcesses which it uses to determine finished-ness. So... + // + // - If a process is created, it won't have received the request for reports, + // and the GetReportsState's mNumChildProcesses won't account for it. So + // the reported data will reflect how things were when the request began. + // + // - If a process is destroyed before reporting back, we'll just hit the + // time-out, because we'll have received reports (barring other errors) + // from N-1 child process. So the reported data will reflect how things + // are when the request ends. + // + // - If a process is destroyed after reporting back, but before all other + // child processes have reported back, it will be included in the reported + // data. So the reported data will reflect how things were when the + // request began. + // + // The inconsistencies between these three cases are unfortunate but + // difficult to avoid. It's enough of an edge case to not be worth doing + // more. + // + void HandleChildReports( + const uint32_t& generation, + const InfallibleTArray& aChildReports); + void FinishReporting(); + // Functions that (a) implement distinguished amounts, and (b) are outside of // this module. struct AmountFns { @@ -36,6 +131,8 @@ public: mozilla::InfallibleAmountFn mLowMemoryEventsPhysical; mozilla::InfallibleAmountFn mGhostWindows; + + AmountFns() { mozilla::PodZero(this); } }; AmountFns mAmountFns; @@ -43,15 +140,55 @@ public: struct SizeOfTabFns { mozilla::JSSizeOfTabFn mJS; mozilla::NonJSSizeOfTabFn mNonJS; + + SizeOfTabFns() { mozilla::PodZero(this); } }; SizeOfTabFns mSizeOfTabFns; private: - nsresult RegisterReporterHelper(nsIMemoryReporter *aReporter, bool aForce); + nsresult RegisterReporterHelper(nsIMemoryReporter* aReporter, bool aForce); + + static void TimeoutCallback(nsITimer* aTimer, void* aData); + static const uint32_t kTimeoutLengthMS = 5000; nsTHashtable mReporters; Mutex mMutex; bool mIsRegistrationBlocked; + + uint32_t mNumChildProcesses; + uint32_t mNextGeneration; + + struct GetReportsState { + uint32_t mGeneration; + nsCOMPtr mTimer; + uint32_t mNumChildProcesses; + uint32_t mNumChildProcessesCompleted; + nsCOMPtr mHandleReport; + nsCOMPtr mHandleReportData; + nsCOMPtr mFinishReporting; + nsCOMPtr mFinishReportingData; + + GetReportsState(uint32_t aGeneration, nsITimer* aTimer, + uint32_t aNumChildProcesses, + nsIHandleReportCallback* aHandleReport, + nsISupports* aHandleReportData, + nsIFinishReportingCallback* aFinishReporting, + nsISupports* aFinishReportingData) + : mGeneration(aGeneration), + mTimer(aTimer), + mNumChildProcesses(aNumChildProcesses), + mNumChildProcessesCompleted(0), + mHandleReport(aHandleReport), + mHandleReportData(aHandleReportData), + mFinishReporting(aFinishReporting), + mFinishReportingData(aFinishReportingData) + {} + }; + + // When this is non-null, a request is in flight. Note: We use manual + // new/delete for this because its lifetime doesn't match block scope or + // anything like that. + GetReportsState* mGetReportsState; }; #define NS_MEMORY_REPORTER_MANAGER_CID \ diff --git a/xpcom/ds/nsObserverService.cpp b/xpcom/ds/nsObserverService.cpp index d233be2bd0a..b62b5d18853 100644 --- a/xpcom/ds/nsObserverService.cpp +++ b/xpcom/ds/nsObserverService.cpp @@ -42,26 +42,22 @@ GetObserverServiceLog() namespace mozilla { -class ObserverServiceReporter MOZ_FINAL : public nsIMemoryReporter +class ObserverServiceReporter MOZ_FINAL : public MemoryMultiReporter { public: - NS_DECL_ISUPPORTS - NS_DECL_NSIMEMORYREPORTER + ObserverServiceReporter() + : MemoryMultiReporter("observer-service") + {} + + NS_IMETHOD CollectReports(nsIMemoryReporterCallback *aCb, + nsISupports *aClosure); + protected: static const size_t kSuspectReferentCount = 100; static PLDHashOperator CountReferents(nsObserverList* aObserverList, void* aClosure); }; -NS_IMPL_ISUPPORTS1(ObserverServiceReporter, nsIMemoryReporter) - -NS_IMETHODIMP -ObserverServiceReporter::GetName(nsACString& aName) -{ - aName.AssignLiteral("observer-service"); - return NS_OK; -} - struct SuspectObserver { SuspectObserver(const char* aTopic, size_t aReferentCount) : topic(aTopic), referentCount(aReferentCount) {}