Backed out changeset f7f8b232d111 (bug 1504005) for devtools failures on browser_dbg_rr_breakpoints-01.js.
authorBrindusan Cristian <cbrindusan@mozilla.com>
Wed, 28 Nov 2018 18:04:30 +0200
changeset 507748 937ed33f8229ec736cc467e2d323087edb9b7c6f
parent 507747 1e214baf8fc1908b52fe9d19549cb4e72cfe42b4
child 507749 58482700e9cbb377d02295c36fb9afc442d9b538
push id1905
push userffxbld-merge
push dateMon, 21 Jan 2019 12:33:13 +0000
treeherdermozilla-release@c2fca1944d8c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1504005
milestone65.0a1
backs outf7f8b232d111ba86b0ac3d9c7aa65a7be21f82ea
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out changeset f7f8b232d111 (bug 1504005) for devtools failures on browser_dbg_rr_breakpoints-01.js.
js/moz.configure
js/src/jit/BaselineJIT.cpp
js/src/jit/BaselineJIT.h
js/src/jit/IonBuilder.cpp
js/src/jit/JitSpewer.cpp
js/src/js-config.mozbuild
js/src/moz.build
js/src/util/StructuredSpewer.cpp
js/src/util/StructuredSpewer.h
js/src/util/Text.cpp
js/src/util/Text.h
js/src/vm/JSContext.cpp
js/src/vm/JSContext.h
js/src/vm/JSONPrinter.cpp
js/src/vm/JSONPrinter.h
js/src/vm/JSScript.cpp
js/src/vm/JSScript.h
js/src/vm/TraceLogging.cpp
js/src/vm/TypeInference.cpp
js/src/vm/TypeInference.h
--- a/js/moz.configure
+++ b/js/moz.configure
@@ -365,21 +365,16 @@ js_option('--enable-jitspew',
           help='{Enable|Disable} the Jit spew and IONFLAGS environment '
                'variable')
 
 set_define('JS_JITSPEW',
            depends_if('--enable-jitspew')(lambda _: True))
 set_config('JS_JITSPEW',
            depends_if('--enable-jitspew')(lambda _: True))
 
-# Also enable the structured spewer
-set_define('JS_STRUCTURED_SPEW',
-           depends_if('--enable-jitspew')(lambda _: True))
-set_config('JS_STRUCTURED_SPEW',
-           depends_if('--enable-jitspew')(lambda _: True))
 # When enabled, masm will generate assumeUnreachable calls that act as
 # assertions in the generated code. This option is worth disabling when you
 # have to track mutated values through the generated code, to avoid constantly
 # dumping registers on and off the stack.
 js_option('--enable-masm-verbose',
           default=depends(when=moz_debug)(lambda: True),
           help='{Enable|Disable} MacroAssembler verbosity of generated code.')
 set_define('JS_MASM_VERBOSE',
--- a/js/src/jit/BaselineJIT.cpp
+++ b/js/src/jit/BaselineJIT.cpp
@@ -12,17 +12,16 @@
 
 #include "gc/FreeOp.h"
 #include "jit/BaselineCompiler.h"
 #include "jit/BaselineIC.h"
 #include "jit/CompileInfo.h"
 #include "jit/IonControlFlow.h"
 #include "jit/JitCommon.h"
 #include "jit/JitSpewer.h"
-#include "util/StructuredSpewer.h"
 #include "vm/Debugger.h"
 #include "vm/Interpreter.h"
 #include "vm/TraceLogging.h"
 #include "wasm/WasmInstance.h"
 
 #include "gc/PrivateIterators-inl.h"
 #include "jit/JitFrames-inl.h"
 #include "jit/MacroAssembler-inl.h"
@@ -1158,17 +1157,17 @@ BaselineScript::purgeOptimizedStubs(Zone
         while (stub->next()) {
             MOZ_ASSERT(stub->allocatedInFallbackSpace());
             stub = stub->next();
         }
     }
 #endif
 }
 
-#ifdef JS_STRUCTURED_SPEW
+#ifdef JS_JITSPEW
 static bool
 GetStubEnteredCount(ICStub* stub, uint32_t* count)
 {
     switch (stub->kind()) {
       case ICStub::CacheIR_Regular:
         *count = stub->toCacheIR_Regular()->enteredCount();
         return true;
       case ICStub::CacheIR_Updated:
@@ -1177,76 +1176,58 @@ GetStubEnteredCount(ICStub* stub, uint32
       case ICStub::CacheIR_Monitored:
         *count = stub->toCacheIR_Monitored()->enteredCount();
         return true;
       default:
         return false;
     }
 }
 
-bool
-HasEnteredCounters(ICEntry& entry)
-{
-    ICStub* stub = entry.firstStub();
-    while (stub && !stub->isFallback()) {
-        uint32_t count;
-        if (GetStubEnteredCount(stub, &count)) {
-            return true;
-        }
-        stub = stub->next();
-    }
-    return false;
-}
-
 void
 jit::JitSpewBaselineICStats(JSScript* script, const char* dumpReason)
 {
     MOZ_ASSERT(script->hasBaselineScript());
     BaselineScript* blScript = script->baselineScript();
-    JSContext* cx = TlsContext.get();
-    AutoStructuredSpewer spew(cx, SpewChannel::BaselineICStats, script);
-    if (!spew) {
+
+    if (!JitSpewEnabled(JitSpew_BaselineIC_Statistics)) {
         return;
     }
-    spew->property("reason", dumpReason);
-    spew->beginListProperty("entries");
+
+    Fprinter& out = JitSpewPrinter();
+
+    out.printf("[BaselineICStats] Dumping IC info for %s script %s:%d:%d\n",
+                dumpReason, script->filename(), script->lineno(),
+                script->column());
+
     for (size_t i = 0; i < blScript->numICEntries(); i++) {
         ICEntry& entry = blScript->icEntry(i);
-        if (!HasEnteredCounters(entry)) {
-            continue;
-        }
 
         uint32_t pcOffset = entry.pcOffset();
         jsbytecode* pc = entry.pc(script);
 
         unsigned column;
         unsigned int line = PCToLineNumber(script, pc, &column);
+        out.printf("[BaselineICStats]     %s - pc=%u line=%u col=%u\n",
+                   CodeName[*pc], pcOffset, line, column);
 
-        spew->beginObject();
-        spew->property("op", CodeName[*pc]);
-        spew->property("pc", pcOffset);
-        spew->property("line", line);
-        spew->property("column", column);
-
-        spew->beginListProperty("counts");
         ICStub* stub = entry.firstStub();
-        while (stub && !stub->isFallback()) {
+        out.printf("[BaselineICStats]          ");
+        while (stub) {
             uint32_t count;
             if (GetStubEnteredCount(stub, &count)) {
-                spew->value(count);
+                out.printf("%u -> ", count);
+            } else if (stub->isFallback()) {
+                out.printf("(fb) %u", stub->toFallbackStub()->enteredCount());
             } else {
-                spew->value("?");
+                out.printf(" ?? -> ");
             }
             stub = stub->next();
         }
-        spew->endList();
-        spew->property("fallback_count", entry.fallbackStub()->enteredCount());
-        spew->endObject();
+        out.printf("\n");
     }
-    spew->endList();
 }
 #endif
 
 
 void
 jit::FinishDiscardBaselineScript(FreeOp* fop, JSScript* script)
 {
     if (!script->hasBaselineScript()) {
--- a/js/src/jit/BaselineJIT.h
+++ b/js/src/jit/BaselineJIT.h
@@ -761,17 +761,17 @@ BailoutIonToBaseline(JSContext* cx, JitA
 // Mark baseline scripts on the stack as active, so that they are not discarded
 // during GC.
 void
 MarkActiveBaselineScripts(Zone* zone);
 
 MethodStatus
 BaselineCompile(JSContext* cx, JSScript* script, bool forceDebugInstrumentation = false);
 
-#ifdef JS_STRUCTURED_SPEW
+#ifdef JS_JITSPEW
 void
 JitSpewBaselineICStats(JSScript* script, const char* dumpReason);
 #endif
 
 static const unsigned BASELINE_MAX_ARGS_LENGTH = 20000;
 
 } // namespace jit
 } // namespace js
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -777,17 +777,17 @@ IonBuilder::init()
     return Ok();
 }
 
 AbortReasonOr<Ok>
 IonBuilder::build()
 {
     // Spew IC info for inlined script, but only when actually compiling,
     // not when analyzing it.
-#ifdef JS_STRUCTURED_SPEW
+#ifdef JS_JITSPEW
     if (!info().isAnalysis()) {
         JitSpewBaselineICStats(script(), "To-Be-Compiled");
     }
 #endif
 
     MOZ_TRY(init());
 
     if (script()->hasBaselineScript()) {
@@ -978,17 +978,17 @@ IonBuilder::processIterators()
 AbortReasonOr<Ok>
 IonBuilder::buildInline(IonBuilder* callerBuilder, MResumePoint* callerResumePoint,
                         CallInfo& callInfo)
 {
     inlineCallInfo_ = &callInfo;
 
     // Spew IC info for inlined script, but only when actually compiling,
     // not when analyzing it.
-#ifdef JS_STRUCTURED_SPEW
+#ifdef JS_JITSPEW
     if (!info().isAnalysis()) {
         JitSpewBaselineICStats(script(), "To-Be-Inlined");
     }
 #endif
 
     MOZ_TRY(init());
 
     JitSpew(JitSpew_IonScripts, "Inlining script %s:%u:%u (%p)",
--- a/js/src/jit/JitSpewer.cpp
+++ b/js/src/jit/JitSpewer.cpp
@@ -17,17 +17,16 @@
 #else
 #include <unistd.h>
 #endif
 #include "jit/Ion.h"
 #include "jit/MIR.h"
 #include "jit/MIRGenerator.h"
 #include "jit/MIRGraph.h"
 #include "threading/LockGuard.h"
-#include "util/Text.h"
 #include "vm/HelperThreads.h"
 #include "vm/MutexIDs.h"
 
 #include "vm/Realm-inl.h"
 
 #ifndef JIT_SPEW_DIR
 # if defined(_WIN32)
 #  define JIT_SPEW_DIR "."
@@ -368,16 +367,31 @@ AutoSpewEndFunction::~AutoSpewEndFunctio
 
 Fprinter&
 jit::JitSpewPrinter()
 {
     static Fprinter out;
     return out;
 }
 
+
+static bool
+ContainsFlag(const char* str, const char* flag)
+{
+    size_t flaglen = strlen(flag);
+    const char* index = strstr(str, flag);
+    while (index) {
+        if ((index == str || index[-1] == ',') && (index[flaglen] == 0 || index[flaglen] == ',')) {
+            return true;
+        }
+        index = strstr(index + flaglen, flag);
+    }
+    return false;
+}
+
 void
 jit::CheckLogging()
 {
     if (LoggingChecked) {
         return;
     }
     LoggingChecked = true;
     const char* env = getenv("IONFLAGS");
--- a/js/src/js-config.mozbuild
+++ b/js/src/js-config.mozbuild
@@ -12,21 +12,19 @@ if CONFIG['NIGHTLY_BUILD']:
     DEFINES['ENABLE_WASM_GENERALIZED_TABLES'] = True
     DEFINES['WASM_PRIVATE_REFTYPES'] = True
 
 # Some huge-mapping optimization instead of bounds checks on supported
 # platforms.
 if CONFIG['JS_CODEGEN_X64'] or CONFIG['JS_CODEGEN_ARM64']:
     DEFINES['WASM_HUGE_MEMORY'] = True
 
-# Enables CACHEIR_LOGS to diagnose IC coverage, and
-# Structured spewer for diagnostics
+# Enables CACHEIR_LOGS to diagnose IC coverage.
 if CONFIG['MOZ_DEBUG'] or CONFIG['NIGHTLY_BUILD']:
     DEFINES['JS_CACHEIR_SPEW'] = True
-    DEFINES['JS_STRUCTURED_SPEW'] = True
 
 # CTypes
 if CONFIG['JS_HAS_CTYPES']:
     DEFINES['JS_HAS_CTYPES'] = True
     if not CONFIG['MOZ_SYSTEM_FFI']:
         DEFINES['FFI_BUILDING'] = True
 
 # Forward MOZ_LINKER config
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -235,17 +235,16 @@ UNIFIED_SOURCES += [
     'proxy/Wrapper.cpp',
     'threading/Mutex.cpp',
     'threading/ProtectedData.cpp',
     'util/AllocPolicy.cpp',
     'util/CompleteFile.cpp',
     'util/NativeStack.cpp',
     'util/Printf.cpp',
     'util/StringBuffer.cpp',
-    'util/StructuredSpewer.cpp',
     'util/Text.cpp',
     'util/Unicode.cpp',
     'vm/ArgumentsObject.cpp',
     'vm/ArrayBufferObject.cpp',
     'vm/ArrayBufferViewObject.cpp',
     'vm/AsyncFunction.cpp',
     'vm/AsyncIteration.cpp',
     'vm/BytecodeUtil.cpp',
deleted file mode 100644
--- a/js/src/util/StructuredSpewer.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifdef JS_STRUCTURED_SPEW
-
-#include "util/StructuredSpewer.h"
-
-#include "mozilla/Sprintf.h"
-
-#include "util/Text.h"
-#include "vm/JSContext.h"
-#include "vm/JSScript.h"
-
-using namespace js;
-
-const StructuredSpewer::NameArray StructuredSpewer::names_ =
-{
-#define STRUCTURED_CHANNEL(name) #name,
-    STRUCTURED_CHANNEL_LIST(STRUCTURED_CHANNEL)
-#undef STRUCTURED_CHANNEL
-};
-
-
-// Choose a sensible default spew directory.
-//
-// The preference here is to use the current working directory,
-// except on Android.
-#ifndef DEFAULT_SPEW_DIRECTORY
-# if defined(_WIN32)
-#  define DEFAULT_SPEW_DIRECTORY "."
-# elif defined(__ANDROID__)
-#  define DEFAULT_SPEW_DIRECTORY "/data/local/tmp"
-# else
-#  define DEFAULT_SPEW_DIRECTORY "."
-# endif
-#endif
-
-void
-StructuredSpewer::ensureInitializationAttempted()
-{
-    if (!outputInitializationAttempted_) {
-        char filename[2048] = {0};
-        // For ease of use with Treeherder
-        if (getenv("SPEW_UPLOAD") && getenv("MOZ_UPLOAD_DIR")) {
-            SprintfLiteral(filename, "%s/spew_output", getenv("MOZ_UPLOAD_DIR"));
-        } else if (getenv("SPEW_FILE")) {
-            SprintfLiteral(filename, "%s", getenv("SPEW_FILE"));
-        } else {
-            SprintfLiteral(filename, "%s/spew_output", DEFAULT_SPEW_DIRECTORY);
-        }
-        tryToInitializeOutput(filename);
-
-        // We can't use the intialization state of the Fprinter, as it is not
-        // marked as initialized in a case where we cannot open the output, so
-        // we track the attempt separately.
-        outputInitializationAttempted_ = true;
-    }
-}
-
-
-void
-StructuredSpewer::tryToInitializeOutput(const char* path)
-{
-    static mozilla::Atomic<uint32_t> threadCounter;
-
-    char suffix_path[2048] = {0};
-    SprintfLiteral(suffix_path, "%s.%d.%d", path, getpid(), threadCounter++);
-
-    if (!output_.init(suffix_path)) {
-        // Returning here before we've emplaced the JSONPrinter
-        // means this is effectively disabled, but fail earlier
-        // we also disable all the bits
-        selectedChannels_.disableAll();
-        return;
-    }
-
-    // These logs are structured as a JSON array.
-    output_.put("[");
-    json_.emplace(output_);
-    return;
-}
-
-
-// Treat pattern like a glob, and return true if pattern exists
-// in the script's name or filename or line number.
-//
-// This is the most basic matching I can imagine
-static bool
-MatchJSScript(JSScript* script, const char* pattern)
-{
-    if (!pattern) {
-        return false;
-    }
-
-    char signature[2048] = {0};
-    SprintfLiteral(signature, "%s:%d:%d", script->filename(),
-                                          script->lineno(),
-                                          script->column());
-
-    // Trivial containment match.
-    char* result = strstr(signature, pattern);
-
-    return result != nullptr;
-}
-
-/* static */ bool
-StructuredSpewer::enabled(JSScript* script)
-{
-    static const char* pattern = getenv("SPEW_FILTER");
-    if (!pattern || MatchJSScript(script, pattern)) {
-        return true;
-    }
-    return false;
-}
-
-bool
-StructuredSpewer::enabled(JSContext* cx, const JSScript* script, SpewChannel channel) const
-{
-    return script->spewEnabled() && cx->spewer().filter().enabled(channel);
-}
-
-// Attempt to setup a common header for objects based on script/channel.
-//
-// Returns true if the spewer is prepared for more input
-void
-StructuredSpewer::startObject(JSContext* cx, const JSScript* script, SpewChannel channel)
-{
-    MOZ_ASSERT(json_.isSome());
-
-    JSONPrinter& json = json_.ref();
-
-    json.beginObject();
-    json.property("channel", getName(channel));
-    json.beginObjectProperty("location");
-    {
-        json.property("filename", script->filename());
-        json.property("line", script->lineno());
-        json.property("column", script->column());
-    }
-    json.endObject();
-}
-
-/* static */ void
-StructuredSpewer::spew(JSContext* cx, SpewChannel channel, const char* fmt, ...)
-{
-    // Because we don't have a script here, use the singleton's
-    // filter to determine if the channel is active.
-    if (!cx->spewer().filter().enabled(channel)) {
-        return;
-    }
-
-    cx->spewer().ensureInitializationAttempted();
-
-    va_list ap;
-    va_start(ap, fmt);
-
-    MOZ_ASSERT(cx->spewer().json_.isSome());
-
-    JSONPrinter& json = cx->spewer().json_.ref();
-
-    json.beginObject();
-    json.property("channel", getName(channel));
-    json.formatProperty("message", fmt, ap);
-    json.endObject();
-
-    va_end(ap);
-}
-
-// Currently uses the exact spew flag representation as text.
-void
-StructuredSpewer::parseSpewFlags(const char* flags) {
-    // If '*' or 'all' are in the list, enable all spew.
-    bool star = ContainsFlag(flags, "*") || ContainsFlag(flags, "all");
-#define CHECK_CHANNEL(name) \
-    if (ContainsFlag(flags, #name) || star) { \
-        selectedChannels_.enableChannel(SpewChannel:: name); \
-    }
-
-    STRUCTURED_CHANNEL_LIST(CHECK_CHANNEL)
-
-#undef CHECK_CHANNEL
-
-}
-
-AutoStructuredSpewer::AutoStructuredSpewer(JSContext* cx,
-                                           SpewChannel channel,
-                                           JSScript* script)
-  : printer_(mozilla::Nothing())
-{
-    if (!cx->spewer().enabled(cx, script, channel)) {
-        return;
-    }
-
-    cx->spewer().ensureInitializationAttempted();
-
-    cx->spewer().startObject(cx, script, channel);
-    printer_.emplace(&cx->spewer().json_.ref());
-}
-
-#endif
\ No newline at end of file
deleted file mode 100644
--- a/js/src/util/StructuredSpewer.h
+++ /dev/null
@@ -1,251 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef jit_StructuredSpewer_h
-#define jit_StructuredSpewer_h
-
-#ifdef JS_STRUCTURED_SPEW
-
-#include "mozilla/Atomics.h"
-#include "mozilla/Attributes.h"
-#include "mozilla/EnumeratedArray.h"
-#include "mozilla/EnumSet.h"
-#include "mozilla/Maybe.h"
-#include "mozilla/Sprintf.h"
-
-#include "vm/JSONPrinter.h"
-#include "vm/Printer.h"
-
-#ifdef XP_WIN
-#include <process.h>
-#define getpid _getpid
-#else
-#include <unistd.h>
-#endif
-
-// [SMDOC] JSON Structured Spewer
-//
-// This spewer design has two goals:
-//
-//   1. Provide a spew mechanism that has first-class support for slicing and
-//      dicing output. This means that filtering by script and channel should be
-//      the dominant output mechanism.
-//   2. Provide a simple powerful mechanism for getting information out of the
-//      compiler and into tools. I'm inspired by tools like CacheIR analyzer,
-//      IR Hydra, and the upcoming tracelogger integration into perf.html.
-//
-// The spewer has four main control knobs, all currently set as
-// environment variables. All but the first are optional.
-//
-//   SPEW: Activates the spewer. The value provided is interpreted as a comma
-//         separated list that selects channels by name. Currently there's no
-//         mapping between internal and external names, so the channel names
-//         are exactly those described in STRUCTURED_CHANNEL_LIST below.
-//
-//   SPEW_FILE: Selects the file to write to. An absolute path.
-//
-//   SPEW_FILTER: A string which is matched against 'signature' constructed or a
-//        JSScript, currently connsisting of filename:line:col.
-//
-//        Matching in this version is merely finding the string in
-//        in question in the 'signature'
-//
-//   SPEW_UPLOAD: If this variable is set as well as MOZ_UPLOAD_DIR, output goes
-//        to $MOZ_UPLOAD_DIR/spew_output* to ease usage with Treeherder.
-//
-// Other notes:
-// - Thread safety is provided by opening a new spewer file for every thread.
-// - Each file is prefixed with the PID to handle multiple processes.
-// - Files are opened lazily, just before the first write to them.
-
-class JSScript;
-
-namespace js {
-
-#define STRUCTURED_CHANNEL_LIST(_) \
-    _(BaselineICStats)
-
-// Structured spew channels
-enum class SpewChannel {
-#define STRUCTURED_CHANNEL(name) name,
-    STRUCTURED_CHANNEL_LIST(STRUCTURED_CHANNEL)
-#undef STRUCTURED_CHANNEL
-    Count
-};
-
-// A filter is used to select what channels are enabled
-//
-// To save memory, JSScripts do not have their own filters, but instead have
-// a single bit which tracks if that script has opted into spewing. 
-class StructuredSpewFilter
-{
-    // Packed set of bits indicating what spew channels
-    // are enabled.
-    mozilla::EnumSet<SpewChannel> bits_;
-
-  public:
-    // Default construct to all bits disabled.
-    StructuredSpewFilter()
-      : bits_()
-    {}
-
-    // Return true iff spew is enabled for this channel for
-    // the script this was created for.
-    bool enabled(SpewChannel x) const {
-        return bits_.contains(x);
-    }
-
-    void enableChannel(SpewChannel x) {
-        bits_ += x;
-    }
-
-    void disableAll() {
-        bits_.clear();
-    }
-
-};
-
-class StructuredSpewer
-{
-  public:
-    StructuredSpewer()
-      : outputInitializationAttempted_(false),
-        json_(mozilla::Nothing()),
-        selectedChannels_()
-    {
-        if (getenv("SPEW")) {
-            parseSpewFlags(getenv("SPEW"));
-        }
-    }
-
-    ~StructuredSpewer() {
-        if (json_.isSome()) {
-            json_->endList();
-            output_.flush();
-            output_.finish();
-        }
-    }
-
-    // Check if the spewer is enabled for a particular script, used to power
-    // script level filtering.
-    static bool enabled(JSScript* script);
-
-    // A generic printf like spewer that logs the formatted string.
-    static void spew(JSContext* cx, SpewChannel channel, const char* fmt, ...) MOZ_FORMAT_PRINTF(3,4);
-
-  private:
-    // In order to support lazy initialization, and simultaneously support a
-    // failure to open a log file being non-fatal (as lazily reporting failure
-    // would be hard, we have an akward set of states to represent.
-    //
-    // We need to handle:
-    // - Output file not initialized, and not yet attempted
-    // - Output file not intialized, attempted, and failed.
-    // - Output file initialized, JSON writer ready for input.
-    //
-    // Because Fprinter doesn't record whether or not its initialization was
-    // attempted, we keep track of that here.
-    //
-    // The contract we require is that ensureInitializationAttempted() be called
-    // just before any attempte to write. This will ensure the file open is
-    // attemped in the right place.
-    bool outputInitializationAttempted_;
-    Fprinter output_;
-    mozilla::Maybe<JSONPrinter> json_;
-
-    // Globally selected channels.
-    StructuredSpewFilter selectedChannels_;
-
-    using NameArray = mozilla::EnumeratedArray<SpewChannel,
-                                               SpewChannel::Count,
-                                               const char*>;
-    // Channel Names
-    static NameArray const names_;
-
-    // Return the global filter.
-    StructuredSpewFilter& filter() {
-        return selectedChannels_;
-    }
-
-    // Get channel name
-    static const char* getName(SpewChannel channel) {
-        return names_[channel];
-    }
-
-    // Call just before writes to the output are expected.
-    //
-    // Avoids opening files that will remain empty.
-    void ensureInitializationAttempted();
-
-    void tryToInitializeOutput(const char* path);
-
-    // Using flags, choose the enabled channels for this spewer.
-    void parseSpewFlags(const char* flags);
-
-    // Returns true iff the channels is enabled for the given script.
-    bool enabled(JSContext* cx, const JSScript* script, SpewChannel channel) const;
-
-    // Start a record
-    void startObject(JSContext* cx, const JSScript* script, SpewChannel channel);
-
-    friend class AutoStructuredSpewer;
-};
-
-// An RAII class for accessing the structured spewer.
-//
-// This class prefixes the spew with channel and location information.
-//
-// Before writing with this Spewer, it must be checked: ie.
-//
-//     {
-//       AutoSpew x(...);
-//       if (x) {
-//          x->property("lalala", y);
-//       }
-//     }
-//
-// As the selected channel may not be enabled.
-//
-// Note: If the lifespan of two AutoSpewers overlap, then the output
-//  may not be well defined JSON. These spewers should be given as
-//  short a lifespan as possible.
-//
-//  As well, this class cannot be copied or assigned to ensure the
-//  correct number of destructors fire.
-class MOZ_RAII AutoStructuredSpewer {
-    mozilla::Maybe<JSONPrinter*> printer_;
-    AutoStructuredSpewer(const AutoStructuredSpewer&) = delete;
-    void operator=(AutoStructuredSpewer&) = delete;
-  public:
-
-    explicit AutoStructuredSpewer(JSContext* cx, SpewChannel channel, JSScript* script);
-
-    ~AutoStructuredSpewer() {
-        if (printer_.isSome()) {
-            printer_.ref()->endObject();
-        }
-    }
-
-    explicit operator bool() const {
-        return printer_.isSome();
-    }
-
-    JSONPrinter* operator->() {
-        MOZ_ASSERT(printer_.isSome());
-        return printer_.ref();
-    }
-
-    JSONPrinter& operator*() {
-        MOZ_ASSERT(printer_.isSome());
-        return *printer_.ref();
-    }
-
-};
-
-} // namespace js
-
-#endif
-#endif /* jit_StructuredSpewer_h */
\ No newline at end of file
--- a/js/src/util/Text.cpp
+++ b/js/src/util/Text.cpp
@@ -283,30 +283,16 @@ js::PutEscapedStringImpl(char* buffer, s
     }
   stop:
     if (buffer) {
         buffer[n] = '\0';
     }
     return n;
 }
 
-bool
-js::ContainsFlag(const char* str, const char* flag)
-{
-    size_t flaglen = strlen(flag);
-    const char* index = strstr(str, flag);
-    while (index) {
-        if ((index == str || index[-1] == ',') && (index[flaglen] == 0 || index[flaglen] == ',')) {
-            return true;
-        }
-        index = strstr(index + flaglen, flag);
-    }
-    return false;
-}
-
 template size_t
 js::PutEscapedStringImpl(char* buffer, size_t bufferSize, GenericPrinter* out, const Latin1Char* chars,
                          size_t length, uint32_t quote);
 
 template size_t
 js::PutEscapedStringImpl(char* buffer, size_t bufferSize, GenericPrinter* out, const char* chars,
                          size_t length, uint32_t quote);
 
--- a/js/src/util/Text.h
+++ b/js/src/util/Text.h
@@ -221,15 +221,11 @@ FileEscapedString(FILE* fp, const char* 
     bool res = EscapedStringPrinter(out, chars, length, quote);
     out.finish();
     return res;
 }
 
 JSString*
 EncodeURI(JSContext* cx, const char* chars, size_t length);
 
-// Return true if input string contains a given flag in a comma separated list.
-bool
-ContainsFlag(const char* str, const char* flag);
-
 } // namespace js
 
 #endif // util_Text_h
--- a/js/src/vm/JSContext.cpp
+++ b/js/src/vm/JSContext.cpp
@@ -1370,19 +1370,16 @@ JSContext::JSContext(JSRuntime* runtime,
     enqueuePromiseJobCallback(nullptr),
     enqueuePromiseJobCallbackData(nullptr),
     jobQueue(nullptr),
     drainingJobQueue(false),
     stopDrainingJobQueue(false),
     canSkipEnqueuingJobs(false),
     promiseRejectionTrackerCallback(nullptr),
     promiseRejectionTrackerCallbackData(nullptr)
-#ifdef JS_STRUCTURED_SPEW
-    , structuredSpewer_()
-#endif
 {
     MOZ_ASSERT(static_cast<JS::RootingContext*>(this) ==
                JS::RootingContext::get(this));
 
     MOZ_ASSERT(!TlsContext.get());
     TlsContext.set(this);
 
     for (size_t i = 0; i < mozilla::ArrayLength(nativeStackQuota); i++) {
--- a/js/src/vm/JSContext.h
+++ b/js/src/vm/JSContext.h
@@ -13,17 +13,16 @@
 
 #include "ds/TraceableFifo.h"
 #include "js/CharacterEncoding.h"
 #include "js/GCVector.h"
 #include "js/Result.h"
 #include "js/Utility.h"
 #include "js/Vector.h"
 #include "threading/ProtectedData.h"
-#include "util/StructuredSpewer.h"
 #include "vm/ErrorReporting.h"
 #include "vm/MallocProvider.h"
 #include "vm/Runtime.h"
 
 struct DtoaState;
 
 namespace js {
 
@@ -955,25 +954,16 @@ struct JSContext : public JS::RootingCon
     }
 
   public:
     // Assert the arguments are in this context's realm (for scripts),
     // compartment (for objects) or zone (for strings, symbols).
     template <class... Args> inline void check(const Args&... args);
     template <class... Args> inline void releaseCheck(const Args&... args);
     template <class... Args> MOZ_ALWAYS_INLINE void debugOnlyCheck(const Args&... args);
-
-#ifdef JS_STRUCTURED_SPEW
-  private:
-    // Spewer for this thread
-    js::ThreadData<js::StructuredSpewer> structuredSpewer_;
-  public:
-    js::StructuredSpewer& spewer() { return structuredSpewer_.ref(); }
-#endif
-
 }; /* struct JSContext */
 
 inline JS::Result<>
 JSContext::boolToResult(bool ok)
 {
     if (MOZ_LIKELY(ok)) {
         MOZ_ASSERT(!isExceptionPending());
         MOZ_ASSERT(!isPropagatingForcedReturn());
--- a/js/src/vm/JSONPrinter.cpp
+++ b/js/src/vm/JSONPrinter.cpp
@@ -115,24 +115,16 @@ JSONPrinter::formatProperty(const char* 
     beginStringProperty(name);
     out_.vprintf(format, ap);
     endStringProperty();
 
     va_end(ap);
 }
 
 void
-JSONPrinter::formatProperty(const char* name, const char* format, va_list ap)
-{
-    beginStringProperty(name);
-    out_.vprintf(format, ap);
-    endStringProperty();
-}
-
-void
 JSONPrinter::value(const char* format, ...)
 {
     va_list ap;
     va_start(ap, format);
 
     if (!first_) {
         out_.putChar(',');
     }
--- a/js/src/vm/JSONPrinter.h
+++ b/js/src/vm/JSONPrinter.h
@@ -57,17 +57,16 @@ class JSONPrinter
 #if defined(XP_DARWIN) || defined(__OpenBSD__)
     // On OSX and OpenBSD, size_t is long unsigned, uint32_t is unsigned, and
     // uint64_t is long long unsigned. Everywhere else, size_t matches either
     // uint32_t or uint64_t.
     void property(const char* name, size_t value);
 #endif
 
     void formatProperty(const char* name, const char* format, ...) MOZ_FORMAT_PRINTF(3, 4);
-    void formatProperty(const char* name, const char* format, va_list ap);
 
     // JSON requires decimals to be separated by periods, but the LC_NUMERIC
     // setting may cause printf to use commas in some locales.
     enum TimePrecision { SECONDS, MILLISECONDS, MICROSECONDS };
     void property(const char* name, const mozilla::TimeDuration& dur, TimePrecision precision);
 
     void floatProperty(const char* name, double value, size_t precision);
 
--- a/js/src/vm/JSScript.cpp
+++ b/js/src/vm/JSScript.cpp
@@ -3512,21 +3512,16 @@ JSScript::fullyInitFromEmitter(JSContext
     // JSFunction::hasUncompletedScript relies on the fact that the existence
     // of the pointer to JSScript means the pointed JSScript is complete.
     if (bce->sc->isFunctionBox()) {
         initFromFunctionBox(script, bce->sc->asFunctionBox());
     } else if (bce->sc->isModuleContext()) {
         initFromModuleContext(script);
     }
 
-#ifdef JS_STRUCTURED_SPEW
-    // We want this to happen after line number initialization to allow filtering to work.
-    script->setSpewEnabled(StructuredSpewer::enabled(script));
-#endif
-
 #ifdef DEBUG
     script->assertValidJumpTargets();
 #endif
 
     return true;
 }
 
 #ifdef DEBUG
--- a/js/src/vm/JSScript.h
+++ b/js/src/vm/JSScript.h
@@ -28,17 +28,16 @@
 #include "frontend/NameAnalysisTypes.h"
 #include "gc/Barrier.h"
 #include "gc/Rooting.h"
 #include "jit/IonCode.h"
 #include "js/CompileOptions.h"
 #include "js/UbiNode.h"
 #include "js/UniquePtr.h"
 #include "js/Utility.h"
-#include "util/StructuredSpewer.h"
 #include "vm/BytecodeIterator.h"
 #include "vm/BytecodeLocation.h"
 #include "vm/BytecodeUtil.h"
 #include "vm/JSAtom.h"
 #include "vm/NativeObject.h"
 #include "vm/Scope.h"
 #include "vm/Shape.h"
 #include "vm/SharedImmutableStringsCache.h"
@@ -1772,19 +1771,16 @@ class JSScript : public js::gc::TenuredC
         FailedLexicalCheck = 1 << 16,
 
         // See comments below.
         NeedsArgsAnalysis = 1 << 17,
         NeedsArgsObj = 1 << 18,
 
         // Set if the debugger's onNewScript hook has not yet been called.
         HideScriptFromDebugger = 1 << 19,
-
-        // Set if the script has opted into spew
-        SpewEnabled = 1 << 20,
     };
   private:
     // Note: don't make this a bitfield! It makes it hard to read these flags
     // from JIT code.
     uint32_t mutableFlags_ = 0;
 
     // 16-bit fields.
 
@@ -2187,23 +2183,16 @@ class JSScript : public js::gc::TenuredC
 
     bool hideScriptFromDebugger() const {
         return hasFlag(MutableFlags::HideScriptFromDebugger);
     }
     void clearHideScriptFromDebugger() {
         clearFlag(MutableFlags::HideScriptFromDebugger);
     }
 
-    bool spewEnabled() const {
-        return hasFlag(MutableFlags::SpewEnabled);
-    }
-    void setSpewEnabled(bool enabled) {
-        setFlag(MutableFlags::SpewEnabled, enabled);
-    }
-
     bool needsHomeObject() const {
         return hasFlag(ImmutableFlags::NeedsHomeObject);
     }
 
     bool isDerivedClassConstructor() const {
         return hasFlag(ImmutableFlags::IsDerivedClassConstructor);
     }
 
--- a/js/src/vm/TraceLogging.cpp
+++ b/js/src/vm/TraceLogging.cpp
@@ -818,16 +818,30 @@ TraceLoggerThreadState::~TraceLoggerThre
         js_delete(r.front().value());
     }
 
 #ifdef DEBUG
     initialized = false;
 #endif
 }
 
+static bool
+ContainsFlag(const char* str, const char* flag)
+{
+    size_t flaglen = strlen(flag);
+    const char* index = strstr(str, flag);
+    while (index) {
+        if ((index == str || index[-1] == ',') && (index[flaglen] == 0 || index[flaglen] == ',')) {
+            return true;
+        }
+        index = strstr(index + flaglen, flag);
+    }
+    return false;
+}
+
 bool
 TraceLoggerThreadState::init()
 {
     const char* env = getenv("TLLOG");
     if (env) {
         if (strstr(env, "help")) {
             fflush(nullptr);
             printf(
--- a/js/src/vm/TypeInference.cpp
+++ b/js/src/vm/TypeInference.cpp
@@ -166,17 +166,17 @@ TypeSet::TypeString(const TypeSet::Type 
 TypeSet::ObjectGroupString(const ObjectGroup* group)
 {
     return TypeString(TypeSet::ObjectType(group));
 }
 
 #ifdef DEBUG
 
 bool
-js::InferSpewActive(TypeSpewChannel channel)
+js::InferSpewActive(SpewChannel channel)
 {
     static bool active[SPEW_COUNT];
     static bool checked = false;
     if (!checked) {
         checked = true;
         PodArrayZero(active);
         if (mozilla::recordreplay::IsRecordingOrReplaying()) {
             return false;
--- a/js/src/vm/TypeInference.h
+++ b/js/src/vm/TypeInference.h
@@ -430,25 +430,25 @@ class TypeZone
     mozilla::Maybe<IonCompilationId> currentCompilationId() const {
         return currentCompilationId_.ref();
     }
     mozilla::Maybe<IonCompilationId>& currentCompilationIdRef() {
         return currentCompilationId_.ref();
     }
 };
 
-enum TypeSpewChannel {
+enum SpewChannel {
     ISpewOps,      /* ops: New constraints and types. */
     ISpewResult,   /* result: Final type sets. */
     SPEW_COUNT
 };
 
 #ifdef DEBUG
 
-bool InferSpewActive(TypeSpewChannel channel);
+bool InferSpewActive(SpewChannel channel);
 const char * InferSpewColorReset();
 const char * InferSpewColor(TypeConstraint* constraint);
 const char * InferSpewColor(TypeSet* types);
 
 #define InferSpew(channel, ...) if (InferSpewActive(channel)) { InferSpewImpl(__VA_ARGS__); } else {}
 void InferSpewImpl(const char* fmt, ...) MOZ_FORMAT_PRINTF(1, 2);
 
 /* Check that the type property for id in group contains value. */