mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-11 20:35:50 +00:00
Bug 1337062 - Transfer initial gfxVars over command line - r=blassey
When a subprocess is launched, gfxVars updates (for non-default values) are serialized and passed on the command line, up to a limit of 1023 characters, and ensuring it should not overflow the command line size. When the child starts, the command line parameter is given to gfxVars, so the updates can be used during gfxVars::Initialize(), instead of doing a sync request to the parent. In case the updates are not sent, or in the unlikely case the child cannot parse them, we fallback to the sync request -- The former case should be rare enough that a slow sync request is acceptable: It should only happen if D3D block-list is *modified* (most people would either use the default, or just overwrite these prefs with short strings.) MozReview-Commit-ID: 6MoJC0fe59Q --HG-- extra : rebase_source : cdc2e451783160c579b8fc84050e8457c600523e
This commit is contained in:
parent
04137c02ea
commit
9c16b0ccdc
@ -2039,6 +2039,35 @@ ContentParent::LaunchSubprocess(ProcessPriority aInitialPriority /* = PROCESS_PR
|
||||
extraArgs.push_back("-stringPrefs");
|
||||
extraArgs.push_back(stringPrefs.get());
|
||||
|
||||
char gfxBuf[1024];
|
||||
nsFixedCString gfxVarsUpdates(gfxBuf, 1024, 0);
|
||||
if (gfxVars::SerializeNonDefaultVarUpdates(gfxVarsUpdates, 1023)) {
|
||||
// Don't add gfxVarsUpdates if they risk taking too much command line space.
|
||||
const size_t maxArg =
|
||||
#ifdef XP_WIN
|
||||
8191;
|
||||
#else
|
||||
size_t(sysconf(_SC_ARG_MAX));
|
||||
#endif
|
||||
size_t extraArgsLength = 0;
|
||||
for (const std::string& arg : extraArgs) {
|
||||
extraArgsLength += arg.size() + 1;
|
||||
}
|
||||
if (extraArgsLength + size_t(gfxVarsUpdates.Length()) + 1024 < maxArg) {
|
||||
extraArgs.push_back("-gfxVars");
|
||||
if (gfxVarsUpdates.IsEmpty()) {
|
||||
// Don't pass an empty string.
|
||||
extraArgs.push_back("0");
|
||||
} else {
|
||||
extraArgs.push_back(gfxVarsUpdates.get());
|
||||
}
|
||||
|
||||
// Since we have sent all gfxVarsUpdates known so far, we can start
|
||||
// listening for updates.
|
||||
gfxVars::AddReceiver(this);
|
||||
}
|
||||
}
|
||||
|
||||
if (gSafeMode) {
|
||||
extraArgs.push_back("-safeMode");
|
||||
}
|
||||
|
@ -20,6 +20,8 @@
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#endif
|
||||
|
||||
#include "mozilla/gfx/gfxVars.h"
|
||||
|
||||
using mozilla::ipc::IOThreadChild;
|
||||
|
||||
namespace mozilla {
|
||||
@ -203,8 +205,14 @@ ContentProcess::Init(int aArgc, char* aArgv[])
|
||||
}
|
||||
SET_PREF_PHASE(END_INIT_PREFS);
|
||||
foundStringPrefs = true;
|
||||
}
|
||||
else if (!strcmp(aArgv[idx], "-safeMode")) {
|
||||
} else if (!strcmp(aArgv[idx], "-gfxVars")) {
|
||||
SET_PREF_PHASE(BEGIN_INIT_PREFS);
|
||||
char* str = aArgv[idx + 1];
|
||||
if (str[0] != '0' || str[1] != '\0') {
|
||||
gfxVars::GotSerializedInitialVarUpdates(aArgv[idx + 1]);
|
||||
}
|
||||
SET_PREF_PHASE(END_INIT_PREFS);
|
||||
} else if (!strcmp(aArgv[idx], "-safeMode")) {
|
||||
gSafeMode = true;
|
||||
}
|
||||
|
||||
|
@ -7,14 +7,17 @@
|
||||
#include "gfxVars.h"
|
||||
#include "gfxVarReceiver.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "nsPrintfCString.h"
|
||||
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
StaticAutoPtr<gfxVars> gfxVars::sInstance;
|
||||
StaticAutoPtr<nsTArray<gfxVars::VarBase*>> gfxVars::sVarList;
|
||||
const char* gfxVars::sSerializedInitialVarUpdates = nullptr;
|
||||
|
||||
void
|
||||
/* static */ void
|
||||
gfxVars::Initialize()
|
||||
{
|
||||
if (sInstance) {
|
||||
@ -30,10 +33,13 @@ gfxVars::Initialize()
|
||||
// init. Note the GPU process is not handled here - it cannot send sync
|
||||
// messages, so instead the initial data is pushed down.
|
||||
if (XRE_IsContentProcess()) {
|
||||
InfallibleTArray<GfxVarUpdate> vars;
|
||||
dom::ContentChild::GetSingleton()->SendGetGfxVars(&vars);
|
||||
for (const auto& var : vars) {
|
||||
ApplyUpdate(var);
|
||||
if (!ApplySerializedVarUpdates(sSerializedInitialVarUpdates)) {
|
||||
// No initial updates, or could not apply them -> Try sync retrieval.
|
||||
InfallibleTArray<GfxVarUpdate> vars;
|
||||
dom::ContentChild::GetSingleton()->SendGetGfxVars(&vars);
|
||||
for (const auto& var : vars) {
|
||||
ApplyUpdate(var);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -101,6 +107,183 @@ gfxVars::FetchNonDefaultVars()
|
||||
return updates;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
gfxVars::SerializeNonDefaultVarUpdates(nsACString& aUpdates, size_t aMax)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!sVarList) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < sVarList->Length(); i++) {
|
||||
VarBase* var = sVarList->ElementAt(i);
|
||||
if (var->HasDefaultValue()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
GfxVarValue value;
|
||||
var->GetValue(&value);
|
||||
|
||||
switch (value.type()) {
|
||||
case mozilla::gfx::GfxVarValue::TBackendType: {
|
||||
nsPrintfCString t("T%zu:%d|", i, int(value.get_BackendType()));
|
||||
if (aUpdates.Length() + t.Length() > aMax) {
|
||||
return false;
|
||||
}
|
||||
aUpdates.Append(t);
|
||||
}
|
||||
break;
|
||||
case mozilla::gfx::GfxVarValue::Tbool: {
|
||||
nsPrintfCString b("B%zu:%d|",
|
||||
i, int(value.get_bool()));
|
||||
if (aUpdates.Length() + b.Length() > aMax) {
|
||||
return false;
|
||||
}
|
||||
aUpdates.Append(b);
|
||||
}
|
||||
break;
|
||||
case mozilla::gfx::GfxVarValue::TgfxImageFormat: {
|
||||
nsPrintfCString f("F%zu:%d|", i, int(value.get_gfxImageFormat()));
|
||||
if (aUpdates.Length() + f.Length() > aMax) {
|
||||
return false;
|
||||
}
|
||||
aUpdates.Append(f);
|
||||
}
|
||||
break;
|
||||
case mozilla::gfx::GfxVarValue::TIntSize: {
|
||||
nsPrintfCString z("Z%zu:%dx%d|",
|
||||
i,
|
||||
int(value.get_IntSize().width),
|
||||
int(value.get_IntSize().height));
|
||||
if (aUpdates.Length() + z.Length() > aMax) {
|
||||
return false;
|
||||
}
|
||||
aUpdates.Append(z);
|
||||
}
|
||||
break;
|
||||
case mozilla::gfx::GfxVarValue::TnsCString: {
|
||||
nsPrintfCString s("S%zu:%u;%s|",
|
||||
i,
|
||||
value.get_nsCString().Length(),
|
||||
value.get_nsCString().get());
|
||||
if (aUpdates.Length() + s.Length() > aMax) {
|
||||
return false;
|
||||
}
|
||||
aUpdates.Append(s);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
gfxVars::GotSerializedInitialVarUpdates(const char* aUpdates)
|
||||
{
|
||||
sSerializedInitialVarUpdates = aUpdates;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
gfxVars::ApplySerializedVarUpdates(const char* aUpdates)
|
||||
{
|
||||
if (!aUpdates) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const char* p = aUpdates; *p;) {
|
||||
switch (*p++) {
|
||||
case 'T': {
|
||||
int32_t index = strtol(p, const_cast<char**>(&p), 10);
|
||||
if (*p != ':') {
|
||||
return false;
|
||||
}
|
||||
p++;
|
||||
int32_t type = strtol(p, const_cast<char**>(&p), 10);
|
||||
if (*p != '|') {
|
||||
return false;
|
||||
}
|
||||
p++;
|
||||
ApplyUpdate(GfxVarUpdate(index, GfxVarValue(BackendType(type))));
|
||||
}
|
||||
break;
|
||||
case 'B': {
|
||||
int32_t index = strtol(p, const_cast<char**>(&p), 10);
|
||||
if (*p != ':') {
|
||||
return false;
|
||||
}
|
||||
p++;
|
||||
int32_t b = strtol(p, const_cast<char**>(&p), 10);
|
||||
if (*p != '|') {
|
||||
return false;
|
||||
}
|
||||
p++;
|
||||
ApplyUpdate(GfxVarUpdate(index, GfxVarValue(bool(b))));
|
||||
}
|
||||
break;
|
||||
case 'F': {
|
||||
int32_t index = strtol(p, const_cast<char**>(&p), 10);
|
||||
if (*p != ':') {
|
||||
return false;
|
||||
}
|
||||
p++;
|
||||
int32_t format = strtol(p, const_cast<char**>(&p), 10);
|
||||
if (*p != '|') {
|
||||
return false;
|
||||
}
|
||||
p++;
|
||||
ApplyUpdate(GfxVarUpdate(index, GfxVarValue(gfxImageFormat(format))));
|
||||
}
|
||||
break;
|
||||
case 'Z': {
|
||||
int32_t index = strtol(p, const_cast<char**>(&p), 10);
|
||||
if (*p != ':') {
|
||||
return false;
|
||||
}
|
||||
p++;
|
||||
int32_t width = strtol(p, const_cast<char**>(&p), 10);
|
||||
if (*p != 'x') {
|
||||
return false;
|
||||
}
|
||||
p++;
|
||||
int32_t height = strtol(p, const_cast<char**>(&p), 10);
|
||||
if (*p != '|') {
|
||||
return false;
|
||||
}
|
||||
p++;
|
||||
ApplyUpdate(GfxVarUpdate(index, GfxVarValue(IntSize(width, height))));
|
||||
}
|
||||
break;
|
||||
case 'S': {
|
||||
int32_t index = strtol(p, const_cast<char**>(&p), 10);
|
||||
if (*p != ':') {
|
||||
return false;
|
||||
}
|
||||
p++;
|
||||
int32_t length = strtol(p, const_cast<char**>(&p), 10);
|
||||
if (*p != ';') {
|
||||
return false;
|
||||
}
|
||||
p++;
|
||||
ApplyUpdate(GfxVarUpdate(index, GfxVarValue(nsCString(p, length))));
|
||||
p += length;
|
||||
if (*p++ != '|') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
gfxVars::VarBase::VarBase()
|
||||
{
|
||||
mIndex = gfxVars::sVarList->Length();
|
||||
|
@ -66,6 +66,12 @@ public:
|
||||
|
||||
// Return a list of updates for all variables with non-default values.
|
||||
static nsTArray<GfxVarUpdate> FetchNonDefaultVars();
|
||||
// Fill aUpdates with serialized updates for all variables with non-default
|
||||
// values. Return true if ok, false if length>aMax or other issue.
|
||||
static bool SerializeNonDefaultVarUpdates(nsACString& aUpdates, size_t aMax);
|
||||
// Inform gfxVars that some initial updates are available, to be used from
|
||||
// a child's Initialize(), instead of doing a sync request to the parent.
|
||||
static void GotSerializedInitialVarUpdates(const char* aUpdates);
|
||||
|
||||
public:
|
||||
// Each variable must expose Set and Get methods for IPDL.
|
||||
@ -86,6 +92,7 @@ public:
|
||||
private:
|
||||
static StaticAutoPtr<gfxVars> sInstance;
|
||||
static StaticAutoPtr<nsTArray<VarBase*>> sVarList;
|
||||
static const char* sSerializedInitialVarUpdates;
|
||||
|
||||
template <typename T, T Default()>
|
||||
class VarImpl final : public VarBase
|
||||
@ -141,6 +148,8 @@ public: \
|
||||
private:
|
||||
gfxVars();
|
||||
|
||||
static bool ApplySerializedVarUpdates(const char* aUpdates);
|
||||
|
||||
void NotifyReceivers(VarBase* aVar);
|
||||
|
||||
private:
|
||||
|
Loading…
Reference in New Issue
Block a user