Bug 1478124: Part 3 - Add a lookup table for ProcessMatchesSelector. r=froydnj

Currently, when we build the component registry at startup, we exclude any
entry with a process selector which doesn't match the current process. When we
switch to static lookup tables, however, that check is going to have to happen
for every lookup, since we can't alter the table at runtime.

That may not matter much, given how expensive the rest of the component lookup
code is relative to ProcessMatchesSelector, but it's also easy and cheap
enough to generate a lookup table for all possible ProcessSelector values, and
do a quick index check instead.

Differential Revision: https://phabricator.services.mozilla.com/D15033

--HG--
extra : rebase_source : fa6c764c2acd68dbe620e5a0779c6c58724ea209
This commit is contained in:
Kris Maglione 2018-12-18 14:48:53 -08:00
Родитель d3b05e8dad
Коммит 2b2a2a06e7
3 изменённых файлов: 82 добавлений и 28 удалений

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

@ -39,6 +39,8 @@ struct Module {
* This selector allows CIDEntrys to be marked so that they're only loaded
* into certain kinds of processes. Selectors can be combined.
*/
// Note: This must be kept in sync with the selector matching in
// nsComponentManager.cpp.
enum ProcessSelector {
ANY_PROCESS = 0x0,
MAIN_PROCESS_ONLY = 0x1,
@ -59,6 +61,9 @@ struct Module {
ALLOW_IN_GPU_PROCESS | ALLOW_IN_VR_PROCESS | ALLOW_IN_SOCKET_PROCESS
};
static constexpr size_t kMaxProcessSelector =
size_t(ProcessSelector::ALLOW_IN_GPU_VR_AND_SOCKET_PROCESS);
/**
* The constructor callback is an implementation detail of the default binary
* loader and may be null.

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

@ -67,6 +67,7 @@
#endif
using namespace mozilla;
using namespace mozilla::xpcom;
static LazyLogModule nsComponentManagerLog("nsComponentManager");
@ -117,6 +118,45 @@ nsresult nsGetServiceFromCategory::operator()(const nsIID& aIID,
return rv;
}
namespace mozilla {
namespace xpcom {
using ProcessSelector = Module::ProcessSelector;
// Note: These must be kept in sync with the ProcessSelector definition in
// Module.h.
bool ProcessSelectorMatches(ProcessSelector aSelector) {
GeckoProcessType type = XRE_GetProcessType();
if (type == GeckoProcessType_GPU || type == GeckoProcessType_RDD) {
return !!(aSelector & Module::ALLOW_IN_GPU_PROCESS);
}
if (type == GeckoProcessType_Socket) {
return !!(aSelector & (Module::ALLOW_IN_SOCKET_PROCESS));
}
if (type == GeckoProcessType_VR) {
return !!(aSelector & Module::ALLOW_IN_VR_PROCESS);
}
if (aSelector & Module::MAIN_PROCESS_ONLY) {
return type == GeckoProcessType_Default;
}
if (aSelector & Module::CONTENT_PROCESS_ONLY) {
return type == GeckoProcessType_Content;
}
return true;
}
static bool gProcessMatchTable[Module::kMaxProcessSelector + 1];
bool FastProcessSelectorMatches(ProcessSelector aSelector) {
return gProcessMatchTable[size_t(aSelector)];
}
} // namespace xpcom
} // namespace mozilla
// GetService and a few other functions need to exit their mutex mid-function
// without reentering it later in the block. This class supports that
// style of early-exit that MutexAutoUnlock doesn't.
@ -314,6 +354,27 @@ nsTArray<nsComponentManagerImpl::ComponentLocation>*
}
nsresult nsComponentManagerImpl::Init() {
{
gProcessMatchTable[size_t(ProcessSelector::ANY_PROCESS)] =
ProcessSelectorMatches(ProcessSelector::ANY_PROCESS);
gProcessMatchTable[size_t(ProcessSelector::MAIN_PROCESS_ONLY)] =
ProcessSelectorMatches(ProcessSelector::MAIN_PROCESS_ONLY);
gProcessMatchTable[size_t(ProcessSelector::CONTENT_PROCESS_ONLY)] =
ProcessSelectorMatches(ProcessSelector::CONTENT_PROCESS_ONLY);
gProcessMatchTable[size_t(ProcessSelector::ALLOW_IN_GPU_PROCESS)] =
ProcessSelectorMatches(ProcessSelector::ALLOW_IN_GPU_PROCESS);
gProcessMatchTable[size_t(ProcessSelector::ALLOW_IN_VR_PROCESS)] =
ProcessSelectorMatches(ProcessSelector::ALLOW_IN_VR_PROCESS);
gProcessMatchTable[size_t(ProcessSelector::ALLOW_IN_SOCKET_PROCESS)] =
ProcessSelectorMatches(ProcessSelector::ALLOW_IN_SOCKET_PROCESS);
gProcessMatchTable[size_t(ProcessSelector::ALLOW_IN_GPU_AND_VR_PROCESS)] =
ProcessSelectorMatches(ProcessSelector::ALLOW_IN_GPU_AND_VR_PROCESS);
gProcessMatchTable[size_t(ProcessSelector::ALLOW_IN_GPU_AND_SOCKET_PROCESS)] =
ProcessSelectorMatches(ProcessSelector::ALLOW_IN_GPU_AND_SOCKET_PROCESS);
gProcessMatchTable[size_t(ProcessSelector::ALLOW_IN_GPU_VR_AND_SOCKET_PROCESS)] =
ProcessSelectorMatches(ProcessSelector::ALLOW_IN_GPU_VR_AND_SOCKET_PROCESS);
}
MOZ_ASSERT(NOT_INITIALIZED == mStatus);
nsCOMPtr<nsIFile> greDir = GetLocationFromDirectoryService(NS_GRE_DIR);
@ -437,29 +498,6 @@ nsresult nsComponentManagerImpl::Init() {
return NS_OK;
}
static bool ProcessSelectorMatches(Module::ProcessSelector aSelector) {
GeckoProcessType type = XRE_GetProcessType();
if (type == GeckoProcessType_GPU || type == GeckoProcessType_RDD) {
return !!(aSelector & Module::ALLOW_IN_GPU_PROCESS);
}
if (type == GeckoProcessType_Socket) {
return !!(aSelector & (Module::ALLOW_IN_SOCKET_PROCESS));
}
if (type == GeckoProcessType_VR) {
return !!(aSelector & Module::ALLOW_IN_VR_PROCESS);
}
if (aSelector & Module::MAIN_PROCESS_ONLY) {
return type == GeckoProcessType_Default;
}
if (aSelector & Module::CONTENT_PROCESS_ONLY) {
return type == GeckoProcessType_Content;
}
return true;
}
static const int kModuleVersionWithSelector = 51;
template <typename T>
@ -1157,9 +1195,10 @@ PRThread* nsComponentManagerImpl::GetPendingServiceThread(
return nullptr;
}
nsresult
nsComponentManagerImpl::GetServiceLocked(MutexLock& aLock, nsFactoryEntry& aEntry,
const nsIID& aIID, void** aResult) {
nsresult nsComponentManagerImpl::GetServiceLocked(MutexLock& aLock,
nsFactoryEntry& aEntry,
const nsIID& aIID,
void** aResult) {
if (aEntry.mServiceObject) {
aLock.Unlock();
return aEntry.mServiceObject->QueryInterface(aIID, aResult);
@ -1228,7 +1267,8 @@ nsComponentManagerImpl::GetServiceLocked(MutexLock& aLock, nsFactoryEntry& aEntr
nsresult rv;
{
SafeMutexAutoUnlock unlock(mLock);
rv = CreateInstance(*aEntry.mCIDEntry->cid, nullptr, aIID, getter_AddRefs(service));
rv = CreateInstance(*aEntry.mCIDEntry->cid, nullptr, aIID,
getter_AddRefs(service));
}
if (NS_SUCCEEDED(rv) && !service) {
NS_ERROR("Factory did not return an object but returned success");

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

@ -53,9 +53,18 @@ struct PRThread;
extern const mozilla::Module kXPCOMModule;
namespace {
class MutexLock;
class MutexLock;
}
namespace mozilla {
namespace xpcom {
bool ProcessSelectorMatches(Module::ProcessSelector aSelector);
bool FastProcessSelectorMatches(Module::ProcessSelector aSelector);
} // namespace xpcom
} // namespace mozilla
/**
* This is a wrapper around mozilla::Mutex which provides runtime
* checking for a deadlock where the same thread tries to lock a mutex while