Bug 1602757: add preallocation cache for webIsolated (fission) processes r=nika,smaug

Differential Revision: https://phabricator.services.mozilla.com/D69589
This commit is contained in:
Randell Jesup 2020-05-28 14:33:24 +00:00
Родитель 3d17f898c9
Коммит 4899b7707e
10 изменённых файлов: 494 добавлений и 113 удалений

Просмотреть файл

@ -760,6 +760,7 @@ static WebIDLProcType ProcTypeToWebIDL(mozilla::ProcType aType) {
#ifdef MOZ_ENABLE_FORKSERVER
PROCTYPE_TO_WEBIDL_CASE(ForkServer, ForkServer);
#endif
PROCTYPE_TO_WEBIDL_CASE(Preallocated, Preallocated);
PROCTYPE_TO_WEBIDL_CASE(Unknown, Unknown);
}
@ -861,6 +862,9 @@ already_AddRefed<Promise> ChromeUtils::RequestProcInfo(GlobalObject& aGlobal,
} else if (remoteType.EqualsLiteral(
LARGE_ALLOCATION_REMOTE_TYPE)) {
type = mozilla::ProcType::WebLargeAllocation;
} else if (remoteType.EqualsLiteral(
PREALLOC_REMOTE_TYPE)) {
type = mozilla::ProcType::Preallocated;
} else {
MOZ_CRASH("Unknown remoteType");
}

Просмотреть файл

@ -517,6 +517,7 @@ enum WebIDLProcType {
#ifdef MOZ_ENABLE_FORKSERVER
"forkServer",
#endif
"preallocated",
"unknown",
};

Просмотреть файл

@ -29,6 +29,7 @@
#include "mozilla/Unused.h"
#include "mozilla/SchedulerGroup.h"
#include "mozilla/StaticPrefs_dom.h"
#include "mozilla/StaticPrefs_fission.h"
#include "mozilla/StaticPrefs_media.h"
#include "mozilla/TelemetryIPC.h"
#include "mozilla/RemoteDecoderManagerChild.h"
@ -2545,12 +2546,27 @@ mozilla::ipc::IPCResult ContentChild::RecvAppInfo(
mozilla::ipc::IPCResult ContentChild::RecvRemoteType(
const nsString& aRemoteType) {
MOZ_ASSERT(DOMStringIsNull(mRemoteType));
if (!DOMStringIsNull(mRemoteType)) {
// Preallocated processes are type PREALLOC_REMOTE_TYPE; they can become
// anything except a File: process.
MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
("Changing remoteType of process %d from %s to %s", getpid(),
NS_ConvertUTF16toUTF8(mRemoteType).get(),
NS_ConvertUTF16toUTF8(aRemoteType).get()));
// prealloc->anything (but file) or web->web allowed
MOZ_RELEASE_ASSERT(!aRemoteType.EqualsLiteral(FILE_REMOTE_TYPE) &&
(mRemoteType.EqualsLiteral(PREALLOC_REMOTE_TYPE) ||
(mRemoteType.EqualsLiteral(DEFAULT_REMOTE_TYPE) &&
aRemoteType.EqualsLiteral(DEFAULT_REMOTE_TYPE))));
} else {
// Initial setting of remote type. Either to 'prealloc' or the actual
// final type (if we didn't use a preallocated process)
MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
("Setting remoteType of process %d to %s", getpid(),
NS_ConvertUTF16toUTF8(aRemoteType).get()));
}
mRemoteType.Assign(aRemoteType);
// For non-default ("web") types, update the process name so about:memory's
// process names are more obvious.
// Update the process name so about:memory's process names are more obvious.
if (aRemoteType.EqualsLiteral(FILE_REMOTE_TYPE)) {
SetProcessName(NS_LITERAL_STRING("file:// Content"));
} else if (aRemoteType.EqualsLiteral(EXTENSION_REMOTE_TYPE)) {
@ -2559,7 +2575,13 @@ mozilla::ipc::IPCResult ContentChild::RecvRemoteType(
SetProcessName(NS_LITERAL_STRING("Privileged Content"));
} else if (aRemoteType.EqualsLiteral(LARGE_ALLOCATION_REMOTE_TYPE)) {
SetProcessName(NS_LITERAL_STRING("Large Allocation Web Content"));
} else if (RemoteTypePrefix(aRemoteType)
.EqualsLiteral(FISSION_WEB_REMOTE_TYPE)) {
SetProcessName(NS_LITERAL_STRING("Isolated Web Content"));
}
// else "prealloc", "web" or "webCOOP+COEP" type -> "Web Content" already set
mRemoteType.Assign(aRemoteType);
return IPC_OK();
}

Просмотреть файл

@ -20,6 +20,9 @@
# include "mozilla/a11y/PDocAccessible.h"
#endif
#include "GeckoProfiler.h"
#ifdef MOZ_GECKO_PROFILER
# include "ProfilerMarkerPayload.h"
#endif
#include "GMPServiceParent.h"
#include "HandlerServiceParent.h"
#include "IHistory.h"
@ -349,6 +352,11 @@ extern FileDescriptor CreateAudioIPCConnection();
namespace dom {
LazyLogModule gProcessLog("Process");
/* static */
LogModule* ContentParent::GetLog() { return gProcessLog; }
#define NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC "ipc:network:set-offline"
#define NS_IPC_IOSERVICE_SET_CONNECTIVITY_TOPIC "ipc:network:set-connectivity"
@ -475,6 +483,10 @@ ContentParentsMemoryReporter::CollectReports(
return NS_OK;
}
// A hashtable (by type) of processes/ContentParents. This includes
// processes that are in the Preallocator cache (which would be type
// 'prealloc'), and recycled processes ('web' and in the future
// eTLD+1-locked) processes).
nsClassHashtable<nsStringHashKey, nsTArray<ContentParent*>>*
ContentParent::sBrowserContentParents;
@ -632,8 +644,10 @@ static const char* sObserverTopics[] = {
/*static*/ RefPtr<ContentParent::LaunchPromise>
ContentParent::PreallocateProcess() {
RefPtr<ContentParent> process = new ContentParent(
/* aOpener = */ nullptr, NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE));
/* aOpener = */ nullptr, NS_LITERAL_STRING(PREALLOC_REMOTE_TYPE));
MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
("Preallocating process of type " PREALLOC_REMOTE_TYPE));
return process->LaunchSubprocessAsync(PROCESS_PRIORITY_PREALLOC);
}
@ -712,6 +726,8 @@ const nsDependentSubstring RemoteTypePrefix(
}
bool IsWebRemoteType(const nsAString& aContentProcessType) {
// Note: matches webIsolated as well as web (and webLargeAllocation, and
// webCOOP+COEP)
return StringBeginsWith(aContentProcessType,
NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE));
}
@ -729,7 +745,7 @@ uint32_t ContentParent::GetMaxProcessCount(
RemoteTypePrefix(aContentProcessType);
// Check for the default remote type of "web", as it uses different prefs.
if (processTypePrefix.EqualsLiteral("web")) {
if (processTypePrefix.EqualsLiteral(DEFAULT_REMOTE_TYPE)) {
return GetMaxWebProcessCount();
}
@ -754,27 +770,57 @@ bool ContentParent::IsMaxProcessCountReached(
GetMaxProcessCount(aContentProcessType);
}
// Really more ReleaseUnneededProcesses()
/*static*/
void ContentParent::ReleaseCachedProcesses() {
if (!GetPoolSize(NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE))) {
MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
("ReleaseCachedProcesses:"));
if (!sBrowserContentParents) {
return;
}
// We might want to extend this for other process types as well in the
// future...
nsTArray<ContentParent*>& contentParents =
GetOrCreatePool(NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE));
#ifdef DEBUG
int num = 0;
for (auto iter = sBrowserContentParents->Iter(); !iter.Done(); iter.Next()) {
nsTArray<ContentParent*>* contentParents = iter.Data().get();
num += contentParents->Length();
for (auto* cp : *contentParents) {
MOZ_LOG(
ContentParent::GetLog(), LogLevel::Debug,
("%s: %zu processes", NS_ConvertUTF16toUTF8(cp->mRemoteType).get(),
contentParents->Length()));
break;
}
}
#endif
// We process the toRelease array outside of the iteration to avoid modifying
// the list (via RemoveFromList()) while we're iterating it.
nsTArray<ContentParent*> toRelease;
for (auto iter = sBrowserContentParents->Iter(); !iter.Done(); iter.Next()) {
nsTArray<ContentParent*>* contentParents = iter.Data().get();
// Shuting down these processes will change the array so let's use another
// array for the removal.
for (auto* cp : contentParents) {
if (cp->ManagedPBrowserParent().Count() == 0) {
toRelease.AppendElement(cp);
// Shutting down these processes will change the array so let's use another
// array for the removal.
for (auto* cp : *contentParents) {
if (cp->ManagedPBrowserParent().Count() == 0 &&
!cp->HasActiveWorkerOrJSPlugin() &&
cp->mRemoteType.EqualsLiteral(DEFAULT_REMOTE_TYPE)) {
toRelease.AppendElement(cp);
} else {
MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
(" Skipping %p (%s), count %d, HasActiveWorkerOrJSPlugin %d",
cp, NS_ConvertUTF16toUTF8(cp->mRemoteType).get(),
cp->ManagedPBrowserParent().Count(),
cp->HasActiveWorkerOrJSPlugin()));
}
}
}
for (auto* cp : toRelease) {
MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
(" Shutdown %p (%s)", cp,
NS_ConvertUTF16toUTF8(cp->mRemoteType).get()));
PreallocatedProcessManager::Erase(cp);
// Start a soft shutdown.
cp->ShutDownProcess(SEND_SHUTDOWN_MESSAGE);
// Make sure we don't select this process for new tabs.
@ -839,6 +885,19 @@ already_AddRefed<ContentParent> ContentParent::GetUsedBrowserProcess(
// If the provider returned an existing ContentParent, use that one.
if (0 <= index && static_cast<uint32_t>(index) <= aMaxContentParents) {
RefPtr<ContentParent> retval = aContentParents[index];
#ifdef MOZ_GECKO_PROFILER
if (profiler_thread_is_being_profiled()) {
nsPrintfCString marker("Reused process %u",
(unsigned int)retval->ChildID());
TimeStamp now = TimeStamp::Now();
PROFILER_ADD_MARKER_WITH_PAYLOAD("Process", DOM, TextMarkerPayload,
(marker, now, now));
}
#endif
MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
("GetUsedProcess: Reused process %p (%u) for %s", retval.get(),
(unsigned int)retval->ChildID(),
NS_ConvertUTF16toUTF8(aRemoteType).get()));
return retval.forget();
}
} else {
@ -848,21 +907,55 @@ already_AddRefed<ContentParent> ContentParent::GetUsedBrowserProcess(
RefPtr<ContentParent> random;
if (aContentParents.Length() >= aMaxContentParents &&
(random = MinTabSelect(aContentParents, aOpener, aMaxContentParents))) {
MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
("GetUsedProcess: Reused random process %p (%d) for %s",
random.get(), (unsigned int)random->ChildID(),
NS_ConvertUTF16toUTF8(aRemoteType).get()));
return random.forget();
}
}
// Try to take the preallocated process only for the default process type.
// Try to take the preallocated process except for blacklisted types.
// The preallocated process manager might not had the chance yet to release
// the process after a very recent ShutDownProcess, let's make sure we don't
// try to reuse a process that is being shut down.
RefPtr<ContentParent> p;
if (aRemoteType.EqualsLiteral(DEFAULT_REMOTE_TYPE) &&
(p = PreallocatedProcessManager::Take()) && !p->mShutdownPending) {
bool preallocated = false;
if (!aRemoteType.EqualsLiteral(FILE_REMOTE_TYPE) &&
!aRemoteType.EqualsLiteral(EXTENSION_REMOTE_TYPE) && // Bug 1638119
(p = PreallocatedProcessManager::Take(aRemoteType)) &&
!p->mShutdownPending) {
// p may be a preallocated process, or (if not PREALLOC_REMOTE_TYPE)
// a perviously-used process that's being recycled. Currently this is
// only done for short-duration web (DEFAULT_REMOTE_TYPE) processes
preallocated = p->mRemoteType.EqualsLiteral(PREALLOC_REMOTE_TYPE);
// For pre-allocated process we have not set the opener yet.
#ifdef MOZ_GECKO_PROFILER
if (profiler_thread_is_being_profiled()) {
nsPrintfCString marker("Assigned %s process %u",
preallocated ? "preallocated" : "reused web",
(unsigned int)p->ChildID());
TimeStamp now = TimeStamp::Now();
PROFILER_ADD_MARKER_WITH_PAYLOAD("Process", DOM, TextMarkerPayload,
(marker, now, now));
}
#endif
MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
("Adopted %s process %p for type %s",
preallocated ? "preallocated" : "reused web", p.get(),
NS_ConvertUTF16toUTF8(aRemoteType).get()));
p->mOpener = aOpener;
aContentParents.AppendElement(p);
p->mActivateTS = TimeStamp::Now();
aContentParents.AppendElement(p);
if (preallocated) {
p->mRemoteType.Assign(aRemoteType);
// Specialize this process for the appropriate eTLD+1
Unused << p->SendRemoteType(p->mRemoteType);
} else {
// we only allow "web" to "web" for security reasons
MOZ_RELEASE_ASSERT(p->mRemoteType.EqualsLiteral(DEFAULT_REMOTE_TYPE) &&
aRemoteType.EqualsLiteral(DEFAULT_REMOTE_TYPE));
}
return p.forget();
}
@ -877,12 +970,17 @@ ContentParent::GetNewOrUsedBrowserProcessInternal(Element* aFrameElement,
ContentParent* aOpener,
bool aPreferUsed,
bool aIsSync) {
MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
("GetNewOrUsedProcess for type %s",
NS_ConvertUTF16toUTF8(aRemoteType).get()));
nsTArray<ContentParent*>& contentParents = GetOrCreatePool(aRemoteType);
uint32_t maxContentParents = GetMaxProcessCount(aRemoteType);
if (aRemoteType.EqualsLiteral(
LARGE_ALLOCATION_REMOTE_TYPE) // We never want to re-use
// Large-Allocation processes.
&& contentParents.Length() >= maxContentParents) {
MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
("GetNewOrUsedProcess: returning Large Used process"));
return GetNewOrUsedBrowserProcessInternal(
aFrameElement, NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE), aPriority,
aOpener, /*aPreferUsed =*/false, aIsSync);
@ -895,11 +993,18 @@ ContentParent::GetNewOrUsedBrowserProcessInternal(Element* aFrameElement,
if (contentParent) {
// We have located a process. It may not have finished initializing,
// this will be for the caller to handle.
MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
("GetNewOrUsedProcess: Used process %p (launching %d)",
contentParent.get(), contentParent->IsLaunching()));
return contentParent.forget();
}
// No reusable process. Let's create and launch one.
// The life cycle will be set to `LifecycleState::LAUNCHING`.
MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
("Launching new process immediately for type %s",
NS_ConvertUTF16toUTF8(aRemoteType).get()));
contentParent = new ContentParent(aOpener, aRemoteType);
if (!contentParent->BeginSubprocessLaunch(aIsSync, aPriority)) {
// Launch aborted because of shutdown. Bailout.
@ -912,9 +1017,12 @@ ContentParent::GetNewOrUsedBrowserProcessInternal(Element* aFrameElement,
// Until the new process is ready let's not allow to start up any
// preallocated processes. The blocker will be removed once we receive
// the first idle message.
PreallocatedProcessManager::AddBlocker(contentParent);
contentParent->mIsAPreallocBlocker = true;
PreallocatedProcessManager::AddBlocker(aRemoteType, contentParent);
MOZ_ASSERT(contentParent->IsLaunching());
MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
("GetNewOrUsedProcess: new process %p", contentParent.get()));
return contentParent.forget();
}
@ -1412,6 +1520,8 @@ void ContentParent::Init() {
}
void ContentParent::MaybeAsyncSendShutDownMessage() {
MOZ_LOG(ContentParent::GetLog(), LogLevel::Verbose,
("MaybeAsyncSendShutDownMessage %p", this));
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!TryToRecycle());
@ -1554,6 +1664,8 @@ void ContentParent::RemoveFromList() {
}
void ContentParent::MarkAsDead() {
MOZ_LOG(ContentParent::GetLog(), LogLevel::Verbose,
("Marking ContentProcess %p as dead", this));
if (!mShutdownPending) {
RemoveFromList();
}
@ -1717,10 +1829,21 @@ void ContentParent::ActorDestroy(ActorDestroyReason why) {
}
mIdleListeners.Clear();
MOZ_LOG(ContentParent::GetLog(), LogLevel::Verbose,
("destroying Subprocess in ActorDestroy: ContentParent %p "
"mSubprocess %p handle %ld",
this, mSubprocess,
mSubprocess ? (long)mSubprocess->GetChildProcessHandle() : -1));
// FIXME (bug 1520997): does this really need an additional dispatch?
MessageLoop::current()->PostTask(NS_NewRunnableFunction(
"DelayedDeleteSubprocessRunnable",
[subprocess = mSubprocess] { subprocess->Destroy(); }));
"DelayedDeleteSubprocessRunnable", [subprocess = mSubprocess] {
MOZ_LOG(
ContentParent::GetLog(), LogLevel::Debug,
("destroyed Subprocess in ActorDestroy: Subprocess %p handle %ld",
subprocess,
subprocess ? (long)subprocess->GetChildProcessHandle() : -1));
subprocess->Destroy();
}));
mSubprocess = nullptr;
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
@ -1754,23 +1877,53 @@ void ContentParent::ActorDestroy(ActorDestroyReason why) {
void ContentParent::ActorDealloc() { mSelfRef = nullptr; }
bool ContentParent::TryToRecycle() {
// This life time check should be replaced by a memory health check (memory
// usage + fragmentation).
const double kMaxLifeSpan = 5;
if (mShutdownPending || mCalledKillHard || !IsAlive() ||
!mRemoteType.EqualsLiteral(DEFAULT_REMOTE_TYPE) ||
(TimeStamp::Now() - mActivateTS).ToSeconds() > kMaxLifeSpan ||
!PreallocatedProcessManager::Provide(this)) {
// We can only do this if we have a separate cache for recycled
// 'web' processes, and handle them differently than webIsolated ones
if (!mRemoteType.EqualsLiteral(DEFAULT_REMOTE_TYPE)) {
return false;
}
// This life time check should be replaced by a memory health check (memory
// usage + fragmentation).
// The PreallocatedProcessManager took over the ownership let's not keep a
// reference to it, until we don't take it back.
RemoveFromList();
// Note that this is specifically to help with edge cases that rapidly
// create-and-destroy processes
const double kMaxLifeSpan = 5;
MOZ_LOG(
ContentParent::GetLog(), LogLevel::Debug,
("TryToRecycle ContentProcess %p (%u) with lifespan %f seconds", this,
(unsigned int)ChildID(), (TimeStamp::Now() - mActivateTS).ToSeconds()));
if (mShutdownPending || mCalledKillHard || !IsAlive() ||
!mRemoteType.EqualsLiteral(DEFAULT_REMOTE_TYPE) ||
(TimeStamp::Now() - mActivateTS).ToSeconds() > kMaxLifeSpan) {
MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
("TryToRecycle did not take ownership of %p", this));
// It's possible that the process was already cached via Provide() (such
// as from TabDestroyed), and we're being called from a different path,
// such as UnregisterRemoveWorkerActor(), and we're now past kMaxLifeSpan
// (or some other). Ensure that if we're going to destroy this process
// that we don't have it in the cache.
PreallocatedProcessManager::Erase(this);
return false;
} else {
// This will either cache it and take ownership, realize it was already
// cached (due to this being called a second time via a different
// path), or it will decide to not take ownership (if it has another
// already cached)
bool retval = PreallocatedProcessManager::Provide(this);
MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
("Provide did %stake ownership of %p", retval ? "" : "not ", this));
if (retval) {
// The PreallocatedProcessManager took over the ownership let's not keep a
// reference to it
RemoveFromList();
}
return retval;
}
return true;
}
bool ContentParent::ShouldKeepProcessAlive() {
bool ContentParent::HasActiveWorkerOrJSPlugin() {
if (IsForJSPlugin()) {
return true;
}
@ -1782,6 +1935,13 @@ bool ContentParent::ShouldKeepProcessAlive() {
return true;
}
}
return false;
}
bool ContentParent::ShouldKeepProcessAlive() {
if (HasActiveWorkerOrJSPlugin()) {
return true;
}
if (!sBrowserContentParents) {
return false;
@ -1839,6 +1999,8 @@ void ContentParent::NotifyTabDestroying() {
return;
}
MOZ_LOG(ContentParent::GetLog(), LogLevel::Verbose,
("NotifyTabDestroying %p", this));
if (TryToRecycle()) {
return;
}
@ -1885,8 +2047,11 @@ void ContentParent::NotifyTabDestroyed(const TabId& aTabId,
// There can be more than one PBrowser for a given app process
// because of popup windows. When the last one closes, shut
// us down.
MOZ_LOG(ContentParent::GetLog(), LogLevel::Verbose,
("NotifyTabDestroyed %p", this));
if (ManagedPBrowserParent().Count() == 1 && !ShouldKeepProcessAlive() &&
!TryToRecycle()) {
MarkAsDead();
MaybeAsyncSendShutDownMessage();
}
}
@ -2091,7 +2256,10 @@ void ContentParent::LaunchSubprocessReject() {
// Now that communication with the child is complete, we can cleanup
// the preference serializer.
mPrefSerializer = nullptr;
PreallocatedProcessManager::RemoveBlocker(this);
if (mIsAPreallocBlocker) {
PreallocatedProcessManager::RemoveBlocker(mRemoteType, this);
mIsAPreallocBlocker = false;
}
MarkAsDead();
}
@ -2103,6 +2271,16 @@ bool ContentParent::LaunchSubprocessResolve(bool aIsSync,
mPrefSerializer = nullptr;
const auto launchResumeTS = TimeStamp::Now();
#ifdef MOZ_GECKO_PROFILER
if (profiler_thread_is_being_profiled()) {
nsPrintfCString marker("Process start%s for %u",
mIsAPreallocBlocker ? " (immediate)" : "",
(unsigned int)ChildID());
PROFILER_ADD_MARKER_WITH_PAYLOAD(
mIsAPreallocBlocker ? "Process Immediate Launch" : "Process Launch",
DOM, TextMarkerPayload, (marker, mLaunchTS, launchResumeTS));
}
#endif
if (!sCreatedFirstContentProcess) {
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
@ -2208,6 +2386,7 @@ ContentParent::ContentParent(ContentParent* aOpener,
mLaunchYieldTS(mLaunchTS),
mActivateTS(mLaunchTS),
mOpener(aOpener),
mIsAPreallocBlocker(false),
mRemoteType(aRemoteType),
mChildID(gContentChildID++),
mGeolocationWatchID(-1),
@ -2250,6 +2429,10 @@ ContentParent::ContentParent(ContentParent* aOpener,
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
bool isFile = mRemoteType.EqualsLiteral(FILE_REMOTE_TYPE);
mSubprocess = new GeckoChildProcessHost(GeckoProcessType_Content, isFile);
MOZ_LOG(ContentParent::GetLog(), LogLevel::Verbose,
("CreateSubprocess: ContentParent %p mSubprocess %p handle %ld", this,
mSubprocess,
mSubprocess ? (long)mSubprocess->GetChildProcessHandle() : -1));
}
ContentParent::~ContentParent() {
@ -2259,6 +2442,13 @@ ContentParent::~ContentParent() {
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
if (mIsAPreallocBlocker) {
MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
("Removing blocker on ContentProcess destruction"));
PreallocatedProcessManager::RemoveBlocker(mRemoteType, this);
mIsAPreallocBlocker = false;
}
// We should be removed from all these lists in ActorDestroy.
MOZ_ASSERT(!sPrivateContent || !sPrivateContent->Contains(this));
if (IsForJSPlugin()) {
@ -2267,12 +2457,18 @@ ContentParent::~ContentParent() {
} else {
MOZ_ASSERT(!sBrowserContentParents ||
!sBrowserContentParents->Contains(mRemoteType) ||
!sBrowserContentParents->Get(mRemoteType)->Contains(this));
!sBrowserContentParents->Get(mRemoteType)->Contains(this) ||
sCanLaunchSubprocesses ==
false); // aka in shutdown - avoid timing issues
}
// Normally mSubprocess is destroyed in ActorDestroy, but that won't
// happen if the process wasn't launched or if it failed to launch.
if (mSubprocess) {
MOZ_LOG(ContentParent::GetLog(), LogLevel::Verbose,
("DestroySubprocess: ContentParent %p mSubprocess %p handle %ld",
this, mSubprocess,
mSubprocess ? (long)mSubprocess->GetChildProcessHandle() : -1));
mSubprocess->Destroy();
}
}
@ -2280,6 +2476,8 @@ ContentParent::~ContentParent() {
bool ContentParent::InitInternal(ProcessPriority aInitialPriority) {
XPCOMInitData xpcomInit;
MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
("ContentParent::InitInternal: %p", (void*)this));
nsCOMPtr<nsIIOService> io(do_GetIOService());
MOZ_ASSERT(io, "No IO service?");
DebugOnly<nsresult> rv = io->GetOffline(&xpcomInit.isOffline());
@ -2865,7 +3063,10 @@ mozilla::ipc::IPCResult ContentParent::RecvFirstIdle() {
// When the ContentChild goes idle, it sends us a FirstIdle message
// which we use as a good time to signal the PreallocatedProcessManager
// that it can start allocating processes from now on.
PreallocatedProcessManager::RemoveBlocker(this);
if (mIsAPreallocBlocker) {
PreallocatedProcessManager::RemoveBlocker(mRemoteType, this);
mIsAPreallocBlocker = false;
}
return IPC_OK();
}
@ -3363,6 +3564,10 @@ void ContentParent::KillHard(const char* aReason) {
}
if (mSubprocess) {
MOZ_LOG(ContentParent::GetLog(), LogLevel::Verbose,
("KillHard Subprocess: ContentParent %p mSubprocess %p handle %ld",
this, mSubprocess,
mSubprocess ? (long)mSubprocess->GetChildProcessHandle() : -1));
mSubprocess->SetAlreadyDead();
}
@ -5993,8 +6198,11 @@ void ContentParent::UnregisterRemoveWorkerActor() {
}
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
MOZ_LOG(ContentParent::GetLog(), LogLevel::Verbose,
("UnregisterRemoveWorkerActor %p", this));
if (!cpm->GetBrowserParentCountByProcessId(ChildID()) &&
!ShouldKeepProcessAlive() && !TryToRecycle()) {
MarkAsDead();
MaybeAsyncSendShutDownMessage();
}
}

Просмотреть файл

@ -54,15 +54,16 @@
// Process names as reported by about:memory are defined in
// ContentChild:RecvRemoteType. Add your value there too or it will be called
// "Web Content".
#define PREALLOC_REMOTE_TYPE "prealloc"
#define DEFAULT_REMOTE_TYPE "web"
#define FISSION_WEB_REMOTE_TYPE "webIsolated"
#define FILE_REMOTE_TYPE "file"
#define EXTENSION_REMOTE_TYPE "extension"
#define PRIVILEGEDABOUT_REMOTE_TYPE "privilegedabout"
#define PRIVILEGEDMOZILLA_REMOTE_TYPE "privilegedmozilla"
#define WITH_COOP_COEP_REMOTE_TYPE_PREFIX "webCOOP+COEP="
// This must start with the DEFAULT_REMOTE_TYPE above.
// These must start with the DEFAULT_REMOTE_TYPE above.
#define FISSION_WEB_REMOTE_TYPE "webIsolated"
#define WITH_COOP_COEP_REMOTE_TYPE_PREFIX "webCOOP+COEP="
#define LARGE_ALLOCATION_REMOTE_TYPE "webLargeAllocation"
class nsConsoleService;
@ -161,6 +162,8 @@ class ContentParent final
NS_DECLARE_STATIC_IID_ACCESSOR(NS_CONTENTPARENT_IID)
static LogModule* GetLog();
/**
* Create a subprocess suitable for use later as a content process.
*/
@ -786,6 +789,11 @@ class ContentParent final
*/
void RemoveFromList();
/**
* Return if the process has an active worker or JSPlugin
*/
bool HasActiveWorkerOrJSPlugin();
/**
* Decide whether the process should be kept alive even when it would normally
* be shut down, for example when all its tabs are closed.
@ -1343,6 +1351,8 @@ class ContentParent final
TimeStamp mActivateTS;
ContentParent* mOpener;
bool mIsAPreallocBlocker; // We called AddBlocker for this ContentParent
nsString mRemoteType;
ContentParentId mChildID;

Просмотреть файл

@ -11,10 +11,12 @@
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/StaticPrefs_dom.h"
#include "mozilla/StaticPrefs_fission.h"
#include "nsIPropertyBag2.h"
#include "ProcessPriorityManager.h"
#include "nsServiceManagerUtils.h"
#include "nsIXULRuntime.h"
#include <deque>
using namespace mozilla::hal;
using namespace mozilla::dom;
@ -25,6 +27,8 @@ namespace mozilla {
* PreallocatedProcessManager.
*/
class PreallocatedProcessManagerImpl final : public nsIObserver {
friend class PreallocatedProcessManager;
public:
static PreallocatedProcessManagerImpl* Singleton();
@ -34,13 +38,14 @@ class PreallocatedProcessManagerImpl final : public nsIObserver {
// See comments on PreallocatedProcessManager for these methods.
void AddBlocker(ContentParent* aParent);
void RemoveBlocker(ContentParent* aParent);
already_AddRefed<ContentParent> Take();
already_AddRefed<ContentParent> Take(const nsAString& aRemoteType);
bool Provide(ContentParent* aParent);
void Erase(ContentParent* aParent);
private:
static const char* const kObserverTopics[];
static mozilla::StaticRefPtr<PreallocatedProcessManagerImpl> sSingleton;
static StaticRefPtr<PreallocatedProcessManagerImpl> sSingleton;
PreallocatedProcessManagerImpl();
~PreallocatedProcessManagerImpl();
@ -54,21 +59,31 @@ class PreallocatedProcessManagerImpl final : public nsIObserver {
void AllocateNow();
void RereadPrefs();
void Enable();
void Enable(uint32_t aProcesses);
void Disable();
void CloseProcess();
void CloseProcesses();
void ObserveProcessShutdown(nsISupports* aSubject);
bool IsEmpty() const {
return mPreallocatedProcesses.empty() && !mLaunchInProgress;
}
bool mEnabled;
bool mShutdown;
bool mLaunchInProgress;
RefPtr<ContentParent> mPreallocatedProcess;
nsTHashtable<nsUint64HashKey> mBlockers;
bool IsEmpty() const { return !mPreallocatedProcess && !mLaunchInProgress; }
uint32_t mNumberPreallocs;
std::deque<RefPtr<ContentParent>> mPreallocatedProcesses;
RefPtr<ContentParent> mPreallocatedE10SProcess; // There can be only one
// Even if we have multiple PreallocatedProcessManagerImpls, we'll have
// one blocker counter
static uint32_t sNumBlockers;
TimeStamp mBlockingStartTime;
};
/* static */
uint32_t PreallocatedProcessManagerImpl::sNumBlockers = 0;
const char* const PreallocatedProcessManagerImpl::kObserverTopics[] = {
"ipc:content-shutdown",
"memory-pressure",
@ -84,18 +99,22 @@ StaticRefPtr<PreallocatedProcessManagerImpl>
PreallocatedProcessManagerImpl* PreallocatedProcessManagerImpl::Singleton() {
MOZ_ASSERT(NS_IsMainThread());
if (!sSingleton) {
sSingleton = new PreallocatedProcessManagerImpl();
sSingleton = new PreallocatedProcessManagerImpl;
sSingleton->Init();
ClearOnShutdown(&sSingleton);
ClearOnShutdown(&sSingleton,
ShutdownPhase::ShutdownPostLastCycleCollection);
}
return sSingleton;
// PreallocatedProcessManagers live until shutdown
}
NS_IMPL_ISUPPORTS(PreallocatedProcessManagerImpl, nsIObserver)
PreallocatedProcessManagerImpl::PreallocatedProcessManagerImpl()
: mEnabled(false), mShutdown(false), mLaunchInProgress(false) {}
: mEnabled(false),
mShutdown(false),
mLaunchInProgress(false),
mNumberPreallocs(1) {}
PreallocatedProcessManagerImpl::~PreallocatedProcessManagerImpl() {
// This shouldn't happen, because the promise callbacks should
@ -108,6 +127,11 @@ void PreallocatedProcessManagerImpl::Init() {
// We have to respect processCount at all time. This is especially important
// for testing.
Preferences::AddStrongObserver(this, "dom.ipc.processCount");
// A StaticPref, but we need to adjust the number of preallocated processes
// if the value goes up or down, so we need to run code on change.
Preferences::AddStrongObserver(this,
"dom.ipc.processPrelaunch.fission.number");
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
MOZ_ASSERT(os);
for (auto topic : kObserverTopics) {
@ -129,6 +153,9 @@ PreallocatedProcessManagerImpl::Observe(nsISupports* aSubject,
!strcmp("profile-change-teardown", aTopic)) {
Preferences::RemoveObserver(this, "dom.ipc.processPrelaunch.enabled");
Preferences::RemoveObserver(this, "dom.ipc.processCount");
Preferences::RemoveObserver(this,
"dom.ipc.processPrelaunch.fission.number");
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
MOZ_ASSERT(os);
for (auto topic : kObserverTopics) {
@ -136,11 +163,11 @@ PreallocatedProcessManagerImpl::Observe(nsISupports* aSubject,
}
// Let's prevent any new preallocated processes from starting. ContentParent
// will handle the shutdown of the existing process and the
// mPreallocatedProcess reference will be cleared by the ClearOnShutdown of
// the manager singleton.
// mPreallocatedProcesses reference will be cleared by the ClearOnShutdown
// of the manager singleton.
mShutdown = true;
} else if (!strcmp("memory-pressure", aTopic)) {
CloseProcess();
CloseProcesses();
} else {
MOZ_ASSERT_UNREACHABLE("Unknown topic");
}
@ -151,47 +178,84 @@ PreallocatedProcessManagerImpl::Observe(nsISupports* aSubject,
void PreallocatedProcessManagerImpl::RereadPrefs() {
if (mozilla::BrowserTabsRemoteAutostart() &&
Preferences::GetBool("dom.ipc.processPrelaunch.enabled")) {
Enable();
int32_t number = 1;
if (StaticPrefs::fission_autostart()) {
number = StaticPrefs::dom_ipc_processPrelaunch_fission_number();
}
if (number >= 0) {
Enable(number);
// We have one prealloc queue for all types except File now
if (static_cast<uint64_t>(number) < mPreallocatedProcesses.size()) {
CloseProcesses();
}
}
} else {
Disable();
}
if (ContentParent::IsMaxProcessCountReached(
NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE))) {
CloseProcess();
}
}
already_AddRefed<ContentParent> PreallocatedProcessManagerImpl::Take() {
already_AddRefed<ContentParent> PreallocatedProcessManagerImpl::Take(
const nsAString& aRemoteType) {
if (!mEnabled || mShutdown) {
return nullptr;
}
if (mPreallocatedProcess) {
// The preallocated process is taken. Let's try to start up a new one soon.
ProcessPriorityManager::SetProcessPriority(mPreallocatedProcess,
PROCESS_PRIORITY_FOREGROUND);
AllocateOnIdle();
RefPtr<ContentParent> process;
if (aRemoteType.EqualsLiteral(DEFAULT_REMOTE_TYPE)) {
// we can recycle processes via Provide() for e10s only
process = mPreallocatedE10SProcess.forget();
if (process) {
MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
("Reuse " DEFAULT_REMOTE_TYPE " process %p",
mPreallocatedE10SProcess.get()));
}
}
return mPreallocatedProcess.forget();
if (!process && !mPreallocatedProcesses.empty()) {
process = mPreallocatedProcesses.front().forget();
mPreallocatedProcesses.pop_front(); // holds a nullptr
// We took a preallocated process. Let's try to start up a new one
// soon.
AllocateOnIdle();
MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
("Use " PREALLOC_REMOTE_TYPE " process %p", process.get()));
}
if (process) {
ProcessPriorityManager::SetProcessPriority(process,
PROCESS_PRIORITY_FOREGROUND);
}
return process.forget();
}
bool PreallocatedProcessManagerImpl::Provide(ContentParent* aParent) {
MOZ_DIAGNOSTIC_ASSERT(
aParent->GetRemoteType().EqualsLiteral(DEFAULT_REMOTE_TYPE));
// This will take the already-running process even if there's a
// launch in progress; if that process hasn't been taken by the
// time the launch completes, the new process will be shut down.
if (mEnabled && !mShutdown && !mPreallocatedProcess) {
mPreallocatedProcess = aParent;
if (mEnabled && !mShutdown && !mPreallocatedE10SProcess) {
MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
("Store for reuse " DEFAULT_REMOTE_TYPE " process %p", aParent));
ProcessPriorityManager::SetProcessPriority(aParent,
PROCESS_PRIORITY_BACKGROUND);
mPreallocatedE10SProcess = aParent;
return true;
}
// We might get a call from both NotifyTabDestroying and NotifyTabDestroyed
// with the same ContentParent. Returning true here for both calls is
// important to avoid the cached process to be destroyed.
return aParent == mPreallocatedProcess;
return aParent == mPreallocatedE10SProcess;
}
void PreallocatedProcessManagerImpl::Enable() {
void PreallocatedProcessManagerImpl::Erase(ContentParent* aParent) {
// Ensure this ContentParent isn't cached
if (mPreallocatedE10SProcess == aParent) {
mPreallocatedE10SProcess = nullptr;
}
}
void PreallocatedProcessManagerImpl::Enable(uint32_t aProcesses) {
mNumberPreallocs = aProcesses;
if (mEnabled) {
return;
}
@ -201,13 +265,13 @@ void PreallocatedProcessManagerImpl::Enable() {
}
void PreallocatedProcessManagerImpl::AddBlocker(ContentParent* aParent) {
uint64_t childID = aParent->ChildID();
MOZ_ASSERT(!mBlockers.Contains(childID));
mBlockers.PutEntry(childID);
if (sNumBlockers == 0) {
mBlockingStartTime = TimeStamp::Now();
}
sNumBlockers++;
}
void PreallocatedProcessManagerImpl::RemoveBlocker(ContentParent* aParent) {
uint64_t childID = aParent->ChildID();
// This used to assert that the blocker existed, but preallocated
// processes aren't blockers anymore because it's not useful and
// interferes with async launch, and it's simpler if content
@ -215,16 +279,28 @@ void PreallocatedProcessManagerImpl::RemoveBlocker(ContentParent* aParent) {
// (And preallocated processes can't AddBlocker when taken, because
// it's possible for a short-lived process to be recycled through
// Provide() and Take() before reaching RecvFirstIdle.)
mBlockers.RemoveEntry(childID);
if (IsEmpty() && mBlockers.IsEmpty()) {
AllocateAfterDelay();
MOZ_DIAGNOSTIC_ASSERT(sNumBlockers > 0);
sNumBlockers--;
if (sNumBlockers == 0) {
MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
("Blocked preallocation for %fms",
(TimeStamp::Now() - mBlockingStartTime).ToMilliseconds()));
PROFILER_ADD_TEXT_MARKER(
"Process", NS_LITERAL_CSTRING("Blocked preallocation"),
JS::ProfilingCategoryPair::DOM, mBlockingStartTime, TimeStamp::Now());
if (IsEmpty()) {
AllocateAfterDelay();
}
}
}
bool PreallocatedProcessManagerImpl::CanAllocate() {
return mEnabled && mBlockers.IsEmpty() && IsEmpty() && !mShutdown &&
!ContentParent::IsMaxProcessCountReached(
NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE));
return mEnabled && sNumBlockers == 0 &&
mPreallocatedProcesses.size() < mNumberPreallocs && !mShutdown &&
(StaticPrefs::fission_autostart() ||
!ContentParent::IsMaxProcessCountReached(
NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE)));
}
void PreallocatedProcessManagerImpl::AllocateAfterDelay() {
@ -251,7 +327,7 @@ void PreallocatedProcessManagerImpl::AllocateOnIdle() {
void PreallocatedProcessManagerImpl::AllocateNow() {
if (!CanAllocate()) {
if (mEnabled && !mShutdown && IsEmpty() && !mBlockers.IsEmpty()) {
if (mEnabled && !mShutdown && IsEmpty() && sNumBlockers > 0) {
// If it's too early to allocate a process let's retry later.
AllocateAfterDelay();
}
@ -267,7 +343,22 @@ void PreallocatedProcessManagerImpl::AllocateNow() {
[self, this](const RefPtr<ContentParent>& process) {
mLaunchInProgress = false;
if (CanAllocate()) {
mPreallocatedProcess = process;
// slight perf reason for push_back - while the cpu cache
// probably has stack/etc associated with the most recent
// process created, we don't know that it has finished startup.
// If we added it to the queue on completion of startup, we
// could push_front it, but that would require a bunch more
// logic.
mPreallocatedProcesses.push_back(process);
MOZ_LOG(
ContentParent::GetLog(), LogLevel::Debug,
("Preallocated = %lu of %d processes",
(unsigned long)mPreallocatedProcesses.size(), mNumberPreallocs));
// Continue prestarting processes if needed
if (mPreallocatedProcesses.size() < mNumberPreallocs) {
AllocateOnIdle();
}
} else {
process->ShutDownProcess(ContentParent::SEND_SHUTDOWN_MESSAGE);
}
@ -284,13 +375,20 @@ void PreallocatedProcessManagerImpl::Disable() {
}
mEnabled = false;
CloseProcess();
CloseProcesses();
}
void PreallocatedProcessManagerImpl::CloseProcess() {
if (mPreallocatedProcess) {
mPreallocatedProcess->ShutDownProcess(ContentParent::SEND_SHUTDOWN_MESSAGE);
mPreallocatedProcess = nullptr;
void PreallocatedProcessManagerImpl::CloseProcesses() {
while (!mPreallocatedProcesses.empty()) {
RefPtr<ContentParent> process(mPreallocatedProcesses.front().forget());
mPreallocatedProcesses.pop_front();
process->ShutDownProcess(ContentParent::SEND_SHUTDOWN_MESSAGE);
// drop ref and let it free
}
if (mPreallocatedE10SProcess) {
mPreallocatedE10SProcess->ShutDownProcess(
ContentParent::SEND_SHUTDOWN_MESSAGE);
mPreallocatedE10SProcess = nullptr;
}
}
@ -303,11 +401,14 @@ void PreallocatedProcessManagerImpl::ObserveProcessShutdown(
props->GetPropertyAsUint64(NS_LITERAL_STRING("childID"), &childID);
NS_ENSURE_TRUE_VOID(childID != CONTENT_PROCESS_ID_UNKNOWN);
if (mPreallocatedProcess && childID == mPreallocatedProcess->ChildID()) {
mPreallocatedProcess = nullptr;
for (auto it = mPreallocatedProcesses.begin();
it != mPreallocatedProcesses.end(); it++) {
if (childID == (*it)->ChildID()) {
mPreallocatedProcesses.erase(it);
break;
}
}
mBlockers.RemoveEntry(childID);
// The ContentParent is responsible for removing itself as a blocker
}
inline PreallocatedProcessManagerImpl* GetPPMImpl() {
@ -315,18 +416,29 @@ inline PreallocatedProcessManagerImpl* GetPPMImpl() {
}
/* static */
void PreallocatedProcessManager::AddBlocker(ContentParent* aParent) {
void PreallocatedProcessManager::AddBlocker(const nsAString& aRemoteType,
ContentParent* aParent) {
MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
("AddBlocker: %s %p (sNumBlockers=%d)",
NS_ConvertUTF16toUTF8(aRemoteType).get(), aParent,
PreallocatedProcessManagerImpl::sNumBlockers));
GetPPMImpl()->AddBlocker(aParent);
}
/* static */
void PreallocatedProcessManager::RemoveBlocker(ContentParent* aParent) {
void PreallocatedProcessManager::RemoveBlocker(const nsAString& aRemoteType,
ContentParent* aParent) {
MOZ_LOG(ContentParent::GetLog(), LogLevel::Debug,
("RemoveBlocker: %s %p (sNumBlockers=%d)",
NS_ConvertUTF16toUTF8(aRemoteType).get(), aParent,
PreallocatedProcessManagerImpl::sNumBlockers));
GetPPMImpl()->RemoveBlocker(aParent);
}
/* static */
already_AddRefed<ContentParent> PreallocatedProcessManager::Take() {
return GetPPMImpl()->Take();
already_AddRefed<ContentParent> PreallocatedProcessManager::Take(
const nsAString& aRemoteType) {
return GetPPMImpl()->Take(aRemoteType);
}
/* static */
@ -334,4 +446,9 @@ bool PreallocatedProcessManager::Provide(ContentParent* aParent) {
return GetPPMImpl()->Provide(aParent);
}
/* static */
void PreallocatedProcessManager::Erase(ContentParent* aParent) {
GetPPMImpl()->Erase(aParent);
}
} // namespace mozilla

Просмотреть файл

@ -37,23 +37,30 @@ class PreallocatedProcessManager final {
* background. To avoid that, the PreallocatedProcessManager won't start up
* any processes while there is a blocker active.
*/
static void AddBlocker(ContentParent* aParent);
static void RemoveBlocker(ContentParent* aParent);
static void AddBlocker(const nsAString& aRemoteType, ContentParent* aParent);
static void RemoveBlocker(const nsAString& aRemoteType,
ContentParent* aParent);
/**
* Take the preallocated process, if we have one. If we don't have one, this
* returns null.
* Take the preallocated process, if we have one, or a recycled
* process cached via Provide(). Currently we only cache
* DEFAULT_REMOTE_TYPE ('web') processes and only reuse them for that
* type. If we don't have a process to return (cached or preallocated),
* this returns null.
*
* If you call Take() twice in a row, the second call is guaranteed to return
* null.
*
* After you Take() the preallocated process, you need to call one of the
* Allocate* functions (or change the dom.ipc.processPrelaunch pref from
* false to true) before we'll create a new process.
* If we use a preallocated process, it will schedule the start of
* another on Idle (AllocateOnIdle()).
*/
static already_AddRefed<ContentParent> Take();
static already_AddRefed<ContentParent> Take(const nsAString& aRemoteType);
/**
* Cache a process (currently only DEFAULT_REMOTE_TYPE) for reuse later
* via Take(). Returns true if we cached the process, and false if
* another process is already cached (so the caller knows to destroy it).
* This takes a reference to the ContentParent if it is cached.
*/
static bool Provide(ContentParent* aParent);
static void Erase(ContentParent* aParent);
private:
PreallocatedProcessManager();

Просмотреть файл

@ -808,6 +808,8 @@ void ParticularProcessPriorityManager::TabActivityChanged(
void ParticularProcessPriorityManager::ShutDown() {
MOZ_ASSERT(mContentParent);
LOGP("shutdown for %p (mContentParent %p)", this, mContentParent);
UnregisterWakeLockObserver(this);
if (mResetPriorityTimer) {
@ -942,6 +944,7 @@ void ProcessPriorityManager::Init() {
void ProcessPriorityManager::SetProcessPriority(ContentParent* aContentParent,
ProcessPriority aPriority) {
MOZ_ASSERT(aContentParent);
MOZ_ASSERT(aContentParent->Pid() != -1);
ProcessPriorityManagerImpl* singleton =
ProcessPriorityManagerImpl::GetSingleton();

Просмотреть файл

@ -1904,7 +1904,7 @@
value: false
mirror: always
# Process launch delay (im milliseconds).
# Process launch delay (in milliseconds).
- name: dom.ipc.processPrelaunch.delayMs
type: uint32_t
# This number is fairly arbitrary ... the intention is to put off
@ -1913,6 +1913,13 @@
value: 1000
mirror: always
# Process preallocation cache
# Only used in fission; in e10s we use 1 always
- name: dom.ipc.processPrelaunch.fission.number
type: uint32_t
value: 3
mirror: always
- name: dom.ipc.processPriorityManager.enabled
type: bool
value: false

Просмотреть файл

@ -18,7 +18,8 @@ class GeckoChildProcessHost;
}
// Process types. When updating this enum, please make sure to update
// WebIDLProcType and ProcTypeToWebIDL to mirror the changes.
// WebIDLProcType, ChromeUtils::RequestProcInfo and ProcTypeToWebIDL to
// mirror the changes.
enum class ProcType {
// These must match the ones in ContentParent.h, and E10SUtils.jsm
Web,
@ -42,6 +43,7 @@ enum class ProcType {
#ifdef MOZ_ENABLE_FORKSERVER
ForkServer,
#endif
Preallocated,
// Unknown type of process
Unknown,
Max = Unknown,