Bug 1753709 - JavaScript: Add a preference to switch between delazification strategies. r=arai
This patch changes the way we parse JavaScript coming from Necko while loading web pages, by adding an about:config flag named javascript.options.delazification.strategy which is used to select between: 0 - On Demand 1 - Concurrent Depth First 255 - Parse Everything Eagerly Previously, we moved from On-demand delazification, to parsing everything eagerly to improve responsiveness of the browser, but we knew that more room for optimization exists. This toogle is meant to explore the space of delazification strategies, such that we can parse functions of JavaScript files on an helper thread, while the JavaScript file is being executed on the main thread. The space of delazification strategies goes from ordering the order in which functions are processed, as well as filtering functions which are processed. Not all functions have to be delazified, and if the main thread needs a function which is not parsed yet, it will fallback to parsing it on-demand. Differential Revision: https://phabricator.services.mozilla.com/D138034
This commit is contained in:
@@ -42,6 +42,7 @@
|
||||
#include "mozilla/net/UrlClassifierFeatureFactory.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/StaticPrefs_dom.h"
|
||||
#include "mozilla/StaticPrefs_javascript.h"
|
||||
#include "mozilla/StaticPrefs_network.h"
|
||||
#include "nsAboutProtocolUtils.h"
|
||||
#include "nsGkAtoms.h"
|
||||
@@ -1548,16 +1549,16 @@ nsresult ScriptLoader::AttemptAsyncScriptCompile(ScriptLoadRequest* aRequest,
|
||||
} else {
|
||||
MOZ_ASSERT(aRequest->IsTextSource());
|
||||
|
||||
if (ShouldFullParse(aRequest)) {
|
||||
options.setForceFullParse();
|
||||
if (ShouldApplyDelazifyStrategy(aRequest)) {
|
||||
ApplyDelazifyStrategy(&options);
|
||||
mTotalFullParseSize +=
|
||||
aRequest->ScriptTextLength() > 0
|
||||
? static_cast<uint32_t>(aRequest->ScriptTextLength())
|
||||
: 0;
|
||||
|
||||
LOG(
|
||||
("ScriptLoadRequest (%p): Full Parsing Enabled for url=%s "
|
||||
"mTotalFullParseSize=%u",
|
||||
("ScriptLoadRequest (%p): non-on-demand-only Parsing Enabled for "
|
||||
"url=%s mTotalFullParseSize=%u",
|
||||
aRequest, aRequest->mURI->GetSpecOrDefault().get(),
|
||||
mTotalFullParseSize));
|
||||
}
|
||||
@@ -2972,20 +2973,20 @@ static bool IsInternalURIScheme(nsIURI* uri) {
|
||||
uri->SchemeIs("chrome");
|
||||
}
|
||||
|
||||
bool ScriptLoader::ShouldFullParse(ScriptLoadRequest* aRequest) {
|
||||
bool ScriptLoader::ShouldApplyDelazifyStrategy(ScriptLoadRequest* aRequest) {
|
||||
// Full parse everything if negative.
|
||||
if (StaticPrefs::dom_script_loader_full_parse_max_size() < 0) {
|
||||
if (StaticPrefs::dom_script_loader_delazification_max_size() < 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Be conservative on machines with 2GB or less of memory.
|
||||
if (PhysicalSizeOfMemoryInGB() <=
|
||||
StaticPrefs::dom_script_loader_full_parse_min_mem()) {
|
||||
StaticPrefs::dom_script_loader_delazification_min_mem()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t max_size = static_cast<uint32_t>(
|
||||
StaticPrefs::dom_script_loader_full_parse_max_size());
|
||||
StaticPrefs::dom_script_loader_delazification_max_size());
|
||||
uint32_t script_size =
|
||||
aRequest->ScriptTextLength() > 0
|
||||
? static_cast<uint32_t>(aRequest->ScriptTextLength())
|
||||
@@ -2998,14 +2999,46 @@ bool ScriptLoader::ShouldFullParse(ScriptLoadRequest* aRequest) {
|
||||
if (LOG_ENABLED()) {
|
||||
nsCString url = aRequest->mURI->GetSpecOrDefault();
|
||||
LOG(
|
||||
("ScriptLoadRequest (%p): Full Parsing Disabled for (%s) with size=%u"
|
||||
" because mTotalFullParseSize=%u would exceed max_size=%u",
|
||||
("ScriptLoadRequest (%p): non-on-demand-only Parsing Disabled for (%s) "
|
||||
"with size=%u because mTotalFullParseSize=%u would exceed max_size=%u",
|
||||
aRequest, url.get(), script_size, mTotalFullParseSize, max_size));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ScriptLoader::ApplyDelazifyStrategy(JS::CompileOptions* aOptions) {
|
||||
JS::DelazificationOption strategy =
|
||||
JS::DelazificationOption::ParseEverythingEagerly;
|
||||
uint32_t strategyIndex =
|
||||
StaticPrefs::dom_script_loader_delazification_strategy();
|
||||
|
||||
// Assert that all enumerated values of DelazificationOption are dense between
|
||||
// OnDemandOnly and ParseEverythingEagerly.
|
||||
#ifdef DEBUG
|
||||
uint32_t count = 0;
|
||||
uint32_t mask = 0;
|
||||
# define _COUNT_ENTRIES(Name) count++;
|
||||
# define _MASK_ENTRIES(Name) \
|
||||
mask |= 1 << uint32_t(JS::DelazificationOption::Name);
|
||||
|
||||
FOREACH_DELAZIFICATION_STRATEGY(_COUNT_ENTRIES);
|
||||
MOZ_ASSERT(count == uint32_t(strategy) + 1);
|
||||
FOREACH_DELAZIFICATION_STRATEGY(_MASK_ENTRIES);
|
||||
MOZ_ASSERT(((mask + 1) & mask) == 0);
|
||||
# undef _COUNT_ENTRIES
|
||||
# undef _MASK_ENTRIES
|
||||
#endif
|
||||
|
||||
// Any strategy index larger than ParseEverythingEagerly would default to
|
||||
// ParseEverythingEagerly.
|
||||
if (strategyIndex <= uint32_t(strategy)) {
|
||||
strategy = JS::DelazificationOption(uint8_t(strategyIndex));
|
||||
}
|
||||
|
||||
aOptions->setEagerDelazificationStrategy(strategy);
|
||||
}
|
||||
|
||||
bool ScriptLoader::ShouldCompileOffThread(ScriptLoadRequest* aRequest) {
|
||||
if (NumberOfProcessors() <= 1) {
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user