diff --git a/js/src/frontend/BytecodeCompiler.cpp b/js/src/frontend/BytecodeCompiler.cpp index 7a9faa6700f7..1a98f584c8e7 100644 --- a/js/src/frontend/BytecodeCompiler.cpp +++ b/js/src/frontend/BytecodeCompiler.cpp @@ -31,19 +31,6 @@ using namespace js::frontend; using mozilla::Maybe; using mozilla::Nothing; -class MOZ_STACK_CLASS AutoCompilationTraceLogger -{ - public: - AutoCompilationTraceLogger(JSContext* cx, const TraceLoggerTextId id, - const ReadOnlyCompileOptions& options); - - private: - TraceLoggerThread* logger; - TraceLoggerEvent event; - AutoTraceLog scriptLogger; - AutoTraceLog typeLogger; -}; - // The BytecodeCompiler class contains resources common to compiling scripts and // function bodies. class MOZ_STACK_CLASS BytecodeCompiler @@ -54,8 +41,7 @@ class MOZ_STACK_CLASS BytecodeCompiler LifoAlloc& alloc, const ReadOnlyCompileOptions& options, SourceBufferHolder& sourceBuffer, - HandleScope enclosingScope, - TraceLoggerTextId logId); + HandleScope enclosingScope); // Call setters for optional arguments. void maybeSetSourceCompressor(SourceCompressionTask* sourceCompressor); @@ -83,7 +69,6 @@ class MOZ_STACK_CLASS BytecodeCompiler bool deoptimizeArgumentsInEnclosingScripts(JSContext* cx, HandleObject environment); bool maybeCompleteCompressSource(); - AutoCompilationTraceLogger traceLogger; AutoKeepAtoms keepAtoms; JSContext* cx; @@ -109,22 +94,77 @@ class MOZ_STACK_CLASS BytecodeCompiler RootedScript script; }; -AutoCompilationTraceLogger::AutoCompilationTraceLogger(JSContext* cx, - const TraceLoggerTextId id, const ReadOnlyCompileOptions& options) - : logger(TraceLoggerForCurrentThread(cx)), - event(TraceLogger_AnnotateScripts, options), - scriptLogger(logger, event), - typeLogger(logger, id) -{} +AutoFrontendTraceLog::AutoFrontendTraceLog(JSContext* cx, const TraceLoggerTextId id, + const char* filename, size_t line, size_t column) +#ifdef JS_TRACE_LOGGING + : logger_(TraceLoggerForCurrentThread(cx)) +{ + frontendEvent_.emplace(TraceLogger_Frontend, filename, line, column); + frontendLog_.emplace(logger_, *frontendEvent_); + typeLog_.emplace(logger_, id); +} +#else +{ } +#endif + +AutoFrontendTraceLog::AutoFrontendTraceLog(JSContext* cx, const TraceLoggerTextId id, + const TokenStream& tokenStream) +#ifdef JS_TRACE_LOGGING + : logger_(TraceLoggerForCurrentThread(cx)) +{ + // If the tokenizer hasn't yet gotten any tokens, use the line and column + // numbers from CompileOptions. + uint32_t line, column; + if (tokenStream.isCurrentTokenType(TOK_EOF) && !tokenStream.isEOF()) { + line = tokenStream.options().lineno; + column = tokenStream.options().column; + } else { + uint32_t offset = tokenStream.currentToken().pos.begin; + tokenStream.srcCoords.lineNumAndColumnIndex(offset, &line, &column); + } + frontendEvent_.emplace(TraceLogger_Frontend, tokenStream.getFilename(), line, column); + frontendLog_.emplace(logger_, *frontendEvent_); + typeLog_.emplace(logger_, id); +} +#else +{ } +#endif + +AutoFrontendTraceLog::AutoFrontendTraceLog(JSContext* cx, const TraceLoggerTextId id, + const TokenStream& tokenStream, FunctionBox* funbox) +#ifdef JS_TRACE_LOGGING + : logger_(TraceLoggerForCurrentThread(cx)) +{ + frontendEvent_.emplace(TraceLogger_Frontend, tokenStream.getFilename(), + funbox->startLine, funbox->startColumn); + frontendLog_.emplace(logger_, *frontendEvent_); + typeLog_.emplace(logger_, id); +} +#else +{ } +#endif + +AutoFrontendTraceLog::AutoFrontendTraceLog(JSContext* cx, const TraceLoggerTextId id, + const TokenStream& tokenStream, ParseNode* pn) +#ifdef JS_TRACE_LOGGING + : logger_(TraceLoggerForCurrentThread(cx)) +{ + uint32_t line, column; + tokenStream.srcCoords.lineNumAndColumnIndex(pn->pn_pos.begin, &line, &column); + frontendEvent_.emplace(TraceLogger_Frontend, tokenStream.getFilename(), line, column); + frontendLog_.emplace(logger_, *frontendEvent_); + typeLog_.emplace(logger_, id); +} +#else +{ } +#endif BytecodeCompiler::BytecodeCompiler(JSContext* cx, LifoAlloc& alloc, const ReadOnlyCompileOptions& options, SourceBufferHolder& sourceBuffer, - HandleScope enclosingScope, - TraceLoggerTextId logId) - : traceLogger(cx, logId, options), - keepAtoms(cx), + HandleScope enclosingScope) + : keepAtoms(cx), cx(cx), alloc(alloc), options(options), @@ -556,8 +596,7 @@ frontend::CompileGlobalScript(JSContext* cx, LifoAlloc& alloc, ScopeKind scopeKi ScriptSourceObject** sourceObjectOut) { MOZ_ASSERT(scopeKind == ScopeKind::Global || scopeKind == ScopeKind::NonSyntactic); - BytecodeCompiler compiler(cx, alloc, options, srcBuf, /* enclosingScope = */ nullptr, - TraceLogger_ParserCompileScript); + BytecodeCompiler compiler(cx, alloc, options, srcBuf, /* enclosingScope = */ nullptr); AutoInitializeSourceObject autoSSO(compiler, sourceObjectOut); compiler.maybeSetSourceCompressor(extraSct); return compiler.compileGlobalScript(scopeKind); @@ -571,8 +610,7 @@ frontend::CompileEvalScript(JSContext* cx, LifoAlloc& alloc, SourceCompressionTask* extraSct, ScriptSourceObject** sourceObjectOut) { - BytecodeCompiler compiler(cx, alloc, options, srcBuf, enclosingScope, - TraceLogger_ParserCompileScript); + BytecodeCompiler compiler(cx, alloc, options, srcBuf, enclosingScope); AutoInitializeSourceObject autoSSO(compiler, sourceObjectOut); compiler.maybeSetSourceCompressor(extraSct); return compiler.compileEvalScript(environment, enclosingScope); @@ -592,8 +630,7 @@ frontend::CompileModule(JSContext* cx, const ReadOnlyCompileOptions& optionsInpu options.allowHTMLComments = false; RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope()); - BytecodeCompiler compiler(cx, alloc, options, srcBuf, emptyGlobalScope, - TraceLogger_ParserCompileModule); + BytecodeCompiler compiler(cx, alloc, options, srcBuf, emptyGlobalScope); AutoInitializeSourceObject autoSSO(compiler, sourceObjectOut); return compiler.compileModule(); } @@ -630,8 +667,6 @@ frontend::CompileLazyFunction(JSContext* cx, Handle lazy, const cha .setNoScriptRval(false) .setSelfHostingMode(false); - AutoCompilationTraceLogger traceLogger(cx, TraceLogger_ParserCompileLazy, options); - UsedNameTracker usedNames(cx); if (!usedNames.init()) return false; @@ -692,8 +727,7 @@ frontend::CompileStandaloneFunction(JSContext* cx, MutableHandleFunction fun, if (!scope) scope = &cx->global()->emptyGlobalScope(); - BytecodeCompiler compiler(cx, cx->tempLifoAlloc(), options, srcBuf, scope, - TraceLogger_ParserCompileFunction); + BytecodeCompiler compiler(cx, cx->tempLifoAlloc(), options, srcBuf, scope); return compiler.compileStandaloneFunction(fun, NotGenerator, SyncFunction, parameterListEnd); } @@ -705,8 +739,7 @@ frontend::CompileStandaloneGenerator(JSContext* cx, MutableHandleFunction fun, { RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope()); - BytecodeCompiler compiler(cx, cx->tempLifoAlloc(), options, srcBuf, emptyGlobalScope, - TraceLogger_ParserCompileFunction); + BytecodeCompiler compiler(cx, cx->tempLifoAlloc(), options, srcBuf, emptyGlobalScope); return compiler.compileStandaloneFunction(fun, StarGenerator, SyncFunction, parameterListEnd); } @@ -718,7 +751,6 @@ frontend::CompileStandaloneAsyncFunction(JSContext* cx, MutableHandleFunction fu { RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope()); - BytecodeCompiler compiler(cx, cx->tempLifoAlloc(), options, srcBuf, emptyGlobalScope, - TraceLogger_ParserCompileFunction); + BytecodeCompiler compiler(cx, cx->tempLifoAlloc(), options, srcBuf, emptyGlobalScope); return compiler.compileStandaloneFunction(fun, StarGenerator, AsyncFunction, parameterListEnd); } diff --git a/js/src/frontend/BytecodeCompiler.h b/js/src/frontend/BytecodeCompiler.h index 32a4e7ae94d8..5b1df2414d28 100644 --- a/js/src/frontend/BytecodeCompiler.h +++ b/js/src/frontend/BytecodeCompiler.h @@ -13,6 +13,7 @@ #include "vm/Scope.h" #include "vm/String.h" +#include "vm/TraceLogging.h" class JSLinearString; @@ -26,6 +27,10 @@ struct SourceCompressionTask; namespace frontend { +class TokenStream; +class FunctionBox; +class ParseNode; + JSScript* CompileGlobalScript(JSContext* cx, LifoAlloc& alloc, ScopeKind scopeKind, const ReadOnlyCompileOptions& options, @@ -119,6 +124,29 @@ IsKeyword(JSLinearString* str); void TraceParser(JSTracer* trc, JS::AutoGCRooter* parser); +class MOZ_STACK_CLASS AutoFrontendTraceLog +{ +#ifdef JS_TRACE_LOGGING + TraceLoggerThread* logger_; + mozilla::Maybe frontendEvent_; + mozilla::Maybe frontendLog_; + mozilla::Maybe typeLog_; +#endif + + public: + AutoFrontendTraceLog(JSContext* cx, const TraceLoggerTextId id, + const char* filename, size_t line, size_t column); + + AutoFrontendTraceLog(JSContext* cx, const TraceLoggerTextId id, + const TokenStream& tokenStream); + + AutoFrontendTraceLog(JSContext* cx, const TraceLoggerTextId id, + const TokenStream& tokenStream, FunctionBox* funbox); + + AutoFrontendTraceLog(JSContext* cx, const TraceLoggerTextId id, + const TokenStream& tokenStream, ParseNode* pn); +}; + } /* namespace frontend */ } /* namespace js */ diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 995680a41ab6..4c2a3d8ed178 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -580,6 +580,8 @@ class BytecodeEmitter::EmitterScope : public Nestablecx), + TraceLogger_FrontendNameAnalysis); if (Maybe loc = lookupInCache(bce, name)) return *loc; return searchAndCache(bce, name); @@ -866,6 +868,8 @@ Maybe BytecodeEmitter::EmitterScope::locationBoundInScope(BytecodeEmitter* bce, JSAtom* name, EmitterScope* target) { + AutoTraceLog traceLog(TraceLoggerForCurrentThread(bce->cx), TraceLogger_FrontendNameAnalysis); + // The target scope must be an intra-frame enclosing scope of this // one. Count the number of extra hops to reach it. uint8_t extraHops = 0; @@ -923,6 +927,8 @@ bool BytecodeEmitter::EmitterScope::enterLexical(BytecodeEmitter* bce, ScopeKind kind, Handle bindings) { + AutoTraceLog traceLog(TraceLoggerForCurrentThread(bce->cx), TraceLogger_FrontendNameAnalysis); + MOZ_ASSERT(kind != ScopeKind::NamedLambda && kind != ScopeKind::StrictNamedLambda); MOZ_ASSERT(this == bce->innermostEmitterScope); @@ -993,6 +999,8 @@ BytecodeEmitter::EmitterScope::enterLexical(BytecodeEmitter* bce, ScopeKind kind bool BytecodeEmitter::EmitterScope::enterNamedLambda(BytecodeEmitter* bce, FunctionBox* funbox) { + AutoTraceLog traceLog(TraceLoggerForCurrentThread(bce->cx), TraceLogger_FrontendNameAnalysis); + MOZ_ASSERT(this == bce->innermostEmitterScope); MOZ_ASSERT(funbox->namedLambdaBindings()); @@ -1060,6 +1068,8 @@ BytecodeEmitter::EmitterScope::enterComprehensionFor(BytecodeEmitter* bce, bool BytecodeEmitter::EmitterScope::enterParameterExpressionVar(BytecodeEmitter* bce) { + AutoTraceLog traceLog(TraceLoggerForCurrentThread(bce->cx), TraceLogger_FrontendNameAnalysis); + MOZ_ASSERT(this == bce->innermostEmitterScope); if (!ensureCache(bce)) @@ -1181,6 +1191,8 @@ BytecodeEmitter::EmitterScope::enterFunction(BytecodeEmitter* bce, FunctionBox* bool BytecodeEmitter::EmitterScope::enterFunctionExtraBodyVar(BytecodeEmitter* bce, FunctionBox* funbox) { + AutoTraceLog traceLog(TraceLoggerForCurrentThread(bce->cx), TraceLogger_FrontendNameAnalysis); + MOZ_ASSERT(funbox->hasParameterExprs); MOZ_ASSERT(funbox->extraVarScopeBindings() || funbox->needsExtraBodyVarEnvironmentRegardlessOfBindings()); @@ -1270,6 +1282,8 @@ class DynamicBindingIter : public BindingIter bool BytecodeEmitter::EmitterScope::enterGlobal(BytecodeEmitter* bce, GlobalSharedContext* globalsc) { + AutoTraceLog traceLog(TraceLoggerForCurrentThread(bce->cx), TraceLogger_FrontendNameAnalysis); + MOZ_ASSERT(this == bce->innermostEmitterScope); bce->setVarEmitterScope(this); @@ -1330,6 +1344,8 @@ BytecodeEmitter::EmitterScope::enterGlobal(BytecodeEmitter* bce, GlobalSharedCon bool BytecodeEmitter::EmitterScope::enterEval(BytecodeEmitter* bce, EvalSharedContext* evalsc) { + AutoTraceLog traceLog(TraceLoggerForCurrentThread(bce->cx), TraceLogger_FrontendNameAnalysis); + MOZ_ASSERT(this == bce->innermostEmitterScope); bce->setVarEmitterScope(this); @@ -1385,6 +1401,8 @@ BytecodeEmitter::EmitterScope::enterEval(BytecodeEmitter* bce, EvalSharedContext bool BytecodeEmitter::EmitterScope::enterModule(BytecodeEmitter* bce, ModuleSharedContext* modulesc) { + AutoTraceLog traceLog(TraceLoggerForCurrentThread(bce->cx), TraceLogger_FrontendNameAnalysis); + MOZ_ASSERT(this == bce->innermostEmitterScope); bce->setVarEmitterScope(this); @@ -1442,6 +1460,8 @@ BytecodeEmitter::EmitterScope::enterModule(BytecodeEmitter* bce, ModuleSharedCon bool BytecodeEmitter::EmitterScope::enterWith(BytecodeEmitter* bce) { + AutoTraceLog traceLog(TraceLoggerForCurrentThread(bce->cx), TraceLogger_FrontendNameAnalysis); + MOZ_ASSERT(this == bce->innermostEmitterScope); if (!ensureCache(bce)) @@ -1468,6 +1488,8 @@ BytecodeEmitter::EmitterScope::enterWith(BytecodeEmitter* bce) bool BytecodeEmitter::EmitterScope::leave(BytecodeEmitter* bce, bool nonLocal) { + AutoTraceLog traceLog(TraceLoggerForCurrentThread(bce->cx), TraceLogger_FrontendNameAnalysis); + // If we aren't leaving the scope due to a non-local jump (e.g., break), // we must be the innermost scope. MOZ_ASSERT_IF(!nonLocal, this == bce->innermostEmitterScope); @@ -1525,6 +1547,8 @@ BytecodeEmitter::EmitterScope::leave(BytecodeEmitter* bce, bool nonLocal) Maybe BytecodeEmitter::TDZCheckCache::needsTDZCheck(BytecodeEmitter* bce, JSAtom* name) { + AutoTraceLog traceLog(TraceLoggerForCurrentThread(bce->cx), TraceLogger_FrontendTDZAnalysis); + if (!ensureCache(bce)) return Nothing(); @@ -1554,6 +1578,8 @@ bool BytecodeEmitter::TDZCheckCache::noteTDZCheck(BytecodeEmitter* bce, JSAtom* name, MaybeCheckTDZ check) { + AutoTraceLog traceLog(TraceLoggerForCurrentThread(bce->cx), TraceLogger_FrontendTDZAnalysis); + if (!ensureCache(bce)) return false; @@ -3448,8 +3474,8 @@ BytecodeEmitter::needsImplicitThis() bool BytecodeEmitter::maybeSetDisplayURL() { - if (tokenStream()->hasDisplayURL()) { - if (!parser->ss->setDisplayURL(cx, tokenStream()->displayURL())) + if (tokenStream().hasDisplayURL()) { + if (!parser->ss->setDisplayURL(cx, tokenStream().displayURL())) return false; } return true; @@ -3458,9 +3484,9 @@ BytecodeEmitter::maybeSetDisplayURL() bool BytecodeEmitter::maybeSetSourceMap() { - if (tokenStream()->hasSourceMapURL()) { + if (tokenStream().hasSourceMapURL()) { MOZ_ASSERT(!parser->ss->hasSourceMapURL()); - if (!parser->ss->setSourceMapURL(cx, tokenStream()->sourceMapURL())) + if (!parser->ss->setSourceMapURL(cx, tokenStream().sourceMapURL())) return false; } @@ -3499,21 +3525,21 @@ BytecodeEmitter::tellDebuggerAboutCompiledScript(JSContext* cx) Debugger::onNewScript(cx, script); } -inline TokenStream* +inline TokenStream& BytecodeEmitter::tokenStream() { - return &parser->tokenStream; + return parser->tokenStream; } bool BytecodeEmitter::reportError(ParseNode* pn, unsigned errorNumber, ...) { - TokenPos pos = pn ? pn->pn_pos : tokenStream()->currentToken().pos; + TokenPos pos = pn ? pn->pn_pos : tokenStream().currentToken().pos; va_list args; va_start(args, errorNumber); - bool result = tokenStream()->reportCompileErrorNumberVA(nullptr, pos.begin, JSREPORT_ERROR, - errorNumber, args); + bool result = tokenStream().reportCompileErrorNumberVA(nullptr, pos.begin, JSREPORT_ERROR, + errorNumber, args); va_end(args); return result; } @@ -3521,12 +3547,12 @@ BytecodeEmitter::reportError(ParseNode* pn, unsigned errorNumber, ...) bool BytecodeEmitter::reportExtraWarning(ParseNode* pn, unsigned errorNumber, ...) { - TokenPos pos = pn ? pn->pn_pos : tokenStream()->currentToken().pos; + TokenPos pos = pn ? pn->pn_pos : tokenStream().currentToken().pos; va_list args; va_start(args, errorNumber); - bool result = tokenStream()->reportExtraWarningErrorNumberVA(nullptr, pos.begin, - errorNumber, args); + bool result = tokenStream().reportExtraWarningErrorNumberVA(nullptr, pos.begin, + errorNumber, args); va_end(args); return result; } @@ -3534,12 +3560,12 @@ BytecodeEmitter::reportExtraWarning(ParseNode* pn, unsigned errorNumber, ...) bool BytecodeEmitter::reportStrictModeError(ParseNode* pn, unsigned errorNumber, ...) { - TokenPos pos = pn ? pn->pn_pos : tokenStream()->currentToken().pos; + TokenPos pos = pn ? pn->pn_pos : tokenStream().currentToken().pos; va_list args; va_start(args, errorNumber); - bool result = tokenStream()->reportStrictModeErrorNumberVA(nullptr, pos.begin, sc->strict(), - errorNumber, args); + bool result = tokenStream().reportStrictModeErrorNumberVA(nullptr, pos.begin, sc->strict(), + errorNumber, args); va_end(args); return result; } @@ -4789,6 +4815,8 @@ BytecodeEmitter::emitSetThis(ParseNode* pn) bool BytecodeEmitter::emitScript(ParseNode* body) { + AutoFrontendTraceLog traceLog(cx, TraceLogger_BytecodeEmission, tokenStream(), body); + TDZCheckCache tdzCache(this); EmitterScope emitterScope(this); if (sc->isGlobalContext()) { @@ -4856,6 +4884,7 @@ bool BytecodeEmitter::emitFunctionScript(ParseNode* body) { FunctionBox* funbox = sc->asFunctionBox(); + AutoFrontendTraceLog traceLog(cx, TraceLogger_BytecodeEmission, tokenStream(), funbox); // The ordering of these EmitterScopes is important. The named lambda // scope needs to enclose the function scope needs to enclose the extra diff --git a/js/src/frontend/BytecodeEmitter.h b/js/src/frontend/BytecodeEmitter.h index d229a2e18c6d..7c2d17f3a904 100644 --- a/js/src/frontend/BytecodeEmitter.h +++ b/js/src/frontend/BytecodeEmitter.h @@ -352,7 +352,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter MOZ_MUST_USE bool maybeSetSourceMap(); void tellDebuggerAboutCompiledScript(JSContext* cx); - inline TokenStream* tokenStream(); + inline TokenStream& tokenStream(); BytecodeVector& code() const { return current->code; } jsbytecode* code(ptrdiff_t offset) const { return current->code.begin() + offset; } diff --git a/js/src/frontend/FoldConstants.cpp b/js/src/frontend/FoldConstants.cpp index 894a599210f9..dd1c657ba1dc 100644 --- a/js/src/frontend/FoldConstants.cpp +++ b/js/src/frontend/FoldConstants.cpp @@ -1928,5 +1928,6 @@ frontend::FoldConstants(JSContext* cx, ParseNode** pnp, Parser if (parser->pc->useAsmOrInsideUseAsm()) return true; + AutoTraceLog traceLog(TraceLoggerForCurrentThread(cx), TraceLogger_BytecodeFoldConstants); return Fold(cx, pnp, *parser, false); } diff --git a/js/src/frontend/NameFunctions.cpp b/js/src/frontend/NameFunctions.cpp index a24088370876..2a4d14234b03 100644 --- a/js/src/frontend/NameFunctions.cpp +++ b/js/src/frontend/NameFunctions.cpp @@ -835,6 +835,7 @@ class NameResolver bool frontend::NameFunctions(JSContext* cx, ParseNode* pn) { + AutoTraceLog traceLog(TraceLoggerForCurrentThread(cx), TraceLogger_BytecodeNameFunctions); NameResolver nr(cx); return nr.resolve(pn); } diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 24b953f02a82..7bfbc1928174 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -1018,6 +1018,8 @@ Parser::notePositionalFormalParameter(Node fn, HandlePropertyName bool disallowDuplicateParams, bool* duplicatedParam) { + AutoTraceLog traceLog(TraceLoggerForCurrentThread(context), TraceLogger_FrontendNameAnalysis); + if (AddDeclaredNamePtr p = pc->functionScope().lookupDeclaredNameForAdd(name)) { if (disallowDuplicateParams) { error(JSMSG_BAD_DUP_ARGS); @@ -1243,6 +1245,8 @@ bool Parser::tryDeclareVarForAnnexBLexicalFunction(HandlePropertyName name, bool* tryAnnexB) { + AutoTraceLog traceLog(TraceLoggerForCurrentThread(context), TraceLogger_FrontendNameAnalysis); + Maybe redeclaredKind; if (!tryDeclareVar(name, DeclarationKind::VarForAnnexBLexicalFunction, &redeclaredKind)) return false; @@ -1307,6 +1311,8 @@ bool Parser::noteDeclaredName(HandlePropertyName name, DeclarationKind kind, TokenPos pos) { + AutoTraceLog traceLog(TraceLoggerForCurrentThread(context), TraceLogger_FrontendNameAnalysis); + // The asm.js validator does all its own symbol-table management so, as an // optimization, avoid doing any work here. if (pc->useAsmOrInsideUseAsm()) @@ -1459,6 +1465,8 @@ template bool Parser::noteUsedName(HandlePropertyName name) { + AutoTraceLog traceLog(TraceLoggerForCurrentThread(context), TraceLogger_FrontendNameAnalysis); + // If the we are delazifying, the LazyScript already has all the // closed-over info for bindings and there's no need to track used names. if (handler.canSkipLazyClosedOverBindings()) @@ -1484,6 +1492,8 @@ template bool Parser::hasUsedName(HandlePropertyName name) { + AutoTraceLog traceLog(TraceLoggerForCurrentThread(context), TraceLogger_FrontendNameAnalysis); + if (UsedNamePtr p = usedNames.lookup(name)) return p->value().isUsedInScript(pc->scriptId()); return false; @@ -1493,6 +1503,8 @@ template bool Parser::propagateFreeNamesAndMarkClosedOverBindings(ParseContext::Scope& scope) { + AutoTraceLog traceLog(TraceLoggerForCurrentThread(context), TraceLogger_FrontendNameAnalysis); + if (handler.canSkipLazyClosedOverBindings()) { // Scopes are nullptr-delimited in the LazyScript closed over bindings // array. diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h index ff5d66b4f625..08a046f00b3e 100644 --- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -11,6 +11,7 @@ #include "mozilla/Array.h" #include "mozilla/Maybe.h" +#include "mozilla/TypeTraits.h" #include "jspubtd.h" @@ -255,6 +256,9 @@ class ParseContext : public Nestable }; private: + // Trace logging of parsing time. + AutoFrontendTraceLog traceLog_; + // Context shared between parsing and bytecode generation. SharedContext* sc_; @@ -351,6 +355,11 @@ class ParseContext : public Nestable template ParseContext(Parser* prs, SharedContext* sc, Directives* newDirectives) : Nestable(&prs->pc), + traceLog_(sc->context, + mozilla::IsSame::value + ? TraceLogger_ParsingFull + : TraceLogger_ParsingSyntax, + prs->tokenStream), sc_(sc), tokenStream_(prs->tokenStream), innermostStatement_(nullptr), diff --git a/js/src/frontend/TokenStream.cpp b/js/src/frontend/TokenStream.cpp index bc05a5c44f6d..78c072d0a520 100644 --- a/js/src/frontend/TokenStream.cpp +++ b/js/src/frontend/TokenStream.cpp @@ -1296,6 +1296,10 @@ static_assert(LastCharKind < (1 << (sizeof(firstCharKinds[0]) * 8)), bool TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier) { + // The assumption is that the cost of other tokenizer code is dwarfed by + // this one. + AutoTraceLog tokenizerLog(TraceLoggerForCurrentThread(cx), TraceLogger_Tokenizing); + int c; uint32_t qc; Token* tp; diff --git a/js/src/vm/TraceLogging.cpp b/js/src/vm/TraceLogging.cpp index 88fd753645a3..7748b63d3fe0 100644 --- a/js/src/vm/TraceLogging.cpp +++ b/js/src/vm/TraceLogging.cpp @@ -427,7 +427,7 @@ TraceLoggerThreadState::getOrCreateEventPayload(TraceLoggerTextId type, const ch size_t lineno, size_t colno, const void* ptr) { MOZ_ASSERT(type == TraceLogger_Scripts || type == TraceLogger_AnnotateScripts || - type == TraceLogger_InlinedScripts); + type == TraceLogger_InlinedScripts || type == TraceLogger_Frontend); if (!filename) filename = ""; @@ -500,13 +500,6 @@ TraceLoggerThreadState::getOrCreateEventPayload(TraceLoggerTextId type, JSScript nullptr); } -TraceLoggerEventPayload* -TraceLoggerThreadState::getOrCreateEventPayload(TraceLoggerTextId type, - const JS::ReadOnlyCompileOptions& script) -{ - return getOrCreateEventPayload(type, script.filename(), script.lineno, script.column, nullptr); -} - void TraceLoggerThreadState::purgeUnusedPayloads() { @@ -736,9 +729,9 @@ TraceLoggerThreadState::init() " Default Output all default. It includes:\n" " AnnotateScripts, Bailout, Baseline, BaselineCompilation, GC,\n" " GCAllocation, GCSweeping, Interpreter, IonAnalysis, IonCompilation,\n" - " IonLinking, IonMonkey, MinorGC, ParserCompileFunction,\n" - " ParserCompileScript, ParserCompileLazy, ParserCompileModule,\n" - " IrregexpCompile, IrregexpExecute, Scripts, Engine, WasmCompilation\n" + " IonLinking, IonMonkey, MinorGC, Frontend, ParsingFull,\n" + " ParsingSyntax, BytecodeEmission, IrregexpCompile, IrregexpExecute,\n" + " Scripts, Engine, WasmCompilation\n" "\n" " IonCompiler Output all information about compilation. It includes:\n" " IonCompilation, IonLinking, PruneUnusedBranches, FoldTests,\n" @@ -751,8 +744,11 @@ TraceLoggerThreadState::init() " AddKeepAliveInstructions, GenerateLIR, RegisterAllocation, \n" " GenerateCode, Scripts, IonBuilderRestartLoop\n" "\n" - " VMSpecific Output the specific name of the VM call" + " VMSpecific Output the specific name of the VM call\n" "\n" + " Frontend Output all information about frontend compilation. It includes:\n" + " Frontend, ParsingFull, ParsingSyntax, Tokenizing,\n" + " BytecodeEmission, BytecodeFoldConstants, BytecodeNameFunctions\n" "Specific log items:\n" ); for (uint32_t i = 1; i < TraceLogger_Last; i++) { @@ -788,10 +784,10 @@ TraceLoggerThreadState::init() enabledTextIds[TraceLogger_IonLinking] = true; enabledTextIds[TraceLogger_IonMonkey] = true; enabledTextIds[TraceLogger_MinorGC] = true; - enabledTextIds[TraceLogger_ParserCompileFunction] = true; - enabledTextIds[TraceLogger_ParserCompileLazy] = true; - enabledTextIds[TraceLogger_ParserCompileScript] = true; - enabledTextIds[TraceLogger_ParserCompileModule] = true; + enabledTextIds[TraceLogger_Frontend] = true; + enabledTextIds[TraceLogger_ParsingFull] = true; + enabledTextIds[TraceLogger_ParsingSyntax] = true; + enabledTextIds[TraceLogger_BytecodeEmission] = true; enabledTextIds[TraceLogger_IrregexpCompile] = true; enabledTextIds[TraceLogger_IrregexpExecute] = true; enabledTextIds[TraceLogger_Scripts] = true; @@ -833,6 +829,18 @@ TraceLoggerThreadState::init() enabledTextIds[TraceLogger_IonBuilderRestartLoop] = true; } + if (ContainsFlag(env, "Frontend")) { + enabledTextIds[TraceLogger_Frontend] = true; + enabledTextIds[TraceLogger_FrontendNameAnalysis] = true; + enabledTextIds[TraceLogger_FrontendTDZAnalysis] = true; + enabledTextIds[TraceLogger_ParsingFull] = true; + enabledTextIds[TraceLogger_ParsingSyntax] = true; + enabledTextIds[TraceLogger_Tokenizing] = true; + enabledTextIds[TraceLogger_BytecodeEmission] = true; + enabledTextIds[TraceLogger_BytecodeFoldConstants] = true; + enabledTextIds[TraceLogger_BytecodeNameFunctions] = true; + } + enabledTextIds[TraceLogger_Interpreter] = enabledTextIds[TraceLogger_Engine]; enabledTextIds[TraceLogger_Baseline] = enabledTextIds[TraceLogger_Engine]; enabledTextIds[TraceLogger_IonMonkey] = enabledTextIds[TraceLogger_Engine]; @@ -1014,10 +1022,13 @@ TraceLoggerEvent::TraceLoggerEvent(TraceLoggerTextId type, JSScript* script) payload_ = traceLoggerState ? traceLoggerState->getOrCreateEventPayload(type, script) : nullptr; } -TraceLoggerEvent::TraceLoggerEvent(TraceLoggerTextId type, - const JS::ReadOnlyCompileOptions& compileOptions) +TraceLoggerEvent::TraceLoggerEvent(TraceLoggerTextId type, const char* filename, size_t line, + size_t column) + { - payload_ = traceLoggerState ? traceLoggerState->getOrCreateEventPayload(type, compileOptions) : nullptr; + payload_ = traceLoggerState + ? traceLoggerState->getOrCreateEventPayload(type, filename, line, column, nullptr) + : nullptr; } TraceLoggerEvent::TraceLoggerEvent(const char* text) diff --git a/js/src/vm/TraceLogging.h b/js/src/vm/TraceLogging.h index 038a39a3bcdb..7d3388d92326 100644 --- a/js/src/vm/TraceLogging.h +++ b/js/src/vm/TraceLogging.h @@ -88,8 +88,7 @@ class TraceLoggerEvent { #ifdef JS_TRACE_LOGGING explicit TraceLoggerEvent(TraceLoggerTextId textId); TraceLoggerEvent(TraceLoggerTextId type, JSScript* script); - TraceLoggerEvent(TraceLoggerTextId type, - const JS::ReadOnlyCompileOptions& compileOptions); + TraceLoggerEvent(TraceLoggerTextId type, const char* filename, size_t line, size_t column); explicit TraceLoggerEvent(const char* text); TraceLoggerEvent(const TraceLoggerEvent& event); TraceLoggerEvent& operator=(const TraceLoggerEvent& other); @@ -97,8 +96,7 @@ class TraceLoggerEvent { #else explicit TraceLoggerEvent(TraceLoggerTextId textId) {} TraceLoggerEvent(TraceLoggerTextId type, JSScript* script) {} - TraceLoggerEvent(TraceLoggerTextId type, - const JS::ReadOnlyCompileOptions& compileOptions) {} + TraceLoggerEvent(TraceLoggerTextId type, const char* filename, size_t line, size_t column) {} explicit TraceLoggerEvent(const char* text) {} TraceLoggerEvent(const TraceLoggerEvent& event) {} TraceLoggerEvent& operator=(const TraceLoggerEvent& other) { return *this; }; @@ -383,9 +381,6 @@ class TraceLoggerThreadState TraceLoggerEventPayload* getOrCreateEventPayload(TraceLoggerTextId textId); TraceLoggerEventPayload* getOrCreateEventPayload(const char* text); TraceLoggerEventPayload* getOrCreateEventPayload(TraceLoggerTextId type, JSScript* script); - TraceLoggerEventPayload* getOrCreateEventPayload(TraceLoggerTextId type, - const JS::ReadOnlyCompileOptions& script); - private: TraceLoggerEventPayload* getOrCreateEventPayload(TraceLoggerTextId type, const char* filename, size_t lineno, size_t colno, const void* p); #endif diff --git a/js/src/vm/TraceLoggingTypes.h b/js/src/vm/TraceLoggingTypes.h index 779cac1db232..8ee5a2e32c84 100644 --- a/js/src/vm/TraceLoggingTypes.h +++ b/js/src/vm/TraceLoggingTypes.h @@ -29,10 +29,15 @@ _(IrregexpCompile) \ _(IrregexpExecute) \ _(MinorGC) \ - _(ParserCompileFunction) \ - _(ParserCompileLazy) \ - _(ParserCompileScript) \ - _(ParserCompileModule) \ + _(Frontend) \ + _(FrontendNameAnalysis) \ + _(FrontendTDZAnalysis) \ + _(ParsingFull) \ + _(ParsingSyntax) \ + _(Tokenizing) \ + _(BytecodeEmission) \ + _(BytecodeFoldConstants) \ + _(BytecodeNameFunctions) \ _(DecodeScript) \ _(DecodeFunction) \ _(EncodeScript) \