Bug 1343483 - Report how long lazy code remains lazy
MozReview-Commit-ID: BThGS1eUkp7
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -336,31 +336,36 @@ BytecodeCompiler::compileScript(HandleOb
if (!deoptimizeArgumentsInEnclosingScripts(cx, environment))
return nullptr;
}
if (!emitter->emitScript(pn))
return nullptr;
if (!NameFunctions(cx, pn))
return nullptr;
parser->handler.freeTree(pn);
-
break;
}
// Maybe we aborted a syntax parse. See if we can try again.
if (!handleParseFailure(directives))
return nullptr;
// Reset UsedNameTracker state before trying again.
usedNames->reset();
}
if (!maybeCompleteCompressSource())
return nullptr;
+ // FIXME: I'm not sure at all that this happens in the right thread.
+ if (!syntaxParser) { // FIXME: Is this the right way to check that we're doing a syntax parse?
+ js::ScriptSource* source = script->scriptSource();
+ source->syntaxParseEnds();
+ }
+
MOZ_ASSERT_IF(!cx->helperThread(), !cx->isExceptionPending());
return script;
}
JSScript*
BytecodeCompiler::compileGlobalScript(ScopeKind scopeKind)
{
@@ -625,16 +630,25 @@ frontend::CompileLazyFunction(JSContext*
CompileOptions options(cx, lazy->version());
options.setMutedErrors(lazy->mutedErrors())
.setFileAndLine(lazy->filename(), lazy->lineno())
.setColumn(lazy->column())
.setNoScriptRval(false)
.setSelfHostingMode(false);
+ // Update statistics to find out if we have delazified just after having
+ // lazified.
+ if (!lazy->scriptSource()->syntaxParseEnded().IsNull()) {
+ mozilla::TimeDuration delta = mozilla::TimeStamp::Now() - lazy->scriptSource()->syntaxParseEnded();
+ cx->runtime()->addTelemetry(JS_TELEMETRY_PARSER_COMPILE_LAZY_AFTER_MS,
+ delta.ToMilliseconds()
+ );
+ }
+
AutoCompilationTraceLogger traceLogger(cx, TraceLogger_ParserCompileLazy, options);
UsedNameTracker usedNames(cx);
if (!usedNames.init())
return false;
Parser<FullParseHandler> parser(cx, cx->tempLifoAlloc(), options, chars, length,
/* foldConstants = */ true, usedNames, nullptr, lazy);
if (!parser.checkOptions())
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -131,16 +131,17 @@ enum {
JS_TELEMETRY_GC_MINOR_REASON_LONG,
JS_TELEMETRY_GC_MINOR_US,
JS_TELEMETRY_GC_NURSERY_BYTES,
JS_TELEMETRY_GC_PRETENURE_COUNT,
JS_TELEMETRY_DEPRECATED_LANGUAGE_EXTENSIONS_IN_CONTENT,
JS_TELEMETRY_DEPRECATED_LANGUAGE_EXTENSIONS_IN_ADDONS,
JS_TELEMETRY_ADDON_EXCEPTIONS,
JS_TELEMETRY_AOT_USAGE,
+ JS_TELEMETRY_PARSER_COMPILE_LAZY_AFTER_MS,
JS_TELEMETRY_END
};
typedef void
(*JSAccumulateTelemetryDataCallback)(int id, uint32_t sample, const char* key);
extern JS_FRIEND_API(void)
JS_SetAccumulateTelemetryCallback(JSContext* cx, JSAccumulateTelemetryDataCallback callback);
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -350,16 +350,17 @@ class UncompressedSourceCache
private:
void holdEntry(AutoHoldEntry& holder, const ScriptSourceChunk& ssc);
void releaseEntry(AutoHoldEntry& holder);
};
class ScriptSource
{
+ private:
friend struct SourceCompressionTask;
uint32_t refs;
// Note: while ScriptSources may be compressed off thread, they are only
// modified by the active thread, and all members are always safe to access
// on the active thread.
@@ -441,16 +442,24 @@ class ScriptSource
// demand. If sourceRetrievable_ and hasSourceData() are false, it is not
// possible to get source at all.
bool sourceRetrievable_:1;
bool hasIntroductionOffset_:1;
const char16_t* chunkChars(JSContext* cx, UncompressedSourceCache::AutoHoldEntry& holder,
size_t chunk);
+ // Instant at which the syntax parse of this source ended, or null
+ // if there was no syntax parse.
+ //
+ // Used for statistics purposes, to determine how much time code spends
+ // syntax parsed before being full parsed, to help determine whether
+ // our syntax parse vs. full parse heuristics are correct.
+ mozilla::TimeStamp syntaxParseEnded_;
+
public:
explicit ScriptSource()
: refs(0),
data(SourceType(Missing())),
filename_(nullptr),
displayURL_(nullptr),
sourceMapURL_(nullptr),
mutedErrors_(false),
@@ -603,16 +612,24 @@ class ScriptSource
// ScriptSource.
bool xdrEncodeFunction(JSContext* cx, HandleFunction fun,
HandleScriptSource sourceObject);
// Linearize the encoded content in the |buffer| provided as argument to
// |xdrEncodeTopLevel|, and free the XDR encoder. In case of errors, the
// |buffer| is considered undefined.
bool xdrFinalizeEncoder();
+
+ const mozilla::TimeStamp syntaxParseEnded() const {
+ return syntaxParseEnded_;
+ }
+ void syntaxParseEnds() {
+ MOZ_ASSERT(syntaxParseEnded_.IsNull());
+ syntaxParseEnded_ = mozilla::TimeStamp::Now();
+ }
};
class ScriptSourceHolder
{
ScriptSource* ss;
public:
ScriptSourceHolder()
: ss(nullptr)
--- a/js/xpconnect/src/XPCJSContext.cpp
+++ b/js/xpconnect/src/XPCJSContext.cpp
@@ -3118,16 +3118,19 @@ AccumulateTelemetryCallback(int id, uint
Telemetry::Accumulate(Telemetry::JS_DEPRECATED_LANGUAGE_EXTENSIONS_IN_ADDONS, sample);
break;
case JS_TELEMETRY_ADDON_EXCEPTIONS:
Telemetry::Accumulate(Telemetry::JS_TELEMETRY_ADDON_EXCEPTIONS, nsDependentCString(key), sample);
break;
case JS_TELEMETRY_AOT_USAGE:
Telemetry::Accumulate(Telemetry::JS_AOT_USAGE, sample);
break;
+ case JS_TELEMETRY_PARSER_COMPILE_LAZY_AFTER_MS:
+ Telemetry::Accumulate(Telemetry::JS_PARSER_COMPILE_LAZY_AFTER_MS, sample);
+ break;
default:
MOZ_ASSERT_UNREACHABLE("Unexpected JS_TELEMETRY id");
}
}
static void
CompartmentNameCallback(JSContext* cx, JSCompartment* comp,
char* buf, size_t bufsize)
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -1045,16 +1045,26 @@
},
"JS_DEPRECATED_LANGUAGE_EXTENSIONS_IN_ADDONS": {
"alert_emails": ["jdemooij@mozilla.com"],
"expires_in_version": "never",
"kind": "enumerated",
"n_values": 10,
"description": "Use of SpiderMonkey's deprecated language extensions in add-ons: ForEach=0, DestructuringForIn=1 (obsolete), LegacyGenerator=2, ExpressionClosure=3, LetBlock=4 (obsolete), LetExpression=5 (obsolete), NoSuchMethod=6 (obsolete), FlagsArgument=7 (obsolete), RegExpSourceProp=8 (obsolete), RestoredRegExpStatics=9 (obsolete), BlockScopeFunRedecl=10"
},
+ "JS_PARSER_COMPILE_LAZY_AFTER_MS": {
+ "alert_emails": ["dteller@mozilla.com"],
+ "expires_in_version": "70",
+ "bug_numbers": [1343483],
+ "kind": "exponential",
+ "low": 10,
+ "high": 10000,
+ "n_buckets": 10,
+ "description": "Time elapsed between the moment a function is lazy-parsed (end of parsing of the ScriptSource) and the moment it is recompiled as non-lazy (start of compilation)."
+ },
"XUL_CACHE_DISABLED": {
"expires_in_version": "default",
"kind": "flag",
"description": "XUL cache was disabled"
},
"MEMORY_RESIDENT_FAST": {
"alert_emails": ["memshrink-telemetry-alerts@mozilla.com"],
"expires_in_version": "never",