mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 21:01:08 +00:00
Backed out 5 changesets (bug 1330185, bug 1330184) for leaking an nsTArray_base from the plugin process on Win8
Backed out changeset e6f368f2d874 (bug 1330185) Backed out changeset 2b8d50fcb20f (bug 1330184) Backed out changeset dbe452a9eebb (bug 1330184) Backed out changeset e13b9e798e16 (bug 1330184) Backed out changeset 52489c7eadaf (bug 1330184) MozReview-Commit-ID: 8L20BZ5E3t2
This commit is contained in:
parent
e6e35bafa1
commit
6368ef89e2
@ -74,10 +74,6 @@
|
||||
#include "imgLoader.h"
|
||||
#include "GMPServiceChild.h"
|
||||
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
#include "ChildProfilerController.h"
|
||||
#endif
|
||||
|
||||
#if defined(MOZ_CONTENT_SANDBOX)
|
||||
#if defined(XP_WIN)
|
||||
#define TARGET_SANDBOX_EXPORTS
|
||||
@ -1054,11 +1050,6 @@ ContentChild::InitXPCOM(const XPCOMInitData& aXPCOMInit,
|
||||
nsCOMPtr<nsIURI> ucsURL = DeserializeURI(aXPCOMInit.userContentSheetURL());
|
||||
nsLayoutStylesheetCache::SetUserContentCSSURL(ucsURL);
|
||||
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
mProfilerController = new ChildProfilerController();
|
||||
Unused << SendInitProfiler(mProfilerController->SetUpEndpoints(OtherPid()));
|
||||
#endif
|
||||
|
||||
// This will register cross-process observer.
|
||||
mozilla::dom::time::InitializeDateCacheCleaner();
|
||||
|
||||
@ -2660,6 +2651,60 @@ ContentChild::DeallocPOfflineCacheUpdateChild(POfflineCacheUpdateChild* actor)
|
||||
return true;
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentChild::RecvStartProfiler(const ProfilerInitParams& params)
|
||||
{
|
||||
nsTArray<const char*> filterArray;
|
||||
for (size_t i = 0; i < params.filters().Length(); ++i) {
|
||||
filterArray.AppendElement(params.filters()[i].get());
|
||||
}
|
||||
|
||||
profiler_start(params.entries(), params.interval(), params.features(),
|
||||
filterArray.Elements(), filterArray.Length());
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentChild::RecvStopProfiler()
|
||||
{
|
||||
profiler_stop();
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentChild::RecvPauseProfiler(const bool& aPause)
|
||||
{
|
||||
if (aPause) {
|
||||
profiler_pause();
|
||||
} else {
|
||||
profiler_resume();
|
||||
}
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void
|
||||
ContentChild::GatherProfile(bool aIsExitProfile)
|
||||
{
|
||||
nsCString profileCString;
|
||||
UniquePtr<char[]> profile = profiler_get_profile();
|
||||
if (profile) {
|
||||
profileCString = nsCString(profile.get(), strlen(profile.get()));
|
||||
} else {
|
||||
profileCString = EmptyCString();
|
||||
}
|
||||
|
||||
Unused << SendProfile(profileCString, aIsExitProfile);
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentChild::RecvGatherProfile()
|
||||
{
|
||||
GatherProfile(false);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentChild::RecvLoadPluginResult(const uint32_t& aPluginId,
|
||||
const bool& aResult)
|
||||
@ -2826,12 +2871,11 @@ ContentChild::RecvShutdown()
|
||||
GetIPCChannel()->SetAbortOnError(false);
|
||||
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
if (mProfilerController) {
|
||||
nsCString shutdownProfile = mProfilerController->GrabShutdownProfileAndShutdown();
|
||||
mProfilerController = nullptr;
|
||||
// Send the shutdown profile to the parent process through our own
|
||||
// message channel, which we know will survive for long enough.
|
||||
Unused << SendShutdownProfile(shutdownProfile);
|
||||
if (profiler_is_active()) {
|
||||
// We're shutting down while we were profiling. Send the
|
||||
// profile up to the parent so that we don't lose this
|
||||
// information.
|
||||
GatherProfile(true);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -35,7 +35,6 @@ struct LookAndFeelInt;
|
||||
|
||||
namespace mozilla {
|
||||
class RemoteSpellcheckEngineChild;
|
||||
class ChildProfilerController;
|
||||
|
||||
using mozilla::loader::PScriptCacheChild;
|
||||
|
||||
@ -453,6 +452,14 @@ public:
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvUpdateWindow(const uintptr_t& aChildId) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvStartProfiler(const ProfilerInitParams& params) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvPauseProfiler(const bool& aPause) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvStopProfiler() override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvGatherProfile() override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvDomainSetChanged(const uint32_t& aSetType,
|
||||
const uint32_t& aChangeType,
|
||||
const OptionalURIParams& aDomain) override;
|
||||
@ -685,6 +692,8 @@ private:
|
||||
virtual already_AddRefed<nsIEventTarget>
|
||||
GetConstructedEventTarget(const Message& aMsg) override;
|
||||
|
||||
void GatherProfile(bool aIsExitProfile);
|
||||
|
||||
InfallibleTArray<nsAutoPtr<AlertObserver> > mAlertObservers;
|
||||
RefPtr<ConsoleListener> mConsoleListener;
|
||||
|
||||
@ -729,10 +738,6 @@ private:
|
||||
nsCOMPtr<nsIDomainPolicy> mPolicy;
|
||||
nsCOMPtr<nsITimer> mForceKillTimer;
|
||||
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
RefPtr<ChildProfilerController> mProfilerController;
|
||||
#endif
|
||||
|
||||
#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
|
||||
nsCOMPtr<nsIFile> mProfileDir;
|
||||
#endif
|
||||
|
@ -24,6 +24,9 @@
|
||||
#include "chrome/common/process_watcher.h"
|
||||
|
||||
#include "mozilla/a11y/PDocAccessible.h"
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
#include "CrossProcessProfilerController.h"
|
||||
#endif
|
||||
#include "GeckoProfiler.h"
|
||||
#include "GMPServiceParent.h"
|
||||
#include "HandlerServiceParent.h"
|
||||
@ -185,7 +188,6 @@
|
||||
#include "nsHostObjectProtocolHandler.h"
|
||||
#include "nsICaptivePortalService.h"
|
||||
#include "nsIObjectLoadingContent.h"
|
||||
#include "ProfilerParent.h"
|
||||
|
||||
#include "nsIBidiKeyboard.h"
|
||||
|
||||
@ -253,10 +255,6 @@
|
||||
#include "nsAccessibilityService.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
#include "nsIProfiler.h"
|
||||
#endif
|
||||
|
||||
// For VP9Benchmark::sBenchmarkFpsPref
|
||||
#include "Benchmark.h"
|
||||
|
||||
@ -1069,6 +1067,38 @@ ContentParent::RecvRemovePermission(const IPC::Principal& aPrincipal,
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void
|
||||
ContentParent::SendStartProfiler(const ProfilerInitParams& aParams)
|
||||
{
|
||||
if (mSubprocess && mIsAlive) {
|
||||
Unused << PContentParent::SendStartProfiler(aParams);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ContentParent::SendStopProfiler()
|
||||
{
|
||||
if (mSubprocess && mIsAlive) {
|
||||
Unused << PContentParent::SendStopProfiler();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ContentParent::SendPauseProfiler(const bool& aPause)
|
||||
{
|
||||
if (mSubprocess && mIsAlive) {
|
||||
Unused << PContentParent::SendPauseProfiler(aPause);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ContentParent::SendGatherProfile()
|
||||
{
|
||||
if (mSubprocess && mIsAlive) {
|
||||
Unused << PContentParent::SendGatherProfile();
|
||||
}
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentParent::RecvConnectPluginBridge(const uint32_t& aPluginId,
|
||||
nsresult* aRv,
|
||||
@ -1322,6 +1352,10 @@ ContentParent::Init()
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
mProfilerController = MakeUnique<CrossProcessProfilerController>(this);
|
||||
#endif
|
||||
|
||||
// Ensure that the default set of permissions are avaliable in the content
|
||||
// process before we try to load any URIs in it.
|
||||
EnsurePermissionsByKey(EmptyCString());
|
||||
@ -1716,6 +1750,10 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
|
||||
|
||||
mConsoleService = nullptr;
|
||||
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
mProfilerController = nullptr;
|
||||
#endif
|
||||
|
||||
if (obs) {
|
||||
RefPtr<nsHashPropertyBag> props = new nsHashPropertyBag();
|
||||
|
||||
@ -2754,15 +2792,6 @@ ContentParent::RecvInitBackground(Endpoint<PBackgroundParent>&& aEndpoint)
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentParent::RecvInitProfiler(Endpoint<PProfilerParent>&& aEndpoint)
|
||||
{
|
||||
if (!ProfilerParent::Alloc(Move(aEndpoint))) {
|
||||
NS_WARNING("ProfilerParent::Alloc failed");
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::jsipc::PJavaScriptParent *
|
||||
ContentParent::AllocPJavaScriptParent()
|
||||
{
|
||||
@ -4669,11 +4698,12 @@ ContentParent::RecvCreateWindowInDifferentProcess(
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentParent::RecvShutdownProfile(const nsCString& aProfile)
|
||||
ContentParent::RecvProfile(const nsCString& aProfile, const bool& aIsExitProfile)
|
||||
{
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
nsCOMPtr<nsIProfiler> profiler(do_GetService("@mozilla.org/tools/profiler;1"));
|
||||
profiler->ReceiveShutdownProfile(aProfile);
|
||||
if (mProfilerController) {
|
||||
mProfilerController->RecvProfile(aProfile, aIsExitProfile);
|
||||
}
|
||||
#endif
|
||||
return IPC_OK();
|
||||
}
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "nsIDOMGeoPositionErrorCallback.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "PermissionMessageUtils.h"
|
||||
#include "ProfilerControllingProcess.h"
|
||||
#include "DriverCrashGuard.h"
|
||||
|
||||
#define CHILD_PROCESS_SHUTDOWN_MESSAGE NS_LITERAL_STRING("child-process-shutdown")
|
||||
@ -55,6 +56,9 @@ class nsIWidget;
|
||||
|
||||
namespace mozilla {
|
||||
class PRemoteSpellcheckEngineParent;
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
class CrossProcessProfilerController;
|
||||
#endif
|
||||
|
||||
#if defined(XP_LINUX) && defined(MOZ_CONTENT_SANDBOX)
|
||||
class SandboxBroker;
|
||||
@ -110,6 +114,7 @@ class ContentParent final : public PContentParent
|
||||
, public mozilla::LinkedListElement<ContentParent>
|
||||
, public gfx::GPUProcessListener
|
||||
, public mozilla::MemoryReportingProcess
|
||||
, public mozilla::ProfilerControllingProcess
|
||||
{
|
||||
typedef mozilla::ipc::GeckoChildProcessHost GeckoChildProcessHost;
|
||||
typedef mozilla::ipc::OptionalURIParams OptionalURIParams;
|
||||
@ -307,6 +312,11 @@ public:
|
||||
const nsCString& aPermissionType,
|
||||
nsresult* aRv) override;
|
||||
|
||||
void SendStartProfiler(const ProfilerInitParams& aParams) override;
|
||||
void SendStopProfiler() override;
|
||||
void SendPauseProfiler(const bool& aPause) override;
|
||||
void SendGatherProfile() override;
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(ContentParent, nsIObserver)
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
@ -815,7 +825,6 @@ private:
|
||||
static nsTArray<ContentParent*>& GetOrCreatePool(const nsAString& aContentProcessType);
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvInitBackground(Endpoint<mozilla::ipc::PBackgroundParent>&& aEndpoint) override;
|
||||
virtual mozilla::ipc::IPCResult RecvInitProfiler(Endpoint<mozilla::PProfilerParent>&& aEndpoint) override;
|
||||
|
||||
mozilla::ipc::IPCResult RecvAddMemoryReport(const MemoryReport& aReport) override;
|
||||
mozilla::ipc::IPCResult RecvFinishMemoryReport(const uint32_t& aGeneration) override;
|
||||
@ -1122,7 +1131,8 @@ private:
|
||||
virtual mozilla::ipc::IPCResult RecvUpdateDropEffect(const uint32_t& aDragAction,
|
||||
const uint32_t& aDropEffect) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvShutdownProfile(const nsCString& aProfile) override;
|
||||
virtual mozilla::ipc::IPCResult RecvProfile(const nsCString& aProfile,
|
||||
const bool& aIsExitProfile) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvGetGraphicsDeviceInitData(ContentDeviceData* aOut) override;
|
||||
|
||||
@ -1239,6 +1249,10 @@ private:
|
||||
|
||||
PProcessHangMonitorParent* mHangMonitorActor;
|
||||
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
UniquePtr<mozilla::CrossProcessProfilerController> mProfilerController;
|
||||
#endif
|
||||
|
||||
UniquePtr<gfx::DriverCrashGuard> mDriverCrashGuard;
|
||||
UniquePtr<MemoryReportRequestHost> mMemoryReportRequest;
|
||||
|
||||
|
@ -45,7 +45,6 @@ include protocol PURLClassifierLocal;
|
||||
include protocol PVRManager;
|
||||
include protocol PVideoDecoderManager;
|
||||
include protocol PFlyWebPublishedServer;
|
||||
include protocol PProfiler;
|
||||
include protocol PScriptCache;
|
||||
include DOMTypes;
|
||||
include JavaScriptTypes;
|
||||
@ -59,6 +58,7 @@ include PBackgroundSharedTypes;
|
||||
include PContentPermission;
|
||||
include ServiceWorkerConfiguration;
|
||||
include GraphicsMessages;
|
||||
include ProfilerTypes;
|
||||
include MemoryReportTypes;
|
||||
|
||||
// Workaround to prevent error if PContentChild.cpp & PContentBridgeParent.cpp
|
||||
@ -511,6 +511,15 @@ child:
|
||||
*/
|
||||
async LoadPluginResult(uint32_t aPluginId, bool aResult);
|
||||
|
||||
/**
|
||||
* Control the Gecko Profiler in the child process.
|
||||
*/
|
||||
async StartProfiler(ProfilerInitParams params);
|
||||
async StopProfiler();
|
||||
async PauseProfiler(bool aPause);
|
||||
|
||||
async GatherProfile();
|
||||
|
||||
async InvokeDragSession(IPCDataTransfer[] transfers, uint32_t action);
|
||||
|
||||
async EndDragSession(bool aDoneDrag, bool aUserCancelled,
|
||||
@ -620,7 +629,6 @@ child:
|
||||
|
||||
parent:
|
||||
async InitBackground(Endpoint<PBackgroundParent> aEndpoint);
|
||||
async InitProfiler(Endpoint<PProfilerParent> aEndpoint);
|
||||
|
||||
sync CreateChildProcess(IPCTabContext context,
|
||||
ProcessPriority priority,
|
||||
@ -987,7 +995,7 @@ parent:
|
||||
async PContentPermissionRequest(PermissionRequest[] aRequests, Principal aPrincipal,
|
||||
TabId tabId);
|
||||
|
||||
async ShutdownProfile(nsCString aProfile);
|
||||
async Profile(nsCString aProfile, bool aIsExitProfile);
|
||||
|
||||
/**
|
||||
* Request graphics initialization information from the parent.
|
||||
|
@ -6,7 +6,7 @@
|
||||
include protocol PPluginInstance;
|
||||
include protocol PPluginScriptableObject;
|
||||
include protocol PContent;
|
||||
include protocol PProfiler;
|
||||
include ProfilerTypes;
|
||||
|
||||
using NPError from "npapi.h";
|
||||
using NPNVariable from "npapi.h";
|
||||
@ -95,6 +95,14 @@ child:
|
||||
intr InitCrashReporter(Shmem shmem)
|
||||
returns (NativeThreadId tid);
|
||||
|
||||
/**
|
||||
* Control the Gecko Profiler in the plugin process.
|
||||
*/
|
||||
async StartProfiler(ProfilerInitParams params);
|
||||
async StopProfiler();
|
||||
async PauseProfiler(bool aPause);
|
||||
async GatherProfile();
|
||||
|
||||
async SettingChanged(PluginSettings settings);
|
||||
|
||||
async NPP_SetValue_NPNVaudioDeviceChangeDetails(NPAudioDeviceChangeDetailsIPC changeDetails);
|
||||
@ -104,8 +112,6 @@ child:
|
||||
parent:
|
||||
async NP_InitializeResult(NPError aError);
|
||||
|
||||
async InitProfiler(Endpoint<PProfilerParent> aEndPoint);
|
||||
|
||||
/**
|
||||
* This message is only used on X11 platforms.
|
||||
*
|
||||
@ -147,6 +153,8 @@ parent:
|
||||
// down the plugin process in response.
|
||||
async NotifyContentModuleDestroyed();
|
||||
|
||||
async Profile(nsCString aProfile, bool aIsExitProfile);
|
||||
|
||||
// Answers to request about site data
|
||||
async ReturnClearSiteData(NPError aRv, uint64_t aCallbackId);
|
||||
|
||||
|
@ -53,9 +53,7 @@
|
||||
#include "mozilla/ipc/CrashReporterClient.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
#include "ChildProfilerController.h"
|
||||
#endif
|
||||
#include "GeckoProfiler.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::ipc;
|
||||
@ -286,11 +284,6 @@ PluginModuleChild::InitForChrome(const std::string& aPluginFilename,
|
||||
|
||||
GetIPCChannel()->SetAbortOnError(true);
|
||||
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
mProfilerController = new ChildProfilerController();
|
||||
Unused << SendInitProfiler(mProfilerController->SetUpEndpoints(OtherPid()));
|
||||
#endif
|
||||
|
||||
// TODO: use PluginPRLibrary here
|
||||
|
||||
#if defined(OS_LINUX) || defined(OS_BSD) || defined(OS_SOLARIS)
|
||||
@ -753,13 +746,6 @@ PluginModuleChild::AnswerInitCrashReporter(Shmem&& aShmem, mozilla::dom::NativeT
|
||||
void
|
||||
PluginModuleChild::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
if (mProfilerController) {
|
||||
mProfilerController->Shutdown();
|
||||
mProfilerController = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!mIsChrome) {
|
||||
PluginModuleChild* chromeInstance = PluginModuleChild::GetChrome();
|
||||
if (chromeInstance) {
|
||||
@ -2679,6 +2665,54 @@ PluginModuleChild::ProcessNativeEvents() {
|
||||
}
|
||||
#endif
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
PluginModuleChild::RecvStartProfiler(const ProfilerInitParams& params)
|
||||
{
|
||||
nsTArray<const char*> filterArray;
|
||||
for (size_t i = 0; i < params.filters().Length(); ++i) {
|
||||
filterArray.AppendElement(params.filters()[i].get());
|
||||
}
|
||||
|
||||
profiler_start(params.entries(), params.interval(), params.features(),
|
||||
filterArray.Elements(), filterArray.Length());
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
PluginModuleChild::RecvStopProfiler()
|
||||
{
|
||||
profiler_stop();
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
PluginModuleChild::RecvPauseProfiler(const bool& aPause)
|
||||
{
|
||||
if (aPause) {
|
||||
profiler_pause();
|
||||
} else {
|
||||
profiler_resume();
|
||||
}
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
PluginModuleChild::RecvGatherProfile()
|
||||
{
|
||||
nsCString profileCString;
|
||||
UniquePtr<char[]> profile = profiler_get_profile();
|
||||
if (profile != nullptr) {
|
||||
profileCString = nsCString(profile.get(), strlen(profile.get()));
|
||||
} else {
|
||||
profileCString = nsCString("", 0);
|
||||
}
|
||||
|
||||
Unused << SendProfile(profileCString, false);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
NPError
|
||||
PluginModuleChild::PluginRequiresAudioDeviceChanges(
|
||||
PluginInstanceChild* aInstance,
|
||||
|
@ -46,9 +46,6 @@ typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_PLUGINUNIXINIT) (const NPNetscapeFun
|
||||
typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_PLUGINSHUTDOWN) (void);
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ChildProfilerController;
|
||||
|
||||
namespace plugins {
|
||||
|
||||
class PluginInstanceChild;
|
||||
@ -128,6 +125,11 @@ protected:
|
||||
virtual mozilla::ipc::IPCResult
|
||||
RecvProcessNativeEventsInInterruptCall() override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvStartProfiler(const ProfilerInitParams& params) override;
|
||||
virtual mozilla::ipc::IPCResult RecvStopProfiler() override;
|
||||
virtual mozilla::ipc::IPCResult RecvPauseProfiler(const bool& aPause) override;
|
||||
virtual mozilla::ipc::IPCResult RecvGatherProfile() override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult
|
||||
AnswerModuleSupportsAsyncRender(bool* aResult) override;
|
||||
public:
|
||||
@ -253,10 +255,6 @@ private:
|
||||
bool mIsChrome;
|
||||
bool mHasShutdown; // true if NP_Shutdown has run
|
||||
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
RefPtr<ChildProfilerController> mProfilerController;
|
||||
#endif
|
||||
|
||||
// we get this from the plugin
|
||||
NP_PLUGINSHUTDOWN mShutdownFunc;
|
||||
#if defined(OS_LINUX) || defined(OS_BSD) || defined(OS_SOLARIS)
|
||||
|
@ -33,8 +33,10 @@
|
||||
#include "prclist.h"
|
||||
#include "PluginQuirks.h"
|
||||
#include "gfxPlatform.h"
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
#include "CrossProcessProfilerController.h"
|
||||
#endif
|
||||
#include "GeckoProfiler.h"
|
||||
#include "ProfilerParent.h"
|
||||
#include "nsPluginTags.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "mozilla/layers/TextureClientRecycleAllocator.h"
|
||||
@ -56,6 +58,9 @@
|
||||
using base::KillProcess;
|
||||
|
||||
using mozilla::PluginLibrary;
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
using mozilla::CrossProcessProfilerController;
|
||||
#endif
|
||||
using mozilla::ipc::MessageChannel;
|
||||
using mozilla::ipc::GeckoChildProcessHost;
|
||||
|
||||
@ -631,6 +636,10 @@ PluginModuleChromeParent::OnProcessLaunched(const bool aSucceeded)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
mProfilerController = MakeUnique<CrossProcessProfilerController>(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
@ -770,6 +779,10 @@ PluginModuleChromeParent::~PluginModuleChromeParent()
|
||||
MOZ_CRASH("unsafe destruction");
|
||||
}
|
||||
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
mProfilerController = nullptr;
|
||||
#endif
|
||||
|
||||
#ifdef XP_WIN
|
||||
// If we registered for audio notifications, stop.
|
||||
mozilla::plugins::PluginUtilsWin::RegisterForAudioDeviceChanges(this,
|
||||
@ -3120,15 +3133,6 @@ PluginModuleParent::RecvReturnSitesWithData(nsTArray<nsCString>&& aSites,
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
PluginModuleParent::RecvInitProfiler(Endpoint<PProfilerParent>&& aEndpoint)
|
||||
{
|
||||
if (!ProfilerParent::Alloc(Move(aEndpoint))) {
|
||||
NS_WARNING("ProfilerParent::Alloc failed");
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
layers::TextureClientRecycleAllocator*
|
||||
PluginModuleParent::EnsureTextureAllocatorForDirectBitmap()
|
||||
{
|
||||
@ -3259,6 +3263,18 @@ PluginModuleChromeParent::OnCrash(DWORD processID)
|
||||
|
||||
#endif // MOZ_CRASHREPORTER_INJECTOR
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
PluginModuleChromeParent::RecvProfile(const nsCString& aProfile,
|
||||
const bool& aIsExitProfile)
|
||||
{
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
if (mProfilerController) {
|
||||
mProfilerController->RecvProfile(aProfile, aIsExitProfile);
|
||||
}
|
||||
#endif
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
PluginModuleParent::AnswerGetKeyState(const int32_t& aVirtKey, int16_t* aRet)
|
||||
{
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "sandboxPermissions.h"
|
||||
#endif
|
||||
#endif
|
||||
#include "ProfilerControllingProcess.h"
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
#include "nsExceptionHandler.h"
|
||||
@ -38,6 +39,11 @@ class nsPluginTag;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
class CrossProcessProfilerController;
|
||||
#endif
|
||||
|
||||
|
||||
namespace ipc {
|
||||
class CrashReporterHost;
|
||||
} // namespace ipc
|
||||
@ -79,6 +85,7 @@ class FinishInjectorInitTask;
|
||||
class PluginModuleParent
|
||||
: public PPluginModuleParent
|
||||
, public PluginLibrary
|
||||
, public mozilla::ProfilerControllingProcess
|
||||
#ifdef MOZ_CRASHREPORTER_INJECTOR
|
||||
, public CrashReporter::InjectorCrashCallback
|
||||
#endif
|
||||
@ -140,6 +147,23 @@ public:
|
||||
|
||||
int GetQuirks() { return mQuirks; }
|
||||
|
||||
void SendStartProfiler(const ProfilerInitParams& aParams) override
|
||||
{
|
||||
Unused << PPluginModuleParent::SendStartProfiler(aParams);
|
||||
}
|
||||
void SendStopProfiler() override
|
||||
{
|
||||
Unused << PPluginModuleParent::SendStopProfiler();
|
||||
}
|
||||
void SendPauseProfiler(const bool& aPause) override
|
||||
{
|
||||
Unused << PPluginModuleParent::SendPauseProfiler(aPause);
|
||||
}
|
||||
void SendGatherProfile() override
|
||||
{
|
||||
Unused << PPluginModuleParent::SendGatherProfile();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual mozilla::ipc::RacyInterruptPolicy
|
||||
MediateInterruptRace(const MessageInfo& parent,
|
||||
@ -209,6 +233,8 @@ protected:
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvNotifyContentModuleDestroyed() override { return IPC_OK(); }
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvProfile(const nsCString& aProfile, const bool& aIsExitProfile) override { return IPC_OK(); }
|
||||
|
||||
virtual mozilla::ipc::IPCResult AnswerGetKeyState(const int32_t& aVirtKey, int16_t* aRet) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvReturnClearSiteData(const NPError& aRv,
|
||||
@ -217,8 +243,6 @@ protected:
|
||||
virtual mozilla::ipc::IPCResult RecvReturnSitesWithData(nsTArray<nsCString>&& aSites,
|
||||
const uint64_t& aCallbackId) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvInitProfiler(Endpoint<mozilla::PProfilerParent>&& aEndpoint) override;
|
||||
|
||||
void SetPluginFuncs(NPPluginFuncs* aFuncs);
|
||||
|
||||
nsresult NPP_NewInternal(NPMIMEType pluginType, NPP instance,
|
||||
@ -502,6 +526,9 @@ class PluginModuleChromeParent
|
||||
|
||||
void CachedSettingChanged();
|
||||
|
||||
virtual mozilla::ipc::IPCResult
|
||||
RecvProfile(const nsCString& aProfile, const bool& aIsExitProfile) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult
|
||||
AnswerGetKeyState(const int32_t& aVirtKey, int16_t* aRet) override;
|
||||
|
||||
@ -653,6 +680,9 @@ private:
|
||||
// processes in existence!
|
||||
dom::ContentParent* mContentParent;
|
||||
nsCOMPtr<nsIObserver> mPluginOfflineObserver;
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
UniquePtr<CrossProcessProfilerController> mProfilerController;
|
||||
#endif
|
||||
bool mIsBlocklisted;
|
||||
static bool sInstantiated;
|
||||
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
|
@ -20,7 +20,9 @@
|
||||
#include "mozilla/ipc/CrashReporterHost.h"
|
||||
#include "mozilla/layers/LayerTreeOwnerTracker.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "ProfilerParent.h"
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
#include "CrossProcessProfilerController.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
@ -74,6 +76,10 @@ GPUChild::Init()
|
||||
SendInit(prefs, updates, devicePrefs, mappings);
|
||||
|
||||
gfxVars::AddReceiver(this);
|
||||
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
mProfilerController = MakeUnique<CrossProcessProfilerController>(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
@ -199,6 +205,17 @@ GPUChild::RecvNotifyDeviceReset(const GPUDeviceData& aData)
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
GPUChild::RecvProfile(const nsCString& aProfile, const bool& aIsExitProfile)
|
||||
{
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
if (mProfilerController) {
|
||||
mProfilerController->RecvProfile(aProfile, aIsExitProfile);
|
||||
}
|
||||
#endif
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
bool
|
||||
GPUChild::SendRequestMemoryReport(const uint32_t& aGeneration,
|
||||
const bool& aAnonymize,
|
||||
@ -214,16 +231,6 @@ GPUChild::SendRequestMemoryReport(const uint32_t& aGeneration,
|
||||
return true;
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
GPUChild::RecvInitProfiler(Endpoint<PProfilerParent>&& aEndpoint)
|
||||
{
|
||||
if (!ProfilerParent::Alloc(Move(aEndpoint))) {
|
||||
return IPC_FAIL(this, "ProfilerParent::Alloc failed");
|
||||
}
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
GPUChild::RecvAddMemoryReport(const MemoryReport& aReport)
|
||||
{
|
||||
@ -243,6 +250,30 @@ GPUChild::RecvFinishMemoryReport(const uint32_t& aGeneration)
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void
|
||||
GPUChild::SendStartProfiler(const ProfilerInitParams& aParams)
|
||||
{
|
||||
Unused << PGPUChild::SendStartProfiler(aParams);
|
||||
}
|
||||
|
||||
void
|
||||
GPUChild::SendStopProfiler()
|
||||
{
|
||||
Unused << PGPUChild::SendStopProfiler();
|
||||
}
|
||||
|
||||
void
|
||||
GPUChild::SendPauseProfiler(const bool& aPause)
|
||||
{
|
||||
Unused << PGPUChild::SendPauseProfiler(aPause);
|
||||
}
|
||||
|
||||
void
|
||||
GPUChild::SendGatherProfile()
|
||||
{
|
||||
Unused << PGPUChild::SendGatherProfile();
|
||||
}
|
||||
|
||||
void
|
||||
GPUChild::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
@ -264,6 +295,10 @@ GPUChild::ActorDestroy(ActorDestroyReason aWhy)
|
||||
|
||||
}
|
||||
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
mProfilerController = nullptr;
|
||||
#endif
|
||||
|
||||
gfxVars::RemoveReceiver(this);
|
||||
mHost->OnChannelClosed();
|
||||
}
|
||||
|
@ -10,9 +10,14 @@
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/gfx/PGPUChild.h"
|
||||
#include "mozilla/gfx/gfxVarReceiver.h"
|
||||
#include "ProfilerControllingProcess.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
class CrossProcessProfilerController;
|
||||
#endif
|
||||
|
||||
namespace ipc {
|
||||
class CrashReporterHost;
|
||||
} // namespace ipc
|
||||
@ -26,6 +31,7 @@ class GPUProcessHost;
|
||||
class GPUChild final
|
||||
: public PGPUChild
|
||||
, public gfxVarReceiver
|
||||
, public ProfilerControllingProcess
|
||||
{
|
||||
typedef mozilla::dom::MemoryReportRequestHost MemoryReportRequestHost;
|
||||
|
||||
@ -55,10 +61,15 @@ public:
|
||||
mozilla::ipc::IPCResult RecvGraphicsError(const nsCString& aError) override;
|
||||
mozilla::ipc::IPCResult RecvNotifyUiObservers(const nsCString& aTopic) override;
|
||||
mozilla::ipc::IPCResult RecvNotifyDeviceReset(const GPUDeviceData& aData) override;
|
||||
mozilla::ipc::IPCResult RecvInitProfiler(Endpoint<mozilla::PProfilerParent>&& aEndpoint) override;
|
||||
mozilla::ipc::IPCResult RecvProfile(const nsCString& aProfile, const bool& aIsExitProfile) override;
|
||||
mozilla::ipc::IPCResult RecvAddMemoryReport(const MemoryReport& aReport) override;
|
||||
mozilla::ipc::IPCResult RecvFinishMemoryReport(const uint32_t& aGeneration) override;
|
||||
|
||||
void SendStartProfiler(const ProfilerInitParams& aParams) override;
|
||||
void SendStopProfiler() override;
|
||||
void SendPauseProfiler(const bool& aPause) override;
|
||||
void SendGatherProfile() override;
|
||||
|
||||
bool SendRequestMemoryReport(const uint32_t& aGeneration,
|
||||
const bool& aAnonymize,
|
||||
const bool& aMinimizeMemoryUsage,
|
||||
@ -71,6 +82,9 @@ private:
|
||||
UniquePtr<ipc::CrashReporterHost> mCrashReporter;
|
||||
UniquePtr<MemoryReportRequestHost> mMemoryReportRequest;
|
||||
bool mGPUReady;
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
UniquePtr<CrossProcessProfilerController> mProfilerController;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "WMF.h"
|
||||
#endif
|
||||
#include "GPUParent.h"
|
||||
#include "GeckoProfiler.h"
|
||||
#include "gfxConfig.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "gfxPrefs.h"
|
||||
@ -44,9 +45,6 @@
|
||||
#ifdef MOZ_WIDGET_GTK
|
||||
# include <gtk/gtk.h>
|
||||
#endif
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
#include "ChildProfilerController.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
@ -118,10 +116,6 @@ GPUParent::Init(base::ProcessId aParentPid,
|
||||
mozilla::ipc::SetThisProcessName("GPU Process");
|
||||
#ifdef XP_WIN
|
||||
wmf::MFStartup();
|
||||
#endif
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
mProfilerController = new ChildProfilerController();
|
||||
Unused << SendInitProfiler(mProfilerController->SetUpEndpoints(OtherPid()));
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
@ -388,6 +382,51 @@ GPUParent::RecvNotifyGpuObservers(const nsCString& aTopic)
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
GPUParent::RecvStartProfiler(const ProfilerInitParams& params)
|
||||
{
|
||||
nsTArray<const char*> filterArray;
|
||||
for (size_t i = 0; i < params.filters().Length(); ++i) {
|
||||
filterArray.AppendElement(params.filters()[i].get());
|
||||
}
|
||||
profiler_start(params.entries(), params.interval(), params.features(),
|
||||
filterArray.Elements(), filterArray.Length());
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
GPUParent::RecvStopProfiler()
|
||||
{
|
||||
profiler_stop();
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
GPUParent::RecvPauseProfiler(const bool& aPause)
|
||||
{
|
||||
if (aPause) {
|
||||
profiler_pause();
|
||||
} else {
|
||||
profiler_resume();
|
||||
}
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
GPUParent::RecvGatherProfile()
|
||||
{
|
||||
nsCString profileCString;
|
||||
UniquePtr<char[]> profile = profiler_get_profile();
|
||||
if (profile) {
|
||||
profileCString = nsDependentCString(profile.get());
|
||||
}
|
||||
|
||||
Unused << SendProfile(profileCString, false /* aIsExitProfile */);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
GPUParent::RecvRequestMemoryReport(const uint32_t& aGeneration,
|
||||
const bool& aAnonymize,
|
||||
@ -419,13 +458,6 @@ GPUParent::ActorDestroy(ActorDestroyReason aWhy)
|
||||
ProcessChild::QuickExit();
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
if (mProfilerController) {
|
||||
mProfilerController->Shutdown();
|
||||
mProfilerController = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mVsyncBridge) {
|
||||
mVsyncBridge->Shutdown();
|
||||
mVsyncBridge = nullptr;
|
||||
|
@ -12,7 +12,6 @@
|
||||
namespace mozilla {
|
||||
|
||||
class TimeStamp;
|
||||
class ChildProfilerController;
|
||||
|
||||
namespace gfx {
|
||||
|
||||
@ -56,6 +55,10 @@ public:
|
||||
mozilla::ipc::IPCResult RecvAddLayerTreeIdMapping(const LayerTreeIdMapping& aMapping) override;
|
||||
mozilla::ipc::IPCResult RecvRemoveLayerTreeIdMapping(const LayerTreeIdMapping& aMapping) override;
|
||||
mozilla::ipc::IPCResult RecvNotifyGpuObservers(const nsCString& aTopic) override;
|
||||
mozilla::ipc::IPCResult RecvStartProfiler(const ProfilerInitParams& params) override;
|
||||
mozilla::ipc::IPCResult RecvPauseProfiler(const bool& aPause) override;
|
||||
mozilla::ipc::IPCResult RecvStopProfiler() override;
|
||||
mozilla::ipc::IPCResult RecvGatherProfile() override;
|
||||
mozilla::ipc::IPCResult RecvRequestMemoryReport(
|
||||
const uint32_t& generation,
|
||||
const bool& anonymize,
|
||||
@ -67,9 +70,6 @@ public:
|
||||
private:
|
||||
const TimeStamp mLaunchTime;
|
||||
RefPtr<VsyncBridgeParent> mVsyncBridge;
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
RefPtr<ChildProfilerController> mProfilerController;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
|
@ -4,10 +4,10 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
include GraphicsMessages;
|
||||
include ProfilerTypes;
|
||||
include MemoryReportTypes;
|
||||
include protocol PCompositorBridge;
|
||||
include protocol PImageBridge;
|
||||
include protocol PProfiler;
|
||||
include protocol PVRManager;
|
||||
include protocol PVsyncBridge;
|
||||
include protocol PUiCompositorController;
|
||||
@ -90,6 +90,12 @@ parent:
|
||||
// observer service.
|
||||
async NotifyGpuObservers(nsCString aTopic);
|
||||
|
||||
// Control the Gecko Profiler in the GPU process.
|
||||
async StartProfiler(ProfilerInitParams params);
|
||||
async StopProfiler();
|
||||
async PauseProfiler(bool aPause);
|
||||
async GatherProfile();
|
||||
|
||||
async RequestMemoryReport(uint32_t generation,
|
||||
bool anonymize,
|
||||
bool minimizeMemoryUsage,
|
||||
@ -100,9 +106,6 @@ child:
|
||||
// Init().
|
||||
async InitComplete(GPUDeviceData data);
|
||||
|
||||
// Sent to the UI process to register the GPU process's profiler.
|
||||
async InitProfiler(Endpoint<PProfilerParent> endpoint);
|
||||
|
||||
// Sent when APZ detects checkerboarding and apz checkerboard reporting is enabled.
|
||||
async ReportCheckerboard(uint32_t severity, nsCString log);
|
||||
|
||||
@ -124,6 +127,8 @@ child:
|
||||
|
||||
async NotifyDeviceReset(GPUDeviceData status);
|
||||
|
||||
// Called in response to GatherProfile.
|
||||
async Profile(nsCString aProfile, bool aIsExitProfile);
|
||||
async AddMemoryReport(MemoryReport aReport);
|
||||
async FinishMemoryReport(uint32_t aGeneration);
|
||||
};
|
||||
|
@ -265,6 +265,8 @@ SamplerThread::SamplerThread(PSLockRef aLock, uint32_t aActivityGeneration,
|
||||
// mSamplerTid to a dummy value and fill it in for real in ThreadEntry().
|
||||
, mSamplerTid(-1)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
|
||||
#if defined(USE_EHABI_STACKWALK)
|
||||
mozilla::EHABIStackWalkInit();
|
||||
#elif defined(USE_LUL_STACKWALK)
|
||||
@ -319,6 +321,8 @@ SamplerThread::~SamplerThread()
|
||||
void
|
||||
SamplerThread::Stop(PSLockRef aLock)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
|
||||
// Restore old signal handler. This is global state so it's important that
|
||||
// we do it now, while gPSMutex is locked. It's safe to do this now even
|
||||
// though this SamplerThread is still alive, because the next time the main
|
||||
|
@ -78,6 +78,8 @@ SamplerThread::SamplerThread(PSLockRef aLock, uint32_t aActivityGeneration,
|
||||
, mIntervalMicroseconds(
|
||||
std::max(1, int(floor(aIntervalMilliseconds * 1000 + 0.5))))
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
|
||||
pthread_attr_t* attr_ptr = nullptr;
|
||||
if (pthread_create(&mThread, attr_ptr, ThreadEntry, this) != 0) {
|
||||
MOZ_CRASH("pthread_create failed");
|
||||
@ -92,6 +94,7 @@ SamplerThread::~SamplerThread()
|
||||
void
|
||||
SamplerThread::Stop(PSLockRef aLock)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -95,6 +95,8 @@ SamplerThread::SamplerThread(PSLockRef aLock, uint32_t aActivityGeneration,
|
||||
, mIntervalMicroseconds(
|
||||
std::max(1, int(floor(aIntervalMilliseconds * 1000 + 0.5))))
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
|
||||
// By default we'll not adjust the timer resolution which tends to be
|
||||
// around 16ms. However, if the requested interval is sufficiently low
|
||||
// we'll try to adjust the resolution to match.
|
||||
@ -130,6 +132,8 @@ SamplerThread::~SamplerThread()
|
||||
void
|
||||
SamplerThread::Stop(PSLockRef aLock)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
|
||||
// Disable any timer resolution changes we've made. Do it now while
|
||||
// gPSMutex is locked, i.e. before any other SamplerThread can be created
|
||||
// and call ::timeBeginPeriod().
|
||||
|
@ -35,7 +35,6 @@
|
||||
#include "nsMemoryReporterManager.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "nsProfilerStartParams.h"
|
||||
#include "ProfilerParent.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "ProfilerMarkerPayload.h"
|
||||
@ -299,32 +298,16 @@ private:
|
||||
}
|
||||
|
||||
if (mInterposeObserver) {
|
||||
// We need to register the observer on the main thread, because we want
|
||||
// to observe IO that happens on the main thread.
|
||||
if (NS_IsMainThread()) {
|
||||
IOInterposer::Register(IOInterposeObserver::OpAll, mInterposeObserver);
|
||||
} else {
|
||||
RefPtr<ProfilerIOInterposeObserver> observer = mInterposeObserver;
|
||||
NS_DispatchToMainThread(NS_NewRunnableFunction([=]() {
|
||||
IOInterposer::Register(IOInterposeObserver::OpAll, observer);
|
||||
}));
|
||||
}
|
||||
mozilla::IOInterposer::Register(mozilla::IOInterposeObserver::OpAll,
|
||||
mInterposeObserver.get());
|
||||
}
|
||||
}
|
||||
|
||||
~ActivePS()
|
||||
{
|
||||
if (mInterposeObserver) {
|
||||
// We need to unregister the observer on the main thread, because that's
|
||||
// where we've registered it.
|
||||
if (NS_IsMainThread()) {
|
||||
IOInterposer::Unregister(IOInterposeObserver::OpAll, mInterposeObserver);
|
||||
} else {
|
||||
RefPtr<ProfilerIOInterposeObserver> observer = mInterposeObserver;
|
||||
NS_DispatchToMainThread(NS_NewRunnableFunction([=]() {
|
||||
IOInterposer::Unregister(IOInterposeObserver::OpAll, observer);
|
||||
}));
|
||||
}
|
||||
mozilla::IOInterposer::Unregister(mozilla::IOInterposeObserver::OpAll,
|
||||
mInterposeObserver.get());
|
||||
}
|
||||
}
|
||||
|
||||
@ -467,7 +450,7 @@ private:
|
||||
SamplerThread* const mSamplerThread;
|
||||
|
||||
// The interposer that records main thread I/O.
|
||||
const RefPtr<mozilla::ProfilerIOInterposeObserver> mInterposeObserver;
|
||||
const UniquePtr<mozilla::ProfilerIOInterposeObserver> mInterposeObserver;
|
||||
|
||||
// Is the profiler paused?
|
||||
bool mIsPaused;
|
||||
@ -549,6 +532,19 @@ MOZ_THREAD_LOCAL(PseudoStack*) sPseudoStack;
|
||||
// The name of the main thread.
|
||||
static const char* const kMainThreadName = "GeckoMain";
|
||||
|
||||
static bool
|
||||
CanNotifyObservers()
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
|
||||
#if defined(GP_OS_android)
|
||||
// Android ANR reporter uses the profiler off the main thread.
|
||||
return NS_IsMainThread();
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// BEGIN tick/unwinding code
|
||||
|
||||
@ -1384,6 +1380,7 @@ static void
|
||||
StreamTaskTracer(PSLockRef aLock, SpliceableJSONWriter& aWriter)
|
||||
{
|
||||
#ifdef MOZ_TASK_TRACER
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
MOZ_RELEASE_ASSERT(CorePS::Exists() && ActivePS::Exists(aLock));
|
||||
|
||||
aWriter.StartArrayProperty("data");
|
||||
@ -1420,28 +1417,10 @@ StreamTaskTracer(PSLockRef aLock, SpliceableJSONWriter& aWriter)
|
||||
static void
|
||||
StreamMetaJSCustomObject(PSLockRef aLock, SpliceableJSONWriter& aWriter)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
MOZ_RELEASE_ASSERT(CorePS::Exists() && ActivePS::Exists(aLock));
|
||||
|
||||
aWriter.IntProperty("version", 6);
|
||||
|
||||
// The "startTime" field holds the number of milliseconds since midnight
|
||||
// January 1, 1970 GMT. This grotty code computes (Now - (Now -
|
||||
// ProcessStartTime)) to convert CorePS::ProcessStartTime() into that form.
|
||||
mozilla::TimeDuration delta =
|
||||
mozilla::TimeStamp::Now() - CorePS::ProcessStartTime(aLock);
|
||||
aWriter.DoubleProperty(
|
||||
"startTime", static_cast<double>(PR_Now()/1000.0 - delta.ToMilliseconds()));
|
||||
|
||||
if (!NS_IsMainThread()) {
|
||||
// Leave the rest of the properties out if we're not on the main thread.
|
||||
// At the moment, the only case in which this function is called on a
|
||||
// background thread is if we're in a content process and are going to
|
||||
// send this profile to the parent process. In that case, the parent
|
||||
// process profile's "meta" object already has all this information, and
|
||||
// the parent process profile is dumped on its main thread.
|
||||
return;
|
||||
}
|
||||
|
||||
aWriter.DoubleProperty("interval", ActivePS::Interval(aLock));
|
||||
aWriter.IntProperty("stackwalk", ActivePS::FeatureStackWalk(aLock));
|
||||
|
||||
@ -1456,6 +1435,14 @@ StreamMetaJSCustomObject(PSLockRef aLock, SpliceableJSONWriter& aWriter)
|
||||
bool asyncStacks = Preferences::GetBool("javascript.options.asyncstack");
|
||||
aWriter.IntProperty("asyncstack", asyncStacks);
|
||||
|
||||
// The "startTime" field holds the number of milliseconds since midnight
|
||||
// January 1, 1970 GMT. This grotty code computes (Now - (Now -
|
||||
// ProcessStartTime)) to convert CorePS::ProcessStartTime() into that form.
|
||||
mozilla::TimeDuration delta =
|
||||
mozilla::TimeStamp::Now() - CorePS::ProcessStartTime(aLock);
|
||||
aWriter.DoubleProperty(
|
||||
"startTime", static_cast<double>(PR_Now()/1000.0 - delta.ToMilliseconds()));
|
||||
|
||||
aWriter.IntProperty("processType", XRE_GetProcessType());
|
||||
|
||||
nsresult res;
|
||||
@ -1567,6 +1554,7 @@ locked_profiler_stream_json_for_this_process(PSLockRef aLock,
|
||||
{
|
||||
LOG("locked_profiler_stream_json_for_this_process");
|
||||
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
MOZ_RELEASE_ASSERT(CorePS::Exists() && ActivePS::Exists(aLock));
|
||||
|
||||
// Put shared library info
|
||||
@ -1631,6 +1619,7 @@ profiler_stream_json_for_this_process(SpliceableJSONWriter& aWriter, double aSin
|
||||
{
|
||||
LOG("profiler_stream_json_for_this_process");
|
||||
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
MOZ_RELEASE_ASSERT(CorePS::Exists());
|
||||
|
||||
PSAutoLock lock(gPSMutex);
|
||||
@ -2002,24 +1991,19 @@ locked_register_thread(PSLockRef aLock, const char* aName, void* stackTop)
|
||||
CorePS::LiveThreads(aLock).push_back(info);
|
||||
}
|
||||
|
||||
static void
|
||||
NotifyObservers(const char* aTopic, nsISupports* aSubject = nullptr)
|
||||
{
|
||||
if (!NS_IsMainThread()) {
|
||||
nsCOMPtr<nsISupports> subject = aSubject;
|
||||
NS_DispatchToMainThread(NS_NewRunnableFunction([=] { NotifyObservers(aTopic, subject); }));
|
||||
return;
|
||||
}
|
||||
|
||||
if (nsCOMPtr<nsIObserverService> os = services::GetObserverService()) {
|
||||
os->NotifyObservers(aSubject, aTopic, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
NotifyProfilerStarted(const int aEntries, double aInterval, uint32_t aFeatures,
|
||||
const char** aFilters, uint32_t aFilterCount)
|
||||
{
|
||||
if (!CanNotifyObservers()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
|
||||
if (!os) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsTArray<nsCString> filtersArray;
|
||||
for (size_t i = 0; i < aFilterCount; ++i) {
|
||||
filtersArray.AppendElement(aFilters[i]);
|
||||
@ -2028,8 +2012,22 @@ NotifyProfilerStarted(const int aEntries, double aInterval, uint32_t aFeatures,
|
||||
nsCOMPtr<nsIProfilerStartParams> params =
|
||||
new nsProfilerStartParams(aEntries, aInterval, aFeatures, filtersArray);
|
||||
|
||||
ProfilerParent::ProfilerStarted(params);
|
||||
NotifyObservers("profiler-started", params);
|
||||
os->NotifyObservers(params, "profiler-started", nullptr);
|
||||
}
|
||||
|
||||
static void
|
||||
NotifyObservers(const char* aTopic)
|
||||
{
|
||||
if (!CanNotifyObservers()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
|
||||
if (!os) {
|
||||
return;
|
||||
}
|
||||
|
||||
os->NotifyObservers(nullptr, aTopic, nullptr);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2174,7 +2172,6 @@ profiler_shutdown()
|
||||
// We do these operations with gPSMutex unlocked. The comments in
|
||||
// profiler_stop() explain why.
|
||||
if (samplerThread) {
|
||||
ProfilerParent::ProfilerStopped();
|
||||
NotifyObservers("profiler-stopped");
|
||||
delete samplerThread;
|
||||
}
|
||||
@ -2185,6 +2182,7 @@ profiler_get_profile(double aSinceTime)
|
||||
{
|
||||
LOG("profiler_get_profile");
|
||||
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
MOZ_RELEASE_ASSERT(CorePS::Exists());
|
||||
|
||||
SpliceableChunkedJSONWriter b;
|
||||
@ -2208,6 +2206,7 @@ void
|
||||
profiler_get_start_params(int* aEntries, double* aInterval, uint32_t* aFeatures,
|
||||
mozilla::Vector<const char*>* aFilters)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
MOZ_RELEASE_ASSERT(CorePS::Exists());
|
||||
|
||||
if (NS_WARN_IF(!aEntries) || NS_WARN_IF(!aInterval) ||
|
||||
@ -2283,6 +2282,7 @@ profiler_save_profile_to_file(const char* aFilename)
|
||||
uint32_t
|
||||
profiler_get_available_features()
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
MOZ_RELEASE_ASSERT(CorePS::Exists());
|
||||
|
||||
uint32_t features = 0;
|
||||
@ -2354,6 +2354,7 @@ locked_profiler_start(PSLockRef aLock, int aEntries, double aInterval,
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
MOZ_RELEASE_ASSERT(CorePS::Exists() && !ActivePS::Exists(aLock));
|
||||
|
||||
// Fall back to the default values if the passed-in values are unreasonable.
|
||||
@ -2410,6 +2411,7 @@ profiler_start(int aEntries, double aInterval, uint32_t aFeatures,
|
||||
{
|
||||
LOG("profiler_start");
|
||||
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
|
||||
SamplerThread* samplerThread = nullptr;
|
||||
{
|
||||
@ -2432,7 +2434,6 @@ profiler_start(int aEntries, double aInterval, uint32_t aFeatures,
|
||||
// We do these operations with gPSMutex unlocked. The comments in
|
||||
// profiler_stop() explain why.
|
||||
if (samplerThread) {
|
||||
ProfilerParent::ProfilerStopped();
|
||||
NotifyObservers("profiler-stopped");
|
||||
delete samplerThread;
|
||||
}
|
||||
@ -2445,6 +2446,7 @@ locked_profiler_stop(PSLockRef aLock)
|
||||
{
|
||||
LOG("locked_profiler_stop");
|
||||
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
MOZ_RELEASE_ASSERT(CorePS::Exists() && ActivePS::Exists(aLock));
|
||||
|
||||
#ifdef MOZ_TASK_TRACER
|
||||
@ -2492,6 +2494,7 @@ profiler_stop()
|
||||
{
|
||||
LOG("profiler_stop");
|
||||
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
MOZ_RELEASE_ASSERT(CorePS::Exists());
|
||||
|
||||
SamplerThread* samplerThread;
|
||||
@ -2508,7 +2511,6 @@ profiler_stop()
|
||||
// We notify observers with gPSMutex unlocked. Otherwise we might get a
|
||||
// deadlock, if code run by the observer calls a profiler function that locks
|
||||
// gPSMutex. (This has been seen in practise in bug 1346356.)
|
||||
ProfilerParent::ProfilerStopped();
|
||||
NotifyObservers("profiler-stopped");
|
||||
|
||||
// We delete with gPSMutex unlocked. Otherwise we would get a deadlock: we
|
||||
@ -2526,6 +2528,7 @@ profiler_stop()
|
||||
bool
|
||||
profiler_is_paused()
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
MOZ_RELEASE_ASSERT(CorePS::Exists());
|
||||
|
||||
PSAutoLock lock(gPSMutex);
|
||||
@ -2542,6 +2545,7 @@ profiler_pause()
|
||||
{
|
||||
LOG("profiler_pause");
|
||||
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
MOZ_RELEASE_ASSERT(CorePS::Exists());
|
||||
|
||||
{
|
||||
@ -2555,7 +2559,6 @@ profiler_pause()
|
||||
}
|
||||
|
||||
// gPSMutex must be unlocked when we notify, to avoid potential deadlocks.
|
||||
ProfilerParent::ProfilerPaused();
|
||||
NotifyObservers("profiler-paused");
|
||||
}
|
||||
|
||||
@ -2564,6 +2567,7 @@ profiler_resume()
|
||||
{
|
||||
LOG("profiler_resume");
|
||||
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
MOZ_RELEASE_ASSERT(CorePS::Exists());
|
||||
|
||||
{
|
||||
@ -2577,7 +2581,6 @@ profiler_resume()
|
||||
}
|
||||
|
||||
// gPSMutex must be unlocked when we notify, to avoid potential deadlocks.
|
||||
ProfilerParent::ProfilerResumed();
|
||||
NotifyObservers("profiler-resumed");
|
||||
}
|
||||
|
||||
|
@ -1,107 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; 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/. */
|
||||
|
||||
#include "ChildProfilerController.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "ProfilerChild.h"
|
||||
|
||||
using namespace mozilla::ipc;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
ChildProfilerController::ChildProfilerController()
|
||||
{
|
||||
MOZ_COUNT_CTOR(ChildProfilerController);
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
Endpoint<PProfilerParent>
|
||||
ChildProfilerController::SetUpEndpoints(base::ProcessId aOtherPid)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
Endpoint<PProfilerParent> parent;
|
||||
Endpoint<PProfilerChild> child;
|
||||
nsresult rv = PProfiler::CreateEndpoints(aOtherPid,
|
||||
base::GetCurrentProcId(),
|
||||
&parent, &child);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
MOZ_CRASH("Failed to create top level actor for PProfiler!");
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(NS_NewNamedThread("ProfilerChild", getter_AddRefs(mThread)))) {
|
||||
// Now that mThread has been set, run SetupProfilerChild on the thread.
|
||||
mThread->Dispatch(NewRunnableMethod<Endpoint<PProfilerChild>&&>(
|
||||
this, &ChildProfilerController::SetupProfilerChild, Move(child)),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
nsCString
|
||||
ChildProfilerController::GrabShutdownProfileAndShutdown()
|
||||
{
|
||||
nsCString shutdownProfile;
|
||||
ShutdownAndMaybeGrabShutdownProfileFirst(&shutdownProfile);
|
||||
return shutdownProfile;
|
||||
}
|
||||
|
||||
void
|
||||
ChildProfilerController::Shutdown()
|
||||
{
|
||||
ShutdownAndMaybeGrabShutdownProfileFirst(nullptr);
|
||||
}
|
||||
|
||||
void
|
||||
ChildProfilerController::ShutdownAndMaybeGrabShutdownProfileFirst(nsCString* aOutShutdownProfile)
|
||||
{
|
||||
if (mThread) {
|
||||
mThread->Dispatch(NewRunnableMethod<nsCString*>(
|
||||
this, &ChildProfilerController::ShutdownProfilerChild, aOutShutdownProfile),
|
||||
NS_DISPATCH_NORMAL);
|
||||
// Shut down the thread. This call will spin until all runnables (including
|
||||
// the ShutdownProfilerChild runnable) have been processed.
|
||||
mThread->Shutdown();
|
||||
mThread = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ChildProfilerController::~ChildProfilerController()
|
||||
{
|
||||
MOZ_COUNT_DTOR(ChildProfilerController);
|
||||
|
||||
MOZ_ASSERT(!mThread, "Please call Shutdown before destroying ChildProfilerController");
|
||||
MOZ_ASSERT(!mProfilerChild);
|
||||
}
|
||||
|
||||
void
|
||||
ChildProfilerController::SetupProfilerChild(Endpoint<PProfilerChild>&& aEndpoint)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(mThread == NS_GetCurrentThread());
|
||||
MOZ_ASSERT(aEndpoint.IsValid());
|
||||
|
||||
mProfilerChild = new ProfilerChild();
|
||||
Endpoint<PProfilerChild> endpoint = Move(aEndpoint);
|
||||
|
||||
if (!endpoint.Bind(mProfilerChild)) {
|
||||
MOZ_CRASH("Failed to bind ProfilerChild!");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ChildProfilerController::ShutdownProfilerChild(nsCString* aOutShutdownProfile)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(mThread == NS_GetCurrentThread());
|
||||
|
||||
if (aOutShutdownProfile) {
|
||||
*aOutShutdownProfile = mProfilerChild->GrabShutdownProfile();
|
||||
}
|
||||
mProfilerChild->Destroy();
|
||||
mProfilerChild = nullptr;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
157
tools/profiler/gecko/CrossProcessProfilerController.cpp
Normal file
157
tools/profiler/gecko/CrossProcessProfilerController.cpp
Normal file
@ -0,0 +1,157 @@
|
||||
/* 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/. */
|
||||
|
||||
#include "CrossProcessProfilerController.h"
|
||||
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/ProfilerTypes.h"
|
||||
#include "nsIProfiler.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsProfiler.h"
|
||||
#include "ProfilerControllingProcess.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
static const char* sObserverTopics[] = {
|
||||
"profiler-started",
|
||||
"profiler-stopped",
|
||||
"profiler-paused",
|
||||
"profiler-resumed",
|
||||
"profiler-subprocess-gather",
|
||||
};
|
||||
|
||||
// ProfilerObserver is a refcounted class that gets registered with the
|
||||
// observer service and just forwards Observe() calls to mController.
|
||||
// This indirection makes the CrossProcessProfilerController API nicer because
|
||||
// it doesn't require a separate Init() method to register with the observer
|
||||
// service, and because not being refcounted allows CPPC to be managed with a
|
||||
// UniquePtr.
|
||||
// The life time of ProfilerObserver is bounded by the life time of CPPC: CPPC
|
||||
// unregisters the ProfilerObserver from the observer service in its
|
||||
// destructor, and then it drops its reference to the ProfilerObserver, which
|
||||
// destroys the ProfilerObserver.
|
||||
class ProfilerObserver final : public nsIObserver
|
||||
{
|
||||
public:
|
||||
explicit ProfilerObserver(CrossProcessProfilerController& aController)
|
||||
: mController(aController)
|
||||
{}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD Observe(nsISupports* aSubject, const char* aTopic,
|
||||
const char16_t* aData) override
|
||||
{
|
||||
mController.Observe(aSubject, aTopic);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
~ProfilerObserver() {}
|
||||
|
||||
CrossProcessProfilerController& mController;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(ProfilerObserver, nsIObserver)
|
||||
|
||||
CrossProcessProfilerController::CrossProcessProfilerController(
|
||||
ProfilerControllingProcess* aProcess)
|
||||
: mProcess(aProcess)
|
||||
, mObserver(new ProfilerObserver(*this))
|
||||
{
|
||||
if (profiler_is_active()) {
|
||||
// If the profiler is already running in this process, start it in the
|
||||
// child process immediately.
|
||||
nsCOMPtr<nsIProfilerStartParams> currentProfilerParams;
|
||||
nsCOMPtr<nsIProfiler> profiler(do_GetService("@mozilla.org/tools/profiler;1"));
|
||||
DebugOnly<nsresult> rv = profiler->GetStartParams(getter_AddRefs(currentProfilerParams));
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
StartProfiler(currentProfilerParams);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (obs) {
|
||||
size_t length = ArrayLength(sObserverTopics);
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
obs->AddObserver(mObserver, sObserverTopics[i], false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CrossProcessProfilerController::~CrossProcessProfilerController()
|
||||
{
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (obs) {
|
||||
size_t length = ArrayLength(sObserverTopics);
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
obs->RemoveObserver(mObserver, sObserverTopics[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CrossProcessProfilerController::StartProfiler(nsIProfilerStartParams* aParams)
|
||||
{
|
||||
if (NS_WARN_IF(!aParams)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ProfilerInitParams ipcParams;
|
||||
|
||||
ipcParams.enabled() = true;
|
||||
aParams->GetEntries(&ipcParams.entries());
|
||||
aParams->GetInterval(&ipcParams.interval());
|
||||
aParams->GetFeatures(&ipcParams.features());
|
||||
ipcParams.filters() = aParams->GetFilters();
|
||||
|
||||
mProcess->SendStartProfiler(ipcParams);
|
||||
}
|
||||
|
||||
void
|
||||
CrossProcessProfilerController::Observe(nsISupports* aSubject,
|
||||
const char* aTopic)
|
||||
{
|
||||
if (!strcmp(aTopic, "profiler-subprocess-gather")) {
|
||||
// profiler-subprocess-gather is the request to capture the profile. We
|
||||
// need to tell the other process that we're interested in its profile,
|
||||
// and we tell the gatherer that we've forwarded the request, so that it
|
||||
// can keep track of the number of pending profiles.
|
||||
nsProfiler::GetOrCreate()->WillGatherOOPProfile();
|
||||
mProcess->SendGatherProfile();
|
||||
}
|
||||
// These four notifications are sent by the profiler when its corresponding
|
||||
// methods are called inside this process. These state changes just need to
|
||||
// be forwarded to the other process.
|
||||
else if (!strcmp(aTopic, "profiler-started")) {
|
||||
nsCOMPtr<nsIProfilerStartParams> params(do_QueryInterface(aSubject));
|
||||
StartProfiler(params);
|
||||
}
|
||||
else if (!strcmp(aTopic, "profiler-stopped")) {
|
||||
mProcess->SendStopProfiler();
|
||||
}
|
||||
else if (!strcmp(aTopic, "profiler-paused")) {
|
||||
mProcess->SendPauseProfiler(true);
|
||||
}
|
||||
else if (!strcmp(aTopic, "profiler-resumed")) {
|
||||
mProcess->SendPauseProfiler(false);
|
||||
}
|
||||
}
|
||||
|
||||
// This is called in response to a SendGatherProfile request, or when the
|
||||
// other process exits while the profiler is running.
|
||||
void
|
||||
CrossProcessProfilerController::RecvProfile(const nsCString& aProfile,
|
||||
bool aIsExitProfile)
|
||||
{
|
||||
// Pass our process's profile along to nsProfiler.
|
||||
if (aIsExitProfile) {
|
||||
nsProfiler::GetOrCreate()->OOPExitProfile(aProfile);
|
||||
} else {
|
||||
nsProfiler::GetOrCreate()->GatheredOOPProfile(aProfile);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
@ -1,32 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; 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/. */
|
||||
|
||||
include ProfilerTypes;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// PProfiler is a top-level protocol. It is used to let the main process
|
||||
// control the Gecko Profiler in other processes, and request profiles from
|
||||
// those processes.
|
||||
// It is a top-level protocol so that its child endpoint can be on a
|
||||
// background thread, so that profiles can be gathered even if the main thread
|
||||
// is unresponsive.
|
||||
async protocol PProfiler
|
||||
{
|
||||
child:
|
||||
async Start(ProfilerInitParams params);
|
||||
async Stop();
|
||||
async Pause();
|
||||
async Resume();
|
||||
|
||||
async GatherProfile();
|
||||
|
||||
parent:
|
||||
async Profile(nsCString aProfile);
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -60,6 +60,12 @@ ProfileGatherer::GatheredOOPProfile(const nsACString& aProfile)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ProfileGatherer::WillGatherOOPProfile()
|
||||
{
|
||||
mPendingProfiles++;
|
||||
}
|
||||
|
||||
RefPtr<ProfileGatherer::ProfileGatherPromise>
|
||||
ProfileGatherer::Start(double aSinceTime)
|
||||
{
|
||||
@ -72,14 +78,20 @@ ProfileGatherer::Start(double aSinceTime)
|
||||
}
|
||||
|
||||
mGathering = true;
|
||||
mPendingProfiles = 0;
|
||||
|
||||
// Request profiles from the other processes. This will trigger
|
||||
// asynchronous calls to ProfileGatherer::GatheredOOPProfile as the
|
||||
// profiles arrive.
|
||||
// Send a notification to request profiles from other processes. The
|
||||
// observers of this notification will call WillGatherOOPProfile() which
|
||||
// increments mPendingProfiles.
|
||||
// Do this before the call to profiler_stream_json_for_this_process because
|
||||
// that call is slow and we want to let the other processes grab their
|
||||
// profiles as soon as possible.
|
||||
mPendingProfiles = ProfilerParent::GatherProfiles();
|
||||
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
|
||||
if (os) {
|
||||
DebugOnly<nsresult> rv =
|
||||
os->NotifyObservers(this, "profiler-subprocess-gather", nullptr);
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "NotifyObservers failed");
|
||||
}
|
||||
|
||||
mWriter.emplace();
|
||||
|
||||
|
@ -20,6 +20,7 @@ public:
|
||||
typedef MozPromise<nsCString, nsresult, false> ProfileGatherPromise;
|
||||
|
||||
explicit ProfileGatherer();
|
||||
void WillGatherOOPProfile();
|
||||
void GatheredOOPProfile(const nsACString& aProfile);
|
||||
RefPtr<ProfileGatherPromise> Start(double aSinceTime);
|
||||
void OOPExitProfile(const nsACString& aProfile);
|
||||
|
@ -1,104 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; 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/. */
|
||||
|
||||
#include "GeckoProfiler.h"
|
||||
#include "ProfilerChild.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
ProfilerChild::ProfilerChild()
|
||||
: mThread(NS_GetCurrentThread())
|
||||
, mDestroyed(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(ProfilerChild);
|
||||
}
|
||||
|
||||
ProfilerChild::~ProfilerChild()
|
||||
{
|
||||
MOZ_COUNT_DTOR(ProfilerChild);
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ProfilerChild::RecvStart(const ProfilerInitParams& params)
|
||||
{
|
||||
nsTArray<const char*> filterArray;
|
||||
for (size_t i = 0; i < params.filters().Length(); ++i) {
|
||||
filterArray.AppendElement(params.filters()[i].get());
|
||||
}
|
||||
|
||||
profiler_start(params.entries(), params.interval(),
|
||||
params.features(),
|
||||
filterArray.Elements(),
|
||||
filterArray.Length());
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ProfilerChild::RecvStop()
|
||||
{
|
||||
profiler_stop();
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ProfilerChild::RecvPause()
|
||||
{
|
||||
profiler_pause();
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ProfilerChild::RecvResume()
|
||||
{
|
||||
profiler_resume();
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
static nsCString
|
||||
CollectProfileOrEmptyString()
|
||||
{
|
||||
nsCString profileCString;
|
||||
UniquePtr<char[]> profile = profiler_get_profile();
|
||||
if (profile) {
|
||||
profileCString = nsCString(profile.get(), strlen(profile.get()));
|
||||
} else {
|
||||
profileCString = EmptyCString();
|
||||
}
|
||||
return profileCString;
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ProfilerChild::RecvGatherProfile()
|
||||
{
|
||||
if (!mDestroyed) {
|
||||
Unused << SendProfile(CollectProfileOrEmptyString());
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void
|
||||
ProfilerChild::ActorDestroy(ActorDestroyReason aActorDestroyReason)
|
||||
{
|
||||
mDestroyed = true;
|
||||
}
|
||||
|
||||
void
|
||||
ProfilerChild::Destroy()
|
||||
{
|
||||
if (!mDestroyed) {
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
nsCString
|
||||
ProfilerChild::GrabShutdownProfile()
|
||||
{
|
||||
return CollectProfileOrEmptyString();
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
@ -8,7 +8,6 @@
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
|
||||
#include "mozilla/IOInterposer.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -18,13 +17,8 @@ namespace mozilla {
|
||||
*/
|
||||
class ProfilerIOInterposeObserver final : public IOInterposeObserver
|
||||
{
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ProfilerIOInterposeObserver)
|
||||
|
||||
public:
|
||||
virtual void Observe(Observation& aObservation);
|
||||
|
||||
protected:
|
||||
virtual ~ProfilerIOInterposeObserver() {}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -1,250 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; 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/. */
|
||||
|
||||
#include "ProfilerParent.h"
|
||||
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/Unused.h"
|
||||
|
||||
#include "nsProfiler.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using namespace ipc;
|
||||
|
||||
class ProfilerParentTracker final {
|
||||
public:
|
||||
static void StartTracking(ProfilerParent* aParent);
|
||||
static void StopTracking(ProfilerParent* aParent);
|
||||
|
||||
template<typename FuncType>
|
||||
static void Enumerate(FuncType aIterFunc);
|
||||
|
||||
ProfilerParentTracker() {}
|
||||
~ProfilerParentTracker();
|
||||
|
||||
private:
|
||||
nsTArray<ProfilerParent*> mProfilerParents;
|
||||
static UniquePtr<ProfilerParentTracker> sInstance;
|
||||
};
|
||||
|
||||
UniquePtr<ProfilerParentTracker> ProfilerParentTracker::sInstance;
|
||||
|
||||
/* static */ void
|
||||
ProfilerParentTracker::StartTracking(ProfilerParent* aProfilerParent)
|
||||
{
|
||||
if (!sInstance) {
|
||||
sInstance = MakeUnique<ProfilerParentTracker>();
|
||||
ClearOnShutdown(&sInstance, ShutdownPhase::Shutdown);
|
||||
}
|
||||
sInstance->mProfilerParents.AppendElement(aProfilerParent);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
ProfilerParentTracker::StopTracking(ProfilerParent* aParent)
|
||||
{
|
||||
if (sInstance) {
|
||||
sInstance->mProfilerParents.RemoveElement(aParent);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename FuncType>
|
||||
/* static */ void
|
||||
ProfilerParentTracker::Enumerate(FuncType aIterFunc)
|
||||
{
|
||||
if (sInstance) {
|
||||
for (ProfilerParent* profilerParent : sInstance->mProfilerParents) {
|
||||
if (!profilerParent->mDestroyed) {
|
||||
aIterFunc(profilerParent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ProfilerParentTracker::~ProfilerParentTracker()
|
||||
{
|
||||
nsTArray<ProfilerParent*> parents;
|
||||
parents = mProfilerParents;
|
||||
// Close the channels of any profiler parents that haven't been destroyed.
|
||||
for (ProfilerParent* profilerParent : parents) {
|
||||
if (!profilerParent->mDestroyed) {
|
||||
// Keep the object alive until the call to Close() has completed.
|
||||
// Close() will trigger a call to DeallocPProfilerParent.
|
||||
RefPtr<ProfilerParent> actor = profilerParent;
|
||||
actor->Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
ProfilerParent::Alloc(Endpoint<PProfilerParent>&& aEndpoint)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
Endpoint<PProfilerParent> endpoint = Move(aEndpoint);
|
||||
RefPtr<ProfilerParent> actor = new ProfilerParent();
|
||||
|
||||
if (!endpoint.Bind(actor)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// mSelfRef will be cleared in DeallocPProfilerParent.
|
||||
actor->mSelfRef = actor;
|
||||
actor->Init();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ProfilerParent::ProfilerParent()
|
||||
: mPendingRequestedProfilesCount(0)
|
||||
, mDestroyed(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(ProfilerParent);
|
||||
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
void
|
||||
ProfilerParent::Init()
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
|
||||
ProfilerParentTracker::StartTracking(this);
|
||||
|
||||
if (profiler_is_active()) {
|
||||
// If the profiler is already running in this process, start it in the
|
||||
// child process immediately.
|
||||
int entries = 0;
|
||||
double interval = 0;
|
||||
mozilla::Vector<const char*> filters;
|
||||
uint32_t features;
|
||||
profiler_get_start_params(&entries, &interval, &features, &filters);
|
||||
|
||||
ProfilerInitParams ipcParams;
|
||||
ipcParams.enabled() = true;
|
||||
ipcParams.entries() = entries;
|
||||
ipcParams.interval() = interval;
|
||||
ipcParams.features() = features;
|
||||
|
||||
for (uint32_t i = 0; i < filters.length(); ++i) {
|
||||
ipcParams.filters().AppendElement(filters[i]);
|
||||
}
|
||||
|
||||
Unused << SendStart(ipcParams);
|
||||
}
|
||||
}
|
||||
|
||||
ProfilerParent::~ProfilerParent()
|
||||
{
|
||||
MOZ_COUNT_DTOR(ProfilerParent);
|
||||
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
ProfilerParentTracker::StopTracking(this);
|
||||
}
|
||||
|
||||
/* static */ uint32_t
|
||||
ProfilerParent::GatherProfiles()
|
||||
{
|
||||
if (!NS_IsMainThread()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t count = 0;
|
||||
ProfilerParentTracker::Enumerate([&](ProfilerParent* profilerParent) {
|
||||
profilerParent->mPendingRequestedProfilesCount++;
|
||||
Unused << profilerParent->SendGatherProfile();
|
||||
count++;
|
||||
});
|
||||
return count;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
ProfilerParent::ProfilerStarted(nsIProfilerStartParams* aParams)
|
||||
{
|
||||
if (!NS_IsMainThread()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ProfilerInitParams ipcParams;
|
||||
ipcParams.enabled() = true;
|
||||
aParams->GetEntries(&ipcParams.entries());
|
||||
aParams->GetInterval(&ipcParams.interval());
|
||||
aParams->GetFeatures(&ipcParams.features());
|
||||
ipcParams.filters() = aParams->GetFilters();
|
||||
|
||||
ProfilerParentTracker::Enumerate([&](ProfilerParent* profilerParent) {
|
||||
Unused << profilerParent->SendStart(ipcParams);
|
||||
});
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
ProfilerParent::ProfilerStopped()
|
||||
{
|
||||
if (!NS_IsMainThread()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ProfilerParentTracker::Enumerate([](ProfilerParent* profilerParent) {
|
||||
Unused << profilerParent->SendStop();
|
||||
});
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
ProfilerParent::ProfilerPaused()
|
||||
{
|
||||
if (!NS_IsMainThread()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ProfilerParentTracker::Enumerate([](ProfilerParent* profilerParent) {
|
||||
Unused << profilerParent->SendPause();
|
||||
});
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
ProfilerParent::ProfilerResumed()
|
||||
{
|
||||
if (!NS_IsMainThread()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ProfilerParentTracker::Enumerate([](ProfilerParent* profilerParent) {
|
||||
Unused << profilerParent->SendResume();
|
||||
});
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ProfilerParent::RecvProfile(const nsCString& aProfile)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
MOZ_RELEASE_ASSERT(mPendingRequestedProfilesCount > 0);
|
||||
mPendingRequestedProfilesCount--;
|
||||
nsProfiler::GetOrCreate()->GatheredOOPProfile(aProfile);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void
|
||||
ProfilerParent::ActorDestroy(ActorDestroyReason aActorDestroyReason)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
|
||||
RefPtr<nsProfiler> profiler = nsProfiler::GetOrCreate();
|
||||
while (mPendingRequestedProfilesCount > 0) {
|
||||
profiler->GatheredOOPProfile(NS_LITERAL_CSTRING(""));
|
||||
mPendingRequestedProfilesCount--;
|
||||
}
|
||||
mDestroyed = true;
|
||||
}
|
||||
|
||||
void
|
||||
ProfilerParent::DeallocPProfilerParent()
|
||||
{
|
||||
mSelfRef = nullptr;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
@ -10,7 +10,6 @@
|
||||
class nsCString;
|
||||
%}
|
||||
|
||||
[ref] native nsCString(const nsCString);
|
||||
[ref] native StringArrayRef(const nsTArray<nsCString>);
|
||||
|
||||
/**
|
||||
@ -111,7 +110,4 @@ interface nsIProfiler : nsISupports
|
||||
* Dump the collected profile to a file.
|
||||
*/
|
||||
void dumpProfileToFile(in string aFilename);
|
||||
|
||||
[noscript, notxpcom, nostdcall]
|
||||
void receiveShutdownProfile(in nsCString aProfile);
|
||||
};
|
||||
|
@ -480,6 +480,29 @@ nsProfiler::GetStartParams(nsIProfilerStartParams** aRetVal)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsProfiler::GetBufferInfo(uint32_t* aCurrentPosition, uint32_t* aTotalSize,
|
||||
uint32_t* aGeneration)
|
||||
{
|
||||
MOZ_ASSERT(aCurrentPosition);
|
||||
MOZ_ASSERT(aTotalSize);
|
||||
MOZ_ASSERT(aGeneration);
|
||||
profiler_get_buffer_info(aCurrentPosition, aTotalSize, aGeneration);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsProfiler::WillGatherOOPProfile()
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!mGatherer) {
|
||||
return;
|
||||
}
|
||||
|
||||
mGatherer->WillGatherOOPProfile();
|
||||
}
|
||||
|
||||
void
|
||||
nsProfiler::GatheredOOPProfile(const nsACString& aProfile)
|
||||
{
|
||||
@ -493,7 +516,7 @@ nsProfiler::GatheredOOPProfile(const nsACString& aProfile)
|
||||
}
|
||||
|
||||
void
|
||||
nsProfiler::ReceiveShutdownProfile(const nsCString& aProfile)
|
||||
nsProfiler::OOPExitProfile(const nsACString& aProfile)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
|
||||
@ -504,13 +527,3 @@ nsProfiler::ReceiveShutdownProfile(const nsCString& aProfile)
|
||||
mGatherer->OOPExitProfile(aProfile);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsProfiler::GetBufferInfo(uint32_t* aCurrentPosition, uint32_t* aTotalSize,
|
||||
uint32_t* aGeneration)
|
||||
{
|
||||
MOZ_ASSERT(aCurrentPosition);
|
||||
MOZ_ASSERT(aTotalSize);
|
||||
MOZ_ASSERT(aGeneration);
|
||||
profiler_get_buffer_info(aCurrentPosition, aTotalSize, aGeneration);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -33,7 +33,9 @@ public:
|
||||
return static_cast<nsProfiler*>(iprofiler.get());
|
||||
}
|
||||
|
||||
void WillGatherOOPProfile();
|
||||
void GatheredOOPProfile(const nsACString& aProfile);
|
||||
void OOPExitProfile(const nsACString& aProfile);
|
||||
|
||||
private:
|
||||
~nsProfiler();
|
||||
|
@ -13,7 +13,7 @@
|
||||
class nsProfilerStartParams : public nsIProfilerStartParams
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIPROFILERSTARTPARAMS
|
||||
|
||||
nsProfilerStartParams(uint32_t aEntries,
|
||||
|
@ -10,7 +10,7 @@ if CONFIG['MOZ_GECKO_PROFILER']:
|
||||
'gecko/nsIProfiler.idl',
|
||||
]
|
||||
EXPORTS += [
|
||||
'public/ChildProfilerController.h',
|
||||
'public/CrossProcessProfilerController.h',
|
||||
'public/ProfilerMarkerPayload.h',
|
||||
'public/PseudoStack.h',
|
||||
'public/shared-libraries.h',
|
||||
@ -24,7 +24,7 @@ if CONFIG['MOZ_GECKO_PROFILER']:
|
||||
'core/ProfilerMarkerPayload.cpp',
|
||||
'core/StackTop.cpp',
|
||||
'core/ThreadInfo.cpp',
|
||||
'gecko/ChildProfilerController.cpp',
|
||||
'gecko/CrossProcessProfilerController.cpp',
|
||||
'gecko/nsProfilerFactory.cpp',
|
||||
'gecko/nsProfilerStartParams.cpp',
|
||||
'gecko/ProfileGatherer.cpp',
|
||||
@ -109,7 +109,6 @@ if CONFIG['MOZ_GECKO_PROFILER']:
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
IPDL_SOURCES += [
|
||||
'gecko/PProfiler.ipdl',
|
||||
'gecko/ProfilerTypes.ipdlh',
|
||||
]
|
||||
|
||||
@ -118,13 +117,7 @@ include('/ipc/chromium/chromium-config.mozbuild')
|
||||
EXPORTS += [
|
||||
'public/GeckoProfiler.h',
|
||||
'public/GeckoProfilerReporter.h',
|
||||
'public/ProfilerChild.h',
|
||||
'public/ProfilerParent.h',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'gecko/ProfilerChild.cpp',
|
||||
'gecko/ProfilerParent.cpp',
|
||||
'public/ProfilerControllingProcess.h',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_TASK_TRACER']:
|
||||
|
@ -1,48 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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 ChildProfilerController_h
|
||||
#define ChildProfilerController_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "base/process.h"
|
||||
|
||||
class nsCString;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ProfilerChild;
|
||||
class PProfilerChild;
|
||||
class PProfilerParent;
|
||||
|
||||
// ChildProfilerController manages the setup and teardown of ProfilerChild.
|
||||
// It's used on the main thread.
|
||||
// It manages a background thread that ProfilerChild runs on.
|
||||
class ChildProfilerController final
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ChildProfilerController)
|
||||
|
||||
ChildProfilerController();
|
||||
mozilla::ipc::Endpoint<PProfilerParent> SetUpEndpoints(base::ProcessId aOtherPid);
|
||||
MOZ_MUST_USE nsCString GrabShutdownProfileAndShutdown();
|
||||
void Shutdown();
|
||||
|
||||
private:
|
||||
virtual ~ChildProfilerController();
|
||||
void ShutdownAndMaybeGrabShutdownProfileFirst(nsCString* aOutShutdownProfile);
|
||||
|
||||
// Called on mThread:
|
||||
void SetupProfilerChild(mozilla::ipc::Endpoint<PProfilerChild>&& aEndpoint);
|
||||
void ShutdownProfilerChild(nsCString* aOutShutdownProfile);
|
||||
|
||||
RefPtr<ProfilerChild> mProfilerChild; // only accessed on mThread
|
||||
RefPtr<nsIThread> mThread;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // ChildProfilerController_h
|
42
tools/profiler/public/CrossProcessProfilerController.h
Normal file
42
tools/profiler/public/CrossProcessProfilerController.h
Normal file
@ -0,0 +1,42 @@
|
||||
/* 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 CrossProcessProfilerController_h
|
||||
#define CrossProcessProfilerController_h
|
||||
|
||||
#include "nsString.h"
|
||||
|
||||
class nsIProfilerStartParams;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ProfilerObserver;
|
||||
class ProfilerControllingProcess;
|
||||
|
||||
// A class that calls methods on aProcess to coordinate the profiler in other
|
||||
// processes. aProcess needs to implement a number of calls that trigger calls
|
||||
// to the relevant profiler_* functions in the other process.
|
||||
// RecvProfile needs to be called when the other process replies with its
|
||||
// profile.
|
||||
class CrossProcessProfilerController final
|
||||
{
|
||||
public:
|
||||
// aProcess is expected to outlast this CrossProcessProfilerController object.
|
||||
explicit CrossProcessProfilerController(ProfilerControllingProcess* aProcess);
|
||||
~CrossProcessProfilerController();
|
||||
void RecvProfile(const nsCString& aProfile, bool aIsExitProfile);
|
||||
|
||||
private:
|
||||
void StartProfiler(nsIProfilerStartParams* aParams);
|
||||
void Observe(nsISupports* aSubject, const char* aTopic);
|
||||
|
||||
friend class ProfilerObserver;
|
||||
|
||||
ProfilerControllingProcess* mProcess;
|
||||
RefPtr<ProfilerObserver> mObserver;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
@ -1,52 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; 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/. */
|
||||
|
||||
#ifndef ProfilerChild_h
|
||||
#define ProfilerChild_h
|
||||
|
||||
#include "mozilla/PProfilerChild.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
|
||||
class nsIThread;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// The ProfilerChild actor is created in all processes except for the main
|
||||
// process. The corresponding ProfilerParent actor will be created in the main
|
||||
// process, and it will notify us about profiler state changes and request
|
||||
// profiles from us.
|
||||
class ProfilerChild final : public PProfilerChild
|
||||
{
|
||||
NS_INLINE_DECL_REFCOUNTING(ProfilerChild)
|
||||
|
||||
ProfilerChild();
|
||||
|
||||
// Collects and returns a profile.
|
||||
// This method can be used to grab a profile just before PProfiler is torn
|
||||
// down. The collected profile should then be sent through a different
|
||||
// message channel that is guaranteed to stay open long enough.
|
||||
nsCString GrabShutdownProfile();
|
||||
|
||||
void Destroy();
|
||||
|
||||
private:
|
||||
virtual ~ProfilerChild();
|
||||
|
||||
mozilla::ipc::IPCResult RecvStart(const ProfilerInitParams& params) override;
|
||||
mozilla::ipc::IPCResult RecvStop() override;
|
||||
mozilla::ipc::IPCResult RecvPause() override;
|
||||
mozilla::ipc::IPCResult RecvResume() override;
|
||||
mozilla::ipc::IPCResult RecvGatherProfile() override;
|
||||
|
||||
void ActorDestroy(ActorDestroyReason aActorDestroyReason) override;
|
||||
|
||||
nsCOMPtr<nsIThread> mThread;
|
||||
bool mDestroyed;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // ProfilerChild_h
|
26
tools/profiler/public/ProfilerControllingProcess.h
Normal file
26
tools/profiler/public/ProfilerControllingProcess.h
Normal file
@ -0,0 +1,26 @@
|
||||
/* 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 ProfilerControllingProcess_h
|
||||
#define ProfilerControllingProcess_h
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ProfilerInitParams;
|
||||
|
||||
// Top-level process actors should implement this to integrate with
|
||||
// CrossProcessProfilerController.
|
||||
class ProfilerControllingProcess {
|
||||
public:
|
||||
virtual void SendStartProfiler(const ProfilerInitParams& aParams) = 0;
|
||||
virtual void SendPauseProfiler(const bool& aPause) = 0;
|
||||
virtual void SendStopProfiler() = 0;
|
||||
virtual void SendGatherProfile() = 0;
|
||||
|
||||
virtual ~ProfilerControllingProcess() {}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
@ -1,74 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; 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/. */
|
||||
|
||||
#ifndef ProfilerParent_h
|
||||
#define ProfilerParent_h
|
||||
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/PProfilerParent.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ProfilerParentTracker;
|
||||
|
||||
// This is the main process side of the PProfiler protocol.
|
||||
// ProfilerParent instances only exist on the main thread of the main process.
|
||||
// The other side (ProfilerChild) lives on a background thread in the other
|
||||
// process.
|
||||
// The creation of PProfiler actors is initiated from the other process.
|
||||
// ProfilerParent instances are destroyed once the message channel closes,
|
||||
// which can be triggered by either process, depending on which one shuts down
|
||||
// first.
|
||||
// All ProfilerParent instances are registered with a manager class called
|
||||
// ProfilerParentTracker, which has the list of living ProfilerParent instances
|
||||
// and handles shutdown.
|
||||
class ProfilerParent final : public PProfilerParent
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ProfilerParent)
|
||||
|
||||
static bool Alloc(mozilla::ipc::Endpoint<PProfilerParent>&& aEndpoint);
|
||||
|
||||
// The following static methods can be called on any thread, but they are
|
||||
// no-ops on anything other than the main thread.
|
||||
// If called on the main thread, the call will be broadcast to all
|
||||
// registered processes (all processes for which we have a ProfilerParent
|
||||
// object).
|
||||
// At the moment, the main process always calls these methods on the main
|
||||
// thread, and that's the only process in which we need to forward these
|
||||
// calls to other processes. The other processes will call these methods on
|
||||
// the ProfilerChild background thread, but those processes don't need to
|
||||
// forward these calls any further.
|
||||
|
||||
// Returns the number of profiles to expect. The gathered profiles will be
|
||||
// provided asynchronously with a call to ProfileGatherer::ReceiveGatheredProfile.
|
||||
static uint32_t GatherProfiles();
|
||||
|
||||
static void ProfilerStarted(nsIProfilerStartParams* aParams);
|
||||
static void ProfilerStopped();
|
||||
static void ProfilerPaused();
|
||||
static void ProfilerResumed();
|
||||
|
||||
private:
|
||||
friend class ProfilerParentTracker;
|
||||
|
||||
ProfilerParent();
|
||||
virtual ~ProfilerParent();
|
||||
|
||||
void Init();
|
||||
void ActorDestroy(ActorDestroyReason aActorDestroyReason) override;
|
||||
void DeallocPProfilerParent() override;
|
||||
|
||||
mozilla::ipc::IPCResult RecvProfile(const nsCString& aProfile) override;
|
||||
|
||||
RefPtr<ProfilerParent> mSelfRef;
|
||||
uint32_t mPendingRequestedProfilesCount;
|
||||
bool mDestroyed;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // ProfilerParent_h
|
Loading…
Reference in New Issue
Block a user