Bug 1342273 - Improve frontend tracelogging. (r=h4writer)
authorShu-yu Guo <shu@rfrn.org>
Fri, 24 Feb 2017 12:52:13 -0800
changeset 373917 cc682c2db247433a4aad347f0d20ddbc968eb26b
parent 373916 456c1dcfe087675f3ee80ce68ccb88ce56021cbc
child 373918 f4eae24795b9ae702254e576a1f2c5d8d72c7a60
push id10863
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 23:02:23 +0000
treeherdermozilla-aurora@0931190cd725 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersh4writer
bugs1342273
milestone54.0a1
Bug 1342273 - Improve frontend tracelogging. (r=h4writer)
js/src/frontend/BytecodeCompiler.cpp
js/src/frontend/BytecodeCompiler.h
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/BytecodeEmitter.h
js/src/frontend/FoldConstants.cpp
js/src/frontend/NameFunctions.cpp
js/src/frontend/Parser.cpp
js/src/frontend/Parser.h
js/src/frontend/TokenStream.cpp
js/src/vm/TraceLogging.cpp
js/src/vm/TraceLogging.h
js/src/vm/TraceLoggingTypes.h
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -26,41 +26,27 @@
 
 #include "vm/EnvironmentObject-inl.h"
 
 using namespace js;
 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
 {
   public:
     // Construct an object passing mandatory arguments.
     BytecodeCompiler(JSContext* cx,
                      LifoAlloc& alloc,
                      const ReadOnlyCompileOptions& options,
                      SourceBufferHolder& sourceBuffer,
-                     HandleScope enclosingScope,
-                     TraceLoggerTextId logId);
+                     HandleScope enclosingScope);
 
     // Call setters for optional arguments.
     void maybeSetSourceCompressor(SourceCompressionTask* sourceCompressor);
 
     JSScript* compileGlobalScript(ScopeKind scopeKind);
     JSScript* compileEvalScript(HandleObject environment, HandleScope enclosingScope);
     ModuleObject* compileModule();
     bool compileStandaloneFunction(MutableHandleFunction fun, GeneratorKind generatorKind,
@@ -78,17 +64,16 @@ class MOZ_STACK_CLASS BytecodeCompiler
     bool createParser();
     bool createSourceAndParser(const Maybe<uint32_t>& parameterListEnd = Nothing());
     bool createScript();
     bool emplaceEmitter(Maybe<BytecodeEmitter>& emitter, SharedContext* sharedContext);
     bool handleParseFailure(const Directives& newDirectives);
     bool deoptimizeArgumentsInEnclosingScripts(JSContext* cx, HandleObject environment);
     bool maybeCompleteCompressSource();
 
-    AutoCompilationTraceLogger traceLogger;
     AutoKeepAtoms keepAtoms;
 
     JSContext* cx;
     LifoAlloc& alloc;
     const ReadOnlyCompileOptions& options;
     SourceBufferHolder& sourceBuffer;
 
     RootedScope enclosingScope;
@@ -104,32 +89,87 @@ class MOZ_STACK_CLASS BytecodeCompiler
     Maybe<Parser<FullParseHandler>> parser;
 
     Directives directives;
     TokenStream::Position startPosition;
 
     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),
     sourceBuffer(sourceBuffer),
     enclosingScope(cx, enclosingScope),
     sourceObject(cx),
     scriptSource(nullptr),
     sourceCompressor(nullptr),
@@ -551,33 +591,31 @@ class MOZ_STACK_CLASS AutoInitializeSour
 JSScript*
 frontend::CompileGlobalScript(JSContext* cx, LifoAlloc& alloc, ScopeKind scopeKind,
                               const ReadOnlyCompileOptions& options,
                               SourceBufferHolder& srcBuf,
                               SourceCompressionTask* extraSct,
                               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);
 }
 
 JSScript*
 frontend::CompileEvalScript(JSContext* cx, LifoAlloc& alloc,
                             HandleObject environment, HandleScope enclosingScope,
                             const ReadOnlyCompileOptions& options,
                             SourceBufferHolder& srcBuf,
                             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);
 }
 
 ModuleObject*
 frontend::CompileModule(JSContext* cx, const ReadOnlyCompileOptions& optionsInput,
                         SourceBufferHolder& srcBuf, LifoAlloc& alloc,
@@ -587,18 +625,17 @@ frontend::CompileModule(JSContext* cx, c
     MOZ_ASSERT_IF(sourceObjectOut, *sourceObjectOut == nullptr);
 
     CompileOptions options(cx, optionsInput);
     options.maybeMakeStrictMode(true); // ES6 10.2.1 Module code is always strict mode code.
     options.setIsRunOnce(true);
     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();
 }
 
 ModuleObject*
 frontend::CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
                         SourceBufferHolder& srcBuf)
 {
@@ -625,18 +662,16 @@ frontend::CompileLazyFunction(JSContext*
 
     CompileOptions options(cx, lazy->version());
     options.setMutedErrors(lazy->mutedErrors())
            .setFileAndLine(lazy->filename(), lazy->lineno())
            .setColumn(lazy->column())
            .setNoScriptRval(false)
            .setSelfHostingMode(false);
 
-    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())
         return false;
 
@@ -687,38 +722,35 @@ frontend::CompileStandaloneFunction(JSCo
                                     JS::SourceBufferHolder& srcBuf,
                                     const Maybe<uint32_t>& parameterListEnd,
                                     HandleScope enclosingScope /* = nullptr */)
 {
     RootedScope scope(cx, enclosingScope);
     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);
 }
 
 bool
 frontend::CompileStandaloneGenerator(JSContext* cx, MutableHandleFunction fun,
                                      const ReadOnlyCompileOptions& options,
                                      JS::SourceBufferHolder& srcBuf,
                                      const Maybe<uint32_t>& parameterListEnd)
 {
     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);
 }
 
 bool
 frontend::CompileStandaloneAsyncFunction(JSContext* cx, MutableHandleFunction fun,
                                          const ReadOnlyCompileOptions& options,
                                          JS::SourceBufferHolder& srcBuf,
                                          const Maybe<uint32_t>& parameterListEnd)
 {
     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);
 }
--- a/js/src/frontend/BytecodeCompiler.h
+++ b/js/src/frontend/BytecodeCompiler.h
@@ -8,29 +8,34 @@
 #define frontend_BytecodeCompiler_h
 
 #include "mozilla/Maybe.h"
 
 #include "NamespaceImports.h"
 
 #include "vm/Scope.h"
 #include "vm/String.h"
+#include "vm/TraceLogging.h"
 
 class JSLinearString;
 
 namespace js {
 
 class LazyScript;
 class LifoAlloc;
 class ModuleObject;
 class ScriptSourceObject;
 struct SourceCompressionTask;
 
 namespace frontend {
 
+class TokenStream;
+class FunctionBox;
+class ParseNode;
+
 JSScript*
 CompileGlobalScript(JSContext* cx, LifoAlloc& alloc, ScopeKind scopeKind,
                     const ReadOnlyCompileOptions& options,
                     SourceBufferHolder& srcBuf,
                     SourceCompressionTask* extraSct = nullptr,
                     ScriptSourceObject** sourceObjectOut = nullptr);
 
 JSScript*
@@ -114,12 +119,35 @@ IsIdentifier(const char16_t* chars, size
 /* True if str is a keyword. Defined in TokenStream.cpp. */
 bool
 IsKeyword(JSLinearString* str);
 
 /* Trace all GC things reachable from parser. Defined in Parser.cpp. */
 void
 TraceParser(JSTracer* trc, JS::AutoGCRooter* parser);
 
+class MOZ_STACK_CLASS AutoFrontendTraceLog
+{
+#ifdef JS_TRACE_LOGGING
+    TraceLoggerThread* logger_;
+    mozilla::Maybe<TraceLoggerEvent> frontendEvent_;
+    mozilla::Maybe<AutoTraceLog> frontendLog_;
+    mozilla::Maybe<AutoTraceLog> 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 */
 
 #endif /* frontend_BytecodeCompiler_h */
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -575,16 +575,18 @@ class BytecodeEmitter::EmitterScope : pu
         return frameSlotEnd() - frameSlotStart();
     }
 
     EmitterScope* enclosingInFrame() const {
         return Nestable<EmitterScope>::enclosing();
     }
 
     NameLocation lookup(BytecodeEmitter* bce, JSAtom* name) {
+        AutoTraceLog traceLog(TraceLoggerForCurrentThread(bce->cx),
+                              TraceLogger_FrontendNameAnalysis);
         if (Maybe<NameLocation> loc = lookupInCache(bce, name))
             return *loc;
         return searchAndCache(bce, name);
     }
 
     Maybe<NameLocation> locationBoundInScope(BytecodeEmitter* bce, JSAtom* name,
                                              EmitterScope* target);
 };
@@ -861,16 +863,18 @@ BytecodeEmitter::EmitterScope::searchAnd
 
     return *loc;
 }
 
 Maybe<NameLocation>
 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;
     for (EmitterScope* es = this; es != target; es = es->enclosingInFrame()) {
         if (es->hasEnvironment())
             extraHops++;
     }
 
@@ -918,16 +922,18 @@ BytecodeEmitter::EmitterScope::deadZoneF
 {
     return deadZoneFrameSlotRange(bce, frameSlotStart(), frameSlotEnd());
 }
 
 bool
 BytecodeEmitter::EmitterScope::enterLexical(BytecodeEmitter* bce, ScopeKind kind,
                                             Handle<LexicalScope::Data*> bindings)
 {
+    AutoTraceLog traceLog(TraceLoggerForCurrentThread(bce->cx), TraceLogger_FrontendNameAnalysis);
+
     MOZ_ASSERT(kind != ScopeKind::NamedLambda && kind != ScopeKind::StrictNamedLambda);
     MOZ_ASSERT(this == bce->innermostEmitterScope);
 
     if (!ensureCache(bce))
         return false;
 
     // Marks all names as closed over if the the context requires it. This
     // cannot be done in the Parser as we may not know if the context requires
@@ -988,16 +994,18 @@ BytecodeEmitter::EmitterScope::enterLexi
         return false;
 
     return checkEnvironmentChainLength(bce);
 }
 
 bool
 BytecodeEmitter::EmitterScope::enterNamedLambda(BytecodeEmitter* bce, FunctionBox* funbox)
 {
+    AutoTraceLog traceLog(TraceLoggerForCurrentThread(bce->cx), TraceLogger_FrontendNameAnalysis);
+
     MOZ_ASSERT(this == bce->innermostEmitterScope);
     MOZ_ASSERT(funbox->namedLambdaBindings());
 
     if (!ensureCache(bce))
         return false;
 
     // See comment in enterLexical about allBindingsClosedOver.
     if (funbox->allBindingsClosedOver())
@@ -1055,16 +1063,18 @@ BytecodeEmitter::EmitterScope::enterComp
         return false;
 
     return true;
 }
 
 bool
 BytecodeEmitter::EmitterScope::enterParameterExpressionVar(BytecodeEmitter* bce)
 {
+    AutoTraceLog traceLog(TraceLoggerForCurrentThread(bce->cx), TraceLogger_FrontendNameAnalysis);
+
     MOZ_ASSERT(this == bce->innermostEmitterScope);
 
     if (!ensureCache(bce))
         return false;
 
     // Parameter expressions var scopes have no pre-set bindings and are
     // always extensible, as they are needed for eval.
     fallbackFreeNameLocation_ = Some(NameLocation::Dynamic());
@@ -1176,16 +1186,18 @@ BytecodeEmitter::EmitterScope::enterFunc
         return false;
 
     return checkEnvironmentChainLength(bce);
 }
 
 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());
     MOZ_ASSERT(this == bce->innermostEmitterScope);
 
     // The extra var scope is never popped once it's entered. It replaces the
     // function scope as the var emitter scope.
     bce->setVarEmitterScope(this);
@@ -1265,16 +1277,18 @@ class DynamicBindingIter : public Bindin
             MOZ_CRASH("Bad BindingKind");
         }
     }
 };
 
 bool
 BytecodeEmitter::EmitterScope::enterGlobal(BytecodeEmitter* bce, GlobalSharedContext* globalsc)
 {
+    AutoTraceLog traceLog(TraceLoggerForCurrentThread(bce->cx), TraceLogger_FrontendNameAnalysis);
+
     MOZ_ASSERT(this == bce->innermostEmitterScope);
 
     bce->setVarEmitterScope(this);
 
     if (!ensureCache(bce))
         return false;
 
     if (bce->emitterMode == BytecodeEmitter::SelfHosting) {
@@ -1325,16 +1339,18 @@ BytecodeEmitter::EmitterScope::enterGlob
         return GlobalScope::create(cx, globalsc->scopeKind(), globalsc->bindings);
     };
     return internBodyScope(bce, createScope);
 }
 
 bool
 BytecodeEmitter::EmitterScope::enterEval(BytecodeEmitter* bce, EvalSharedContext* evalsc)
 {
+    AutoTraceLog traceLog(TraceLoggerForCurrentThread(bce->cx), TraceLogger_FrontendNameAnalysis);
+
     MOZ_ASSERT(this == bce->innermostEmitterScope);
 
     bce->setVarEmitterScope(this);
 
     if (!ensureCache(bce))
         return false;
 
     // For simplicity, treat all free name lookups in eval scripts as dynamic.
@@ -1380,16 +1396,18 @@ BytecodeEmitter::EmitterScope::enterEval
     }
 
     return true;
 }
 
 bool
 BytecodeEmitter::EmitterScope::enterModule(BytecodeEmitter* bce, ModuleSharedContext* modulesc)
 {
+    AutoTraceLog traceLog(TraceLoggerForCurrentThread(bce->cx), TraceLogger_FrontendNameAnalysis);
+
     MOZ_ASSERT(this == bce->innermostEmitterScope);
 
     bce->setVarEmitterScope(this);
 
     if (!ensureCache(bce))
         return false;
 
     // Resolve body-level bindings, if there are any.
@@ -1437,16 +1455,18 @@ BytecodeEmitter::EmitterScope::enterModu
         return false;
 
     return checkEnvironmentChainLength(bce);
 }
 
 bool
 BytecodeEmitter::EmitterScope::enterWith(BytecodeEmitter* bce)
 {
+    AutoTraceLog traceLog(TraceLoggerForCurrentThread(bce->cx), TraceLogger_FrontendNameAnalysis);
+
     MOZ_ASSERT(this == bce->innermostEmitterScope);
 
     if (!ensureCache(bce))
         return false;
 
     // 'with' make all accesses dynamic and unanalyzable.
     fallbackFreeNameLocation_ = Some(NameLocation::Dynamic());
 
@@ -1463,16 +1483,18 @@ BytecodeEmitter::EmitterScope::enterWith
         return false;
 
     return checkEnvironmentChainLength(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);
 
     ScopeKind kind = scope(bce)->kind();
     switch (kind) {
       case ScopeKind::Lexical:
       case ScopeKind::SimpleCatch:
@@ -1520,16 +1542,18 @@ BytecodeEmitter::EmitterScope::leave(Byt
     }
 
     return true;
 }
 
 Maybe<MaybeCheckTDZ>
 BytecodeEmitter::TDZCheckCache::needsTDZCheck(BytecodeEmitter* bce, JSAtom* name)
 {
+    AutoTraceLog traceLog(TraceLoggerForCurrentThread(bce->cx), TraceLogger_FrontendTDZAnalysis);
+
     if (!ensureCache(bce))
         return Nothing();
 
     CheckTDZMap::AddPtr p = cache_->lookupForAdd(name);
     if (p)
         return Some(p->value().wrapped);
 
     MaybeCheckTDZ rv = CheckTDZ;
@@ -1549,16 +1573,18 @@ BytecodeEmitter::TDZCheckCache::needsTDZ
 
     return Some(rv);
 }
 
 bool
 BytecodeEmitter::TDZCheckCache::noteTDZCheck(BytecodeEmitter* bce, JSAtom* name,
                                              MaybeCheckTDZ check)
 {
+    AutoTraceLog traceLog(TraceLoggerForCurrentThread(bce->cx), TraceLogger_FrontendTDZAnalysis);
+
     if (!ensureCache(bce))
         return false;
 
     CheckTDZMap::AddPtr p = cache_->lookupForAdd(name);
     if (p) {
         MOZ_ASSERT(!check, "TDZ only needs to be checked once per binding per basic block.");
         p->value() = check;
     } else {
@@ -3443,29 +3469,29 @@ BytecodeEmitter::needsImplicitThis()
     }
 
     return false;
 }
 
 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;
 }
 
 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;
     }
 
     /*
      * Source map URLs passed as a compile option (usually via a HTTP source map
      * header) override any source map urls passed as comment pragmas.
      */
     if (parser->options().sourceMapURL()) {
@@ -3494,57 +3520,57 @@ BytecodeEmitter::tellDebuggerAboutCompil
         return;
 
     // Lazy scripts are never top level (despite always being invoked with a
     // nullptr parent), and so the hook should never be fired.
     if (emitterMode != LazyFunction && !parent)
         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;
 }
 
 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;
 }
 
 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;
 }
 
 bool
 BytecodeEmitter::emitNewInit(JSProtoKey key)
 {
     const size_t len = 1 + UINT32_INDEX_LEN;
@@ -4784,16 +4810,18 @@ BytecodeEmitter::emitSetThis(ParseNode* 
     }
 
     return emitSetOrInitializeNameAtLocation(name, lexicalLoc, emitRhs, true);
 }
 
 bool
 BytecodeEmitter::emitScript(ParseNode* body)
 {
+    AutoFrontendTraceLog traceLog(cx, TraceLogger_BytecodeEmission, tokenStream(), body);
+
     TDZCheckCache tdzCache(this);
     EmitterScope emitterScope(this);
     if (sc->isGlobalContext()) {
         switchToPrologue();
         if (!emitterScope.enterGlobal(this, sc->asGlobalContext()))
             return false;
         switchToMain();
     } else if (sc->isEvalContext()) {
@@ -4851,16 +4879,17 @@ BytecodeEmitter::emitScript(ParseNode* b
 
     return true;
 }
 
 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
     // var scope.
 
     Maybe<EmitterScope> namedLambdaEmitterScope;
     if (funbox->namedLambdaBindings()) {
         namedLambdaEmitterScope.emplace(this);
--- a/js/src/frontend/BytecodeEmitter.h
+++ b/js/src/frontend/BytecodeEmitter.h
@@ -347,17 +347,17 @@ struct MOZ_STACK_CLASS BytecodeEmitter
     MOZ_MUST_USE bool checkRunOnceContext();
 
     bool needsImplicitThis();
 
     MOZ_MUST_USE bool maybeSetDisplayURL();
     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; }
     ptrdiff_t offset() const { return current->code.end() - current->code.begin(); }
     ptrdiff_t prologueOffset() const { return prologue.code.end() - prologue.code.begin(); }
     void switchToMain() { current = &main; }
     void switchToPrologue() { current = &prologue; }
     bool inPrologue() const { return current == &prologue; }
--- a/js/src/frontend/FoldConstants.cpp
+++ b/js/src/frontend/FoldConstants.cpp
@@ -1923,10 +1923,11 @@ Fold(JSContext* cx, ParseNode** pnp, Par
 bool
 frontend::FoldConstants(JSContext* cx, ParseNode** pnp, Parser<FullParseHandler>* parser)
 {
     // Don't constant-fold inside "use asm" code, as this could create a parse
     // tree that doesn't type-check as asm.js.
     if (parser->pc->useAsmOrInsideUseAsm())
         return true;
 
+    AutoTraceLog traceLog(TraceLoggerForCurrentThread(cx), TraceLogger_BytecodeFoldConstants);
     return Fold(cx, pnp, *parser, false);
 }
--- a/js/src/frontend/NameFunctions.cpp
+++ b/js/src/frontend/NameFunctions.cpp
@@ -830,11 +830,12 @@ class NameResolver
     }
 };
 
 } /* anonymous namespace */
 
 bool
 frontend::NameFunctions(JSContext* cx, ParseNode* pn)
 {
+    AutoTraceLog traceLog(TraceLoggerForCurrentThread(cx), TraceLogger_BytecodeNameFunctions);
     NameResolver nr(cx);
     return nr.resolve(pn);
 }
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -1013,16 +1013,18 @@ Parser<ParseHandler>::reportRedeclaratio
 // features, we consider the code to have "opted in" to higher standards and
 // forbid duplicates.)
 template <typename ParseHandler>
 bool
 Parser<ParseHandler>::notePositionalFormalParameter(Node fn, HandlePropertyName name,
                                                     bool disallowDuplicateParams,
                                                     bool* duplicatedParam)
 {
+    AutoTraceLog traceLog(TraceLoggerForCurrentThread(context), TraceLogger_FrontendNameAnalysis);
+
     if (AddDeclaredNamePtr p = pc->functionScope().lookupDeclaredNameForAdd(name)) {
         if (disallowDuplicateParams) {
             error(JSMSG_BAD_DUP_ARGS);
             return false;
         }
 
         // Strict-mode disallows duplicate args. We may not know whether we are
         // in strict mode or not (since the function body hasn't been parsed).
@@ -1238,16 +1240,18 @@ Parser<ParseHandler>::tryDeclareVar(Hand
     return true;
 }
 
 template <typename ParseHandler>
 bool
 Parser<ParseHandler>::tryDeclareVarForAnnexBLexicalFunction(HandlePropertyName name,
                                                             bool* tryAnnexB)
 {
+    AutoTraceLog traceLog(TraceLoggerForCurrentThread(context), TraceLogger_FrontendNameAnalysis);
+
     Maybe<DeclarationKind> redeclaredKind;
     if (!tryDeclareVar(name, DeclarationKind::VarForAnnexBLexicalFunction, &redeclaredKind))
         return false;
 
     if (!redeclaredKind && pc->isFunctionBox()) {
         ParseContext::Scope& funScope = pc->functionScope();
         ParseContext::Scope& varScope = pc->varScope();
         if (&funScope != &varScope) {
@@ -1302,16 +1306,18 @@ Parser<ParseHandler>::checkLexicalDeclar
     return true;
 }
 
 template <typename ParseHandler>
 bool
 Parser<ParseHandler>::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())
         return true;
 
     switch (kind) {
       case DeclarationKind::Var:
       case DeclarationKind::BodyLevelFunction:
@@ -1454,16 +1460,18 @@ Parser<ParseHandler>::noteDeclaredName(H
 
     return true;
 }
 
 template <typename ParseHandler>
 bool
 Parser<ParseHandler>::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())
         return true;
 
     // The asm.js validator does all its own symbol-table management so, as an
     // optimization, avoid doing any work here.
     if (pc->useAsmOrInsideUseAsm())
@@ -1479,25 +1487,29 @@ Parser<ParseHandler>::noteUsedName(Handl
 
     return usedNames.noteUse(context, name, pc->scriptId(), scope->id());
 }
 
 template <typename ParseHandler>
 bool
 Parser<ParseHandler>::hasUsedName(HandlePropertyName name)
 {
+    AutoTraceLog traceLog(TraceLoggerForCurrentThread(context), TraceLogger_FrontendNameAnalysis);
+
     if (UsedNamePtr p = usedNames.lookup(name))
         return p->value().isUsedInScript(pc->scriptId());
     return false;
 }
 
 template <typename ParseHandler>
 bool
 Parser<ParseHandler>::propagateFreeNamesAndMarkClosedOverBindings(ParseContext::Scope& scope)
 {
+    AutoTraceLog traceLog(TraceLoggerForCurrentThread(context), TraceLogger_FrontendNameAnalysis);
+
     if (handler.canSkipLazyClosedOverBindings()) {
         // Scopes are nullptr-delimited in the LazyScript closed over bindings
         // array.
         while (JSAtom* name = handler.nextLazyClosedOverBinding())
             scope.lookupDeclaredName(name)->value()->setClosedOver();
         return true;
     }
 
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -6,16 +6,17 @@
 
 /* JS parser. */
 
 #ifndef frontend_Parser_h
 #define frontend_Parser_h
 
 #include "mozilla/Array.h"
 #include "mozilla/Maybe.h"
+#include "mozilla/TypeTraits.h"
 
 #include "jspubtd.h"
 
 #include "frontend/BytecodeCompiler.h"
 #include "frontend/FullParseHandler.h"
 #include "frontend/NameAnalysisTypes.h"
 #include "frontend/NameCollections.h"
 #include "frontend/SharedContext.h"
@@ -250,16 +251,19 @@ class ParseContext : public Nestable<Par
         explicit VarScope(Parser<ParseHandler>* parser)
           : Scope(parser)
         {
             useAsVarScope(parser->pc);
         }
     };
 
   private:
+    // Trace logging of parsing time.
+    AutoFrontendTraceLog traceLog_;
+
     // Context shared between parsing and bytecode generation.
     SharedContext* sc_;
 
     // TokenStream used for error reporting.
     TokenStream& tokenStream_;
 
     // The innermost statement, i.e., top of the statement stack.
     Statement* innermostStatement_;
@@ -346,16 +350,21 @@ class ParseContext : public Nestable<Par
 
     // Set when parsing a function and it has 'return;'
     bool funHasReturnVoid;
 
   public:
     template <typename ParseHandler>
     ParseContext(Parser<ParseHandler>* prs, SharedContext* sc, Directives* newDirectives)
       : Nestable<ParseContext>(&prs->pc),
+        traceLog_(sc->context,
+                  mozilla::IsSame<ParseHandler, FullParseHandler>::value
+                  ? TraceLogger_ParsingFull
+                  : TraceLogger_ParsingSyntax,
+                  prs->tokenStream),
         sc_(sc),
         tokenStream_(prs->tokenStream),
         innermostStatement_(nullptr),
         innermostScope_(nullptr),
         varScope_(nullptr),
         innerFunctionBoxesForAnnexB_(prs->context->frontendCollectionPool()),
         positionalFormalParameterNames_(prs->context->frontendCollectionPool()),
         closedOverBindingsForLazy_(prs->context->frontendCollectionPool()),
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -1291,16 +1291,20 @@ static const uint8_t firstCharKinds[] = 
 #undef _______
 
 static_assert(LastCharKind < (1 << (sizeof(firstCharKinds[0]) * 8)),
               "Elements of firstCharKinds[] are too small");
 
 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;
     FirstCharKind c1kind;
     const char16_t* numStart;
     bool hasExp;
     DecimalPoint decimalPoint;
     const char16_t* identStart;
--- a/js/src/vm/TraceLogging.cpp
+++ b/js/src/vm/TraceLogging.cpp
@@ -422,17 +422,17 @@ TraceLoggerThreadState::getOrCreateEvent
     return payload;
 }
 
 TraceLoggerEventPayload*
 TraceLoggerThreadState::getOrCreateEventPayload(TraceLoggerTextId type, const char* filename,
                                                 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 = "<unknown>";
 
     // Only log scripts when enabled otherwise return the global Scripts textId,
     // which will get filtered out.
     if (!isTextIdEnabled(type))
         return getOrCreateEventPayload(type);
@@ -495,23 +495,16 @@ TraceLoggerThreadState::getOrCreateEvent
 
 TraceLoggerEventPayload*
 TraceLoggerThreadState::getOrCreateEventPayload(TraceLoggerTextId type, JSScript* script)
 {
     return getOrCreateEventPayload(type, script->filename(), script->lineno(), script->column(),
                                    nullptr);
 }
 
-TraceLoggerEventPayload*
-TraceLoggerThreadState::getOrCreateEventPayload(TraceLoggerTextId type,
-                                                const JS::ReadOnlyCompileOptions& script)
-{
-    return getOrCreateEventPayload(type, script.filename(), script.lineno, script.column, nullptr);
-}
-
 void
 TraceLoggerThreadState::purgeUnusedPayloads()
 {
     // Care needs to be taken to maintain a coherent state in this function,
     // as payloads can have their use count change at any time from non-zero to
     // zero (but not the other way around; see TraceLoggerEventPayload::use()).
     LockGuard<Mutex> guard(lock);
 
@@ -731,33 +724,36 @@ TraceLoggerThreadState::init()
         printf(
             "\n"
             "usage: TLLOG=option,option,option,... where options can be:\n"
             "\n"
             "Collections:\n"
             "  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"
             "                 SplitCriticalEdges, RenumberBlocks, ScalarReplacement, \n"
             "                 DominatorTree, PhiAnalysis, MakeLoopsContiguous, ApplyTypes, \n"
             "                 EagerSimdUnbox, AliasAnalysis, GVN, LICM, Sincos, RangeAnalysis, \n"
             "                 LoopUnrolling, FoldLinearArithConstants, EffectiveAddressAnalysis, \n"
             "                 AlignmentMaskAnalysis, EliminateDeadCode, ReorderInstructions, \n"
             "                 EdgeCaseAnalysis, EliminateRedundantChecks, \n"
             "                 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++) {
             TraceLoggerTextId id = TraceLoggerTextId(i);
             if (!TLTextIdIsTogglable(id))
                 continue;
             printf("  %s\n", TLTextIdString(id));
         }
@@ -783,20 +779,20 @@ TraceLoggerThreadState::init()
         enabledTextIds[TraceLogger_GCAllocation] = true;
         enabledTextIds[TraceLogger_GCSweeping] = true;
         enabledTextIds[TraceLogger_Interpreter] = true;
         enabledTextIds[TraceLogger_IonAnalysis] = true;
         enabledTextIds[TraceLogger_IonCompilation] = true;
         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;
         enabledTextIds[TraceLogger_Engine] = true;
         enabledTextIds[TraceLogger_WasmCompilation] = true;
     }
 
     if (ContainsFlag(env, "IonCompiler")) {
@@ -828,16 +824,28 @@ TraceLoggerThreadState::init()
         enabledTextIds[TraceLogger_AddKeepAliveInstructions] = true;
         enabledTextIds[TraceLogger_GenerateLIR] = true;
         enabledTextIds[TraceLogger_RegisterAllocation] = true;
         enabledTextIds[TraceLogger_GenerateCode] = true;
         enabledTextIds[TraceLogger_Scripts] = true;
         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];
 
     enabledTextIds[TraceLogger_Error] = true;
 
     const char* options = getenv("TLOPTIONS");
     if (options) {
@@ -1009,20 +1017,23 @@ TraceLoggerEvent::TraceLoggerEvent(Trace
     payload_ = traceLoggerState ? traceLoggerState->getOrCreateEventPayload(textId) : nullptr;
 }
 
 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)
 {
     payload_ = traceLoggerState ? traceLoggerState->getOrCreateEventPayload(text) : nullptr;
 }
 
 TraceLoggerEvent::~TraceLoggerEvent()
--- a/js/src/vm/TraceLogging.h
+++ b/js/src/vm/TraceLogging.h
@@ -83,27 +83,25 @@ class TraceLoggerEvent {
   private:
     TraceLoggerEventPayload* payload_;
 
   public:
     TraceLoggerEvent() { payload_ = nullptr; };
 #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);
     ~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; };
     ~TraceLoggerEvent() {}
 #endif
 
     TraceLoggerEventPayload* payload() const {
         MOZ_ASSERT(hasPayload());
@@ -378,19 +376,16 @@ class TraceLoggerThreadState
 
     // These functions map a unique input to a logger ID.
     // This can be used to give start and stop events. Calls to these functions should be
     // limited if possible, because of the overhead.
     // Note: it is not allowed to use them in logTimestamp.
     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
 };
 
 #ifdef JS_TRACE_LOGGING
 void DestroyTraceLoggerThreadState();
 void DestroyTraceLogger(TraceLoggerThread* logger);
--- a/js/src/vm/TraceLoggingTypes.h
+++ b/js/src/vm/TraceLoggingTypes.h
@@ -24,20 +24,25 @@
     _(IonAnalysis)                                    \
     _(IonCompilation)                                 \
     _(IonCompilationPaused)                           \
     _(IonLinking)                                     \
     _(IonMonkey)                                      \
     _(IrregexpCompile)                                \
     _(IrregexpExecute)                                \
     _(MinorGC)                                        \
-    _(ParserCompileFunction)                          \
-    _(ParserCompileLazy)                              \
-    _(ParserCompileScript)                            \
-    _(ParserCompileModule)                            \
+    _(Frontend)                                       \
+    _(FrontendNameAnalysis)                           \
+    _(FrontendTDZAnalysis)                            \
+    _(ParsingFull)                                    \
+    _(ParsingSyntax)                                  \
+    _(Tokenizing)                                     \
+    _(BytecodeEmission)                               \
+    _(BytecodeFoldConstants)                          \
+    _(BytecodeNameFunctions)                          \
     _(DecodeScript)                                   \
     _(DecodeFunction)                                 \
     _(EncodeScript)                                   \
     _(EncodeFunction)                                 \
     _(Scripts)                                        \
     _(VM)                                             \
     _(CompressSource)                                 \
     _(WasmCompilation)                                \