Bug 1594961 - Split FrameIter-related functionality out of vm/Stack.h to vm/FrameIter.h, Activation-related functionality to vm/Activation.h, and JitActivation functionality to vm/JitActivation.h. r=jandem CLOSED TREE
authorJeff Walden <jwalden@mit.edu>
Fri, 08 Nov 2019 23:27:36 +0100
changeset 501360 caf55914ccddba34d462a1206530d7868b6c4992
parent 501359 98da6aa7a8a53528d2efc94e77b8024dd1646fd0
child 501361 641fe2e15d6f1e046f4064af76d1b7c701baa469
child 501366 3d2bf6bfe93154fa81e73c8bb6f7fa49db8887a3
push id114168
push userdluca@mozilla.com
push dateSun, 10 Nov 2019 03:08:55 +0000
treeherdermozilla-inbound@33f64c1ef3e4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1594961
milestone72.0a1
first release with
nightly linux32
caf55914ccdd / 72.0a1 / 20191109093718 / files
nightly linux64
caf55914ccdd / 72.0a1 / 20191109093718 / files
nightly mac
caf55914ccdd / 72.0a1 / 20191109093718 / files
nightly win32
caf55914ccdd / 72.0a1 / 20191109093718 / files
nightly win64
caf55914ccdd / 72.0a1 / 20191109093718 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1594961 - Split FrameIter-related functionality out of vm/Stack.h to vm/FrameIter.h, Activation-related functionality to vm/Activation.h, and JitActivation functionality to vm/JitActivation.h. r=jandem CLOSED TREE Differential Revision: https://phabricator.services.mozilla.com/D52315
js/src/debugger/Frame.h
js/src/frontend/TokenStream.cpp
js/src/jit/Bailouts.h
js/src/jit/JitFrames.h
js/src/jit/JitScript.cpp
js/src/jit/RematerializedFrame-inl.h
js/src/jit/RematerializedFrame.h
js/src/jit/arm/MacroAssembler-arm.cpp
js/src/jit/arm/Trampoline-arm.cpp
js/src/jit/arm64/MacroAssembler-arm64.cpp
js/src/jit/arm64/Trampoline-arm64.cpp
js/src/jit/mips32/MacroAssembler-mips32.cpp
js/src/jit/mips32/Trampoline-mips32.cpp
js/src/jit/mips64/MacroAssembler-mips64.cpp
js/src/jit/mips64/Trampoline-mips64.cpp
js/src/jit/x64/MacroAssembler-x64.cpp
js/src/jit/x64/Trampoline-x64.cpp
js/src/jit/x86/MacroAssembler-x86.cpp
js/src/jit/x86/Trampoline-x86.cpp
js/src/jsexn.cpp
js/src/jsfriendapi.cpp
js/src/moz.build
js/src/vm/Activation-inl.h
js/src/vm/Activation.cpp
js/src/vm/Activation.h
js/src/vm/ArgumentsObject.cpp
js/src/vm/BytecodeUtil.cpp
js/src/vm/FrameIter-inl.h
js/src/vm/FrameIter.cpp
js/src/vm/FrameIter.h
js/src/vm/GeckoProfiler.cpp
js/src/vm/JSContext-inl.h
js/src/vm/JSContext.h
js/src/vm/JSFunction.cpp
js/src/vm/JitActivation.cpp
js/src/vm/JitActivation.h
js/src/vm/SelfHosting.cpp
js/src/vm/Stack-inl.h
js/src/vm/Stack.cpp
js/src/vm/Stack.h
js/src/vm/TraceLogging.cpp
js/src/vm/TypeInference.cpp
js/src/wasm/WasmFrameIter.cpp
js/src/wasm/WasmSignalHandlers.cpp
--- a/js/src/debugger/Frame.h
+++ b/js/src/debugger/Frame.h
@@ -16,19 +16,20 @@
 
 #include "jsapi.h"  // for JSContext, CallArgs
 
 #include "NamespaceImports.h"   // for Value, MutableHandleValue, HandleObject
 #include "debugger/DebugAPI.h"  // for ResumeMode
 #include "debugger/Debugger.h"  // for ResumeMode, Handler, Debugger
 #include "gc/Barrier.h"         // for HeapPtr
 #include "gc/Rooting.h"         // for HandleDebuggerFrame, HandleNativeObject
+#include "vm/FrameIter.h"       // for FrameIter
 #include "vm/JSObject.h"        // for JSObject
 #include "vm/NativeObject.h"    // for NativeObject
-#include "vm/Stack.h"           // for FrameIter, AbstractFramePtr
+#include "vm/Stack.h"           // for AbstractFramePtr
 
 namespace js {
 
 class AbstractGeneratorObject;
 class GlobalObject;
 
 /*
  * An OnStepHandler represents a handler function that is called when a small
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -33,16 +33,17 @@
 #include "frontend/BytecodeCompiler.h"
 #include "frontend/Parser.h"
 #include "frontend/ReservedWords.h"
 #include "js/CharacterEncoding.h"
 #include "js/RegExpFlags.h"  // JS::RegExpFlags
 #include "js/UniquePtr.h"
 #include "util/StringBuffer.h"
 #include "util/Unicode.h"
+#include "vm/FrameIter.h"  // js::{,NonBuiltin}FrameIter
 #include "vm/HelperThreads.h"
 #include "vm/JSAtom.h"
 #include "vm/JSContext.h"
 #include "vm/Realm.h"
 
 using mozilla::ArrayLength;
 using mozilla::AsciiAlphanumericToNumber;
 using mozilla::AssertedCast;
--- a/js/src/jit/Bailouts.h
+++ b/js/src/jit/Bailouts.h
@@ -2,21 +2,24 @@
  * vim: set ts=8 sts=2 et sw=2 tw=80:
  * 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_Bailouts_h
 #define jit_Bailouts_h
 
+#include <stddef.h>  // size_t
+#include <stdint.h>  // uint8_t, uint32_t
+
 #include "jstypes.h"
 
 #include "jit/JitFrames.h"
 #include "jit/JSJitFrameIter.h"
-#include "vm/Stack.h"
+#include "wasm/WasmFrameIter.h"  // js::wasm::ExitOrJitEntryFPTag
 
 namespace js {
 namespace jit {
 
 // [SMDOC] IonMonkey Bailouts
 //
 // A "bailout" is the process of recovering a baseline frame from an IonFrame.
 // Bailouts are implemented in js::jit::BailoutIonToBaseline, which has the
@@ -137,16 +140,19 @@ static_assert(!(FAKE_EXITFP_FOR_BAILOUT_
               "FAKE_EXITFP_FOR_BAILOUT could be mistaken as a low-bit tagged "
               "wasm exit fp");
 
 // BailoutStack is an architecture specific pointer to the stack, given by the
 // bailout handler.
 class BailoutStack;
 class InvalidationBailoutStack;
 
+class JitActivation;
+class JitActivationIterator;
+
 // Must be implemented by each architecture.
 
 // This structure is constructed before recovering the baseline frames for a
 // bailout. It records all information extracted from the stack, and which are
 // needed for the JSJitFrameIter.
 class BailoutFrameInfo {
   MachineState machine_;
   uint8_t* framePointer_;
--- a/js/src/jit/JitFrames.h
+++ b/js/src/jit/JitFrames.h
@@ -2,17 +2,17 @@
  * vim: set ts=8 sts=2 et sw=2 tw=80:
  * 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_JitFrames_h
 #define jit_JitFrames_h
 
-#include <stdint.h>
+#include <stdint.h>  // uintptr_t
 
 #include "jit/JSJitFrameIter.h"
 #include "vm/JSContext.h"
 #include "vm/JSFunction.h"
 
 namespace js {
 namespace jit {
 
--- a/js/src/jit/JitScript.cpp
+++ b/js/src/jit/JitScript.cpp
@@ -12,16 +12,17 @@
 #include "mozilla/ScopeExit.h"
 
 #include "jit/BaselineIC.h"
 #include "jit/BytecodeAnalysis.h"
 #include "util/Memory.h"
 #include "vm/BytecodeIterator.h"
 #include "vm/BytecodeLocation.h"
 #include "vm/BytecodeUtil.h"
+#include "vm/FrameIter.h"  // js::OnlyJSJitFrameIter
 #include "vm/JSScript.h"
 #include "vm/Stack.h"
 #include "vm/TypeInference.h"
 #include "wasm/WasmInstance.h"
 
 #include "gc/FreeOp-inl.h"
 #include "jit/JSJitFrameIter-inl.h"
 #include "vm/BytecodeIterator-inl.h"
new file mode 100644
--- /dev/null
+++ b/js/src/jit/RematerializedFrame-inl.h
@@ -0,0 +1,23 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: set ts=8 sts=2 et sw=2 tw=80:
+ * 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_RematerializedFrame_inl_h
+#define jit_RematerializedFrame_inl_h
+
+#include "jit/RematerializedFrame.h"
+
+#include "mozilla/Assertions.h"  // MOZ_ASSERT
+
+#include "vm/JSScript.h"  // JSScript
+
+#include "vm/JSScript-inl.h"  // JSScript::isDebuggee
+
+inline void js::jit::RematerializedFrame::unsetIsDebuggee() {
+  MOZ_ASSERT(!script()->isDebuggee());
+  isDebuggee_ = false;
+}
+
+#endif  // jit_RematerializedFrame_inl_h
--- a/js/src/jit/RematerializedFrame.h
+++ b/js/src/jit/RematerializedFrame.h
@@ -90,20 +90,17 @@ class RematerializedFrame {
       MaybeReadFallback& fallback, RematerializedFrameVector& frames);
 
   bool prevUpToDate() const { return prevUpToDate_; }
   void setPrevUpToDate() { prevUpToDate_ = true; }
   void unsetPrevUpToDate() { prevUpToDate_ = false; }
 
   bool isDebuggee() const { return isDebuggee_; }
   void setIsDebuggee() { isDebuggee_ = true; }
-  void unsetIsDebuggee() {
-    MOZ_ASSERT(!script()->isDebuggee());
-    isDebuggee_ = false;
-  }
+  inline void unsetIsDebuggee();
 
   uint8_t* top() const { return top_; }
   JSScript* outerScript() const {
     JitFrameLayout* jsFrame = (JitFrameLayout*)top_;
     return ScriptFromCalleeToken(jsFrame->calleeToken());
   }
   jsbytecode* pc() const { return pc_; }
   size_t frameNo() const { return frameNo_; }
--- a/js/src/jit/arm/MacroAssembler-arm.cpp
+++ b/js/src/jit/arm/MacroAssembler-arm.cpp
@@ -16,16 +16,17 @@
 #include "jit/AtomicOp.h"
 #include "jit/AtomicOperations.h"
 #include "jit/Bailouts.h"
 #include "jit/BaselineFrame.h"
 #include "jit/JitFrames.h"
 #include "jit/MacroAssembler.h"
 #include "jit/MoveEmitter.h"
 #include "util/Memory.h"
+#include "vm/JitActivation.h"  // js::jit::JitActivation
 
 #include "jit/MacroAssembler-inl.h"
 
 using namespace js;
 using namespace jit;
 
 using mozilla::Abs;
 using mozilla::BitwiseCast;
--- a/js/src/jit/arm/Trampoline-arm.cpp
+++ b/js/src/jit/arm/Trampoline-arm.cpp
@@ -9,16 +9,17 @@
 #include "jit/JitFrames.h"
 #include "jit/JitRealm.h"
 #include "jit/JitSpewer.h"
 #include "jit/Linker.h"
 #ifdef JS_ION_PERF
 #  include "jit/PerfSpewer.h"
 #endif
 #include "jit/VMFunctions.h"
+#include "vm/JitActivation.h"  // js::jit::JitActivation
 #include "vm/Realm.h"
 
 #include "jit/MacroAssembler-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
 static const FloatRegisterSet NonVolatileFloatRegs = FloatRegisterSet(
--- a/js/src/jit/arm64/MacroAssembler-arm64.cpp
+++ b/js/src/jit/arm64/MacroAssembler-arm64.cpp
@@ -7,16 +7,17 @@
 #include "jit/arm64/MacroAssembler-arm64.h"
 
 #include "jit/arm64/MoveEmitter-arm64.h"
 #include "jit/arm64/SharedICRegisters-arm64.h"
 #include "jit/Bailouts.h"
 #include "jit/BaselineFrame.h"
 #include "jit/MacroAssembler.h"
 #include "util/Memory.h"
+#include "vm/JitActivation.h"  // js::jit::JitActivation
 
 #include "jit/MacroAssembler-inl.h"
 
 namespace js {
 namespace jit {
 
 void MacroAssembler::clampDoubleToUint8(FloatRegister input, Register output) {
   ARMRegister dest(output, 32);
--- a/js/src/jit/arm64/Trampoline-arm64.cpp
+++ b/js/src/jit/arm64/Trampoline-arm64.cpp
@@ -8,16 +8,17 @@
 #include "jit/JitFrames.h"
 #include "jit/JitRealm.h"
 #include "jit/Linker.h"
 #ifdef JS_ION_PERF
 #  include "jit/PerfSpewer.h"
 #endif
 #include "jit/arm64/SharedICHelpers-arm64.h"
 #include "jit/VMFunctions.h"
+#include "vm/JitActivation.h"  // js::jit::JitActivation
 
 #include "jit/MacroAssembler-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
 /* This method generates a trampoline on ARM64 for a c++ function with
  * the following signature:
--- a/js/src/jit/mips32/MacroAssembler-mips32.cpp
+++ b/js/src/jit/mips32/MacroAssembler-mips32.cpp
@@ -13,16 +13,17 @@
 #include "jit/Bailouts.h"
 #include "jit/BaselineFrame.h"
 #include "jit/JitFrames.h"
 #include "jit/MacroAssembler.h"
 #include "jit/mips32/Simulator-mips32.h"
 #include "jit/MoveEmitter.h"
 #include "jit/SharedICRegisters.h"
 #include "util/Memory.h"
+#include "vm/JitActivation.h"  // js::jit::JitActivation
 
 #include "jit/MacroAssembler-inl.h"
 
 using namespace js;
 using namespace jit;
 
 using mozilla::Abs;
 
--- a/js/src/jit/mips32/Trampoline-mips32.cpp
+++ b/js/src/jit/mips32/Trampoline-mips32.cpp
@@ -12,16 +12,17 @@
 #include "jit/JitSpewer.h"
 #include "jit/Linker.h"
 #include "jit/mips-shared/SharedICHelpers-mips-shared.h"
 #include "jit/mips32/Bailouts-mips32.h"
 #ifdef JS_ION_PERF
 #  include "jit/PerfSpewer.h"
 #endif
 #include "jit/VMFunctions.h"
+#include "vm/JitActivation.h"  // js::jit::JitActivation
 #include "vm/Realm.h"
 
 #include "jit/MacroAssembler-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
 static_assert(sizeof(uintptr_t) == sizeof(uint32_t), "Not 64-bit clean.");
--- a/js/src/jit/mips64/MacroAssembler-mips64.cpp
+++ b/js/src/jit/mips64/MacroAssembler-mips64.cpp
@@ -12,16 +12,17 @@
 #include "jit/Bailouts.h"
 #include "jit/BaselineFrame.h"
 #include "jit/JitFrames.h"
 #include "jit/MacroAssembler.h"
 #include "jit/mips64/Simulator-mips64.h"
 #include "jit/MoveEmitter.h"
 #include "jit/SharedICRegisters.h"
 #include "util/Memory.h"
+#include "vm/JitActivation.h"  // js::jit::JitActivation
 
 #include "jit/MacroAssembler-inl.h"
 
 using namespace js;
 using namespace jit;
 
 using mozilla::Abs;
 
--- a/js/src/jit/mips64/Trampoline-mips64.cpp
+++ b/js/src/jit/mips64/Trampoline-mips64.cpp
@@ -12,16 +12,17 @@
 #include "jit/JitSpewer.h"
 #include "jit/Linker.h"
 #include "jit/mips-shared/SharedICHelpers-mips-shared.h"
 #include "jit/mips64/Bailouts-mips64.h"
 #ifdef JS_ION_PERF
 #  include "jit/PerfSpewer.h"
 #endif
 #include "jit/VMFunctions.h"
+#include "vm/JitActivation.h"  // js::jit::JitActivation
 #include "vm/Realm.h"
 
 #include "jit/MacroAssembler-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
 // All registers to save and restore. This includes the stack pointer, since we
--- a/js/src/jit/x64/MacroAssembler-x64.cpp
+++ b/js/src/jit/x64/MacroAssembler-x64.cpp
@@ -8,16 +8,17 @@
 
 #include "jit/Bailouts.h"
 #include "jit/BaselineFrame.h"
 #include "jit/JitFrames.h"
 #include "jit/JitRealm.h"
 #include "jit/MacroAssembler.h"
 #include "jit/MoveEmitter.h"
 #include "util/Memory.h"
+#include "vm/JitActivation.h"  // js::jit::JitActivation
 
 #include "jit/MacroAssembler-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
 void MacroAssemblerX64::loadConstantDouble(double d, FloatRegister dest) {
   if (maybeInlineDouble(d, dest)) {
--- a/js/src/jit/x64/Trampoline-x64.cpp
+++ b/js/src/jit/x64/Trampoline-x64.cpp
@@ -11,16 +11,17 @@
 #ifdef JS_ION_PERF
 #  include "jit/PerfSpewer.h"
 #endif
 #include "jit/VMFunctions.h"
 #include "jit/x64/SharedICHelpers-x64.h"
 #ifdef MOZ_VTUNE
 #  include "vtune/VTuneWrapper.h"
 #endif
+#include "vm/JitActivation.h"  // js::jit::JitActivation
 
 #include "jit/MacroAssembler-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
 using mozilla::IsPowerOfTwo;
 
--- a/js/src/jit/x86/MacroAssembler-x86.cpp
+++ b/js/src/jit/x86/MacroAssembler-x86.cpp
@@ -11,16 +11,17 @@
 
 #include "jit/AtomicOp.h"
 #include "jit/Bailouts.h"
 #include "jit/BaselineFrame.h"
 #include "jit/JitFrames.h"
 #include "jit/MacroAssembler.h"
 #include "jit/MoveEmitter.h"
 #include "util/Memory.h"
+#include "vm/JitActivation.h"  // js::jit::JitActivation
 
 #include "jit/MacroAssembler-inl.h"
 #include "vm/JSScript-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
 void MacroAssemblerX86::loadConstantDouble(double d, FloatRegister dest) {
--- a/js/src/jit/x86/Trampoline-x86.cpp
+++ b/js/src/jit/x86/Trampoline-x86.cpp
@@ -12,16 +12,17 @@
 #include "jit/JitRealm.h"
 #include "jit/JitSpewer.h"
 #include "jit/Linker.h"
 #ifdef JS_ION_PERF
 #  include "jit/PerfSpewer.h"
 #endif
 #include "jit/VMFunctions.h"
 #include "jit/x86/SharedICHelpers-x86.h"
+#include "vm/JitActivation.h"  // js::jit::JitActivation
 #include "vm/Realm.h"
 #ifdef MOZ_VTUNE
 #  include "vtune/VTuneWrapper.h"
 #endif
 
 #include "jit/MacroAssembler-inl.h"
 #include "vm/JSScript-inl.h"
 
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -25,16 +25,17 @@
 #include "js/CharacterEncoding.h"
 #include "js/PropertySpec.h"
 #include "js/UniquePtr.h"
 #include "js/Warnings.h"  // JS::{,Set}WarningReporter
 #include "js/Wrapper.h"
 #include "util/Memory.h"
 #include "util/StringBuffer.h"
 #include "vm/ErrorObject.h"
+#include "vm/FrameIter.h"  // js::NonBuiltinFrameIter
 #include "vm/GlobalObject.h"
 #include "vm/JSContext.h"
 #include "vm/JSFunction.h"
 #include "vm/JSObject.h"
 #include "vm/JSScript.h"
 #include "vm/SavedStacks.h"
 #include "vm/SelfHosting.h"
 #include "vm/StringType.h"
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -23,16 +23,17 @@
 #include "js/CharacterEncoding.h"
 #include "js/Printf.h"
 #include "js/Proxy.h"
 #include "js/Wrapper.h"
 #include "proxy/DeadObjectProxy.h"
 #include "util/Poison.h"
 #include "vm/ArgumentsObject.h"
 #include "vm/DateObject.h"
+#include "vm/FrameIter.h"  // js::FrameIter
 #include "vm/JSContext.h"
 #include "vm/JSObject.h"
 #include "vm/Printer.h"
 #include "vm/Realm.h"
 #include "vm/Time.h"
 #include "vm/WrapperObject.h"
 
 #include "gc/Nursery-inl.h"
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -279,16 +279,17 @@ UNIFIED_SOURCES += [
     '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/Activation.cpp',
     'vm/ArgumentsObject.cpp',
     'vm/ArrayBufferObject.cpp',
     'vm/ArrayBufferViewObject.cpp',
     'vm/AsyncFunction.cpp',
     'vm/AsyncIteration.cpp',
     'vm/BigIntType.cpp',
     'vm/BuildId.cpp',
     'vm/BytecodeUtil.cpp',
@@ -300,24 +301,26 @@ UNIFIED_SOURCES += [
     'vm/CompilationAndEvaluation.cpp',
     'vm/Compression.cpp',
     'vm/DateTime.cpp',
     'vm/EnvironmentObject.cpp',
     'vm/EqualityOperations.cpp',
     'vm/ErrorObject.cpp',
     'vm/ErrorReporting.cpp',
     'vm/ForOfIterator.cpp',
+    'vm/FrameIter.cpp',
     'vm/GeckoProfiler.cpp',
     'vm/GeneratorObject.cpp',
     'vm/GlobalObject.cpp',
     'vm/HelperThreads.cpp',
     'vm/Id.cpp',
     'vm/Initialization.cpp',
     'vm/Instrumentation.cpp',
     'vm/Iteration.cpp',
+    'vm/JitActivation.cpp',
     'vm/JSAtom.cpp',
     'vm/JSContext.cpp',
     'vm/JSFunction.cpp',
     'vm/JSObject.cpp',
     'vm/JSONParser.cpp',
     'vm/JSONPrinter.cpp',
     'vm/JSScript.cpp',
     'vm/List.cpp',
copy from js/src/vm/Stack-inl.h
copy to js/src/vm/Activation-inl.h
--- a/js/src/vm/Stack-inl.h
+++ b/js/src/vm/Activation-inl.h
@@ -1,975 +1,111 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * vim: set ts=8 sts=2 et sw=2 tw=80:
  * 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 vm_Stack_inl_h
-#define vm_Stack_inl_h
+#ifndef vm_Activation_inl_h
+#define vm_Activation_inl_h
 
-#include "vm/Stack.h"
-
-#include "mozilla/Maybe.h"
-#include "mozilla/PodOperations.h"
+#include "vm/Activation.h"
 
-#include "jit/BaselineFrame.h"
-#include "jit/RematerializedFrame.h"
-#include "js/Debug.h"
-#include "vm/EnvironmentObject.h"
-#include "vm/JSContext.h"
-#include "vm/JSScript.h"
+#include "mozilla/Assertions.h"  // MOZ_ASSERT{,_IF}, MOZ_CRASH
+#include "mozilla/Likely.h"  // MOZ_UNLIKELY
+#include "mozilla/Maybe.h"  // mozilla::Maybe
 
-#include "jit/BaselineFrame-inl.h"
-#include "vm/JSObject-inl.h"
-#include "vm/JSScript-inl.h"
-#include "vm/NativeObject-inl.h"
+#include "jit/BaselineFrame.h"  // js::jit::BaselineFrame
+#include "jit/JSJitFrameIter.h"  // js::jit::CalleeToken
+#include "vm/FrameIter.h"  // js::FrameIter
+#include "vm/JitActivation.h"  // js::jit::JitActivation
+#include "vm/JSContext.h"  // JSContext
+#include "vm/Stack.h"  // js::AbstractFramePtr
 
 namespace js {
 
-inline HandleObject InterpreterFrame::environmentChain() const {
-  return HandleObject::fromMarkedLocation(&envChain_);
-}
-
-inline GlobalObject& InterpreterFrame::global() const {
-  return script()->global();
-}
-
-inline JSObject& InterpreterFrame::varObj() const {
-  return GetVariablesObject(environmentChain());
-}
-
-inline LexicalEnvironmentObject&
-InterpreterFrame::extensibleLexicalEnvironment() const {
-  return NearestEnclosingExtensibleLexicalEnvironment(environmentChain());
-}
-
-inline void InterpreterFrame::initCallFrame(InterpreterFrame* prev,
-                                            jsbytecode* prevpc, Value* prevsp,
-                                            JSFunction& callee,
-                                            JSScript* script, Value* argv,
-                                            uint32_t nactual,
-                                            MaybeConstruct constructing) {
-  MOZ_ASSERT(callee.nonLazyScript() == script);
-
-  /* Initialize stack frame members. */
-  flags_ = 0;
-  if (constructing) {
-    flags_ |= CONSTRUCTING;
-  }
-  argv_ = argv;
-  script_ = script;
-  nactual_ = nactual;
-  envChain_ = callee.environment();
-  prev_ = prev;
-  prevpc_ = prevpc;
-  prevsp_ = prevsp;
-
-  if (script->isDebuggee()) {
-    setIsDebuggee();
-  }
-
-  initLocals();
-}
-
-inline void InterpreterFrame::initLocals() {
-  SetValueRangeToUndefined(slots(), script()->nfixed());
-}
-
-inline Value& InterpreterFrame::unaliasedLocal(uint32_t i) {
-  MOZ_ASSERT(i < script()->nfixed());
-  return slots()[i];
-}
-
-inline Value& InterpreterFrame::unaliasedFormal(
-    unsigned i, MaybeCheckAliasing checkAliasing) {
-  MOZ_ASSERT(i < numFormalArgs());
-  MOZ_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals());
-  MOZ_ASSERT_IF(checkAliasing, !script()->formalIsAliased(i));
-  return argv()[i];
-}
-
-inline Value& InterpreterFrame::unaliasedActual(
-    unsigned i, MaybeCheckAliasing checkAliasing) {
-  MOZ_ASSERT(i < numActualArgs());
-  MOZ_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals());
-  MOZ_ASSERT_IF(checkAliasing && i < numFormalArgs(),
-                !script()->formalIsAliased(i));
-  return argv()[i];
-}
-
-template <class Op>
-inline void InterpreterFrame::unaliasedForEachActual(Op op) {
-  // Don't assert !script()->funHasAnyAliasedFormal() since this function is
-  // called from ArgumentsObject::createUnexpected() which can access aliased
-  // slots.
-
-  const Value* argsEnd = argv() + numActualArgs();
-  for (const Value* p = argv(); p < argsEnd; ++p) {
-    op(*p);
-  }
-}
-
-struct CopyTo {
-  Value* dst;
-  explicit CopyTo(Value* dst) : dst(dst) {}
-  void operator()(const Value& src) { *dst++ = src; }
-};
-
-struct CopyToHeap {
-  GCPtrValue* dst;
-  explicit CopyToHeap(GCPtrValue* dst) : dst(dst) {}
-  void operator()(const Value& src) {
-    dst->init(src);
-    ++dst;
-  }
-};
-
-inline ArgumentsObject& InterpreterFrame::argsObj() const {
-  MOZ_ASSERT(script()->needsArgsObj());
-  MOZ_ASSERT(flags_ & HAS_ARGS_OBJ);
-  return *argsObj_;
-}
-
-inline void InterpreterFrame::initArgsObj(ArgumentsObject& argsobj) {
-  MOZ_ASSERT(script()->needsArgsObj());
-  flags_ |= HAS_ARGS_OBJ;
-  argsObj_ = &argsobj;
-}
-
-inline EnvironmentObject& InterpreterFrame::aliasedEnvironment(
-    EnvironmentCoordinate ec) const {
-  JSObject* env = &environmentChain()->as<EnvironmentObject>();
-  for (unsigned i = ec.hops(); i; i--) {
-    env = &env->as<EnvironmentObject>().enclosingEnvironment();
-  }
-  return env->as<EnvironmentObject>();
-}
-
-template <typename SpecificEnvironment>
-inline void InterpreterFrame::pushOnEnvironmentChain(SpecificEnvironment& env) {
-  MOZ_ASSERT(*environmentChain() == env.enclosingEnvironment());
-  envChain_ = &env;
-  if (IsFrameInitialEnvironment(this, env)) {
-    flags_ |= HAS_INITIAL_ENV;
-  }
-}
-
-template <typename SpecificEnvironment>
-inline void InterpreterFrame::popOffEnvironmentChain() {
-  MOZ_ASSERT(envChain_->is<SpecificEnvironment>());
-  envChain_ = &envChain_->as<SpecificEnvironment>().enclosingEnvironment();
-}
-
-inline void InterpreterFrame::replaceInnermostEnvironment(
-    EnvironmentObject& env) {
-  MOZ_ASSERT(env.enclosingEnvironment() ==
-             envChain_->as<EnvironmentObject>().enclosingEnvironment());
-  envChain_ = &env;
-}
-
-bool InterpreterFrame::hasInitialEnvironment() const {
-  MOZ_ASSERT(script()->initialEnvironmentShape());
-  return flags_ & HAS_INITIAL_ENV;
-}
-
-inline CallObject& InterpreterFrame::callObj() const {
-  MOZ_ASSERT(callee().needsCallObject());
-
-  JSObject* pobj = environmentChain();
-  while (MOZ_UNLIKELY(!pobj->is<CallObject>())) {
-    pobj = pobj->enclosingEnvironment();
-  }
-  return pobj->as<CallObject>();
-}
-
-inline void InterpreterFrame::unsetIsDebuggee() {
-  MOZ_ASSERT(!script()->isDebuggee());
-  flags_ &= ~DEBUGGEE;
-}
-
-/*****************************************************************************/
-
-inline void InterpreterStack::purge(JSRuntime* rt) {
-  rt->gc.queueUnusedLifoBlocksForFree(&allocator_);
-}
-
-uint8_t* InterpreterStack::allocateFrame(JSContext* cx, size_t size) {
-  size_t maxFrames;
-  if (cx->realm()->principals() == cx->runtime()->trustedPrincipals()) {
-    maxFrames = MAX_FRAMES_TRUSTED;
-  } else {
-    maxFrames = MAX_FRAMES;
-  }
-
-  if (MOZ_UNLIKELY(frameCount_ >= maxFrames)) {
-    ReportOverRecursed(cx);
-    return nullptr;
-  }
-
-  uint8_t* buffer = reinterpret_cast<uint8_t*>(allocator_.alloc(size));
-  if (!buffer) {
-    ReportOutOfMemory(cx);
-    return nullptr;
-  }
-
-  frameCount_++;
-  return buffer;
-}
-
-MOZ_ALWAYS_INLINE InterpreterFrame* InterpreterStack::getCallFrame(
-    JSContext* cx, const CallArgs& args, HandleScript script,
-    MaybeConstruct constructing, Value** pargv) {
-  JSFunction* fun = &args.callee().as<JSFunction>();
-
-  MOZ_ASSERT(fun->nonLazyScript() == script);
-  unsigned nformal = fun->nargs();
-  unsigned nvals = script->nslots();
-
-  if (args.length() >= nformal) {
-    *pargv = args.array();
-    uint8_t* buffer =
-        allocateFrame(cx, sizeof(InterpreterFrame) + nvals * sizeof(Value));
-    return reinterpret_cast<InterpreterFrame*>(buffer);
-  }
-
-  // Pad any missing arguments with |undefined|.
-  MOZ_ASSERT(args.length() < nformal);
-
-  unsigned nfunctionState = 2 + constructing;  // callee, |this|, |new.target|
-
-  nvals += nformal + nfunctionState;
-  uint8_t* buffer =
-      allocateFrame(cx, sizeof(InterpreterFrame) + nvals * sizeof(Value));
-  if (!buffer) {
-    return nullptr;
-  }
-
-  Value* argv = reinterpret_cast<Value*>(buffer);
-  unsigned nmissing = nformal - args.length();
-
-  mozilla::PodCopy(argv, args.base(), 2 + args.length());
-  SetValueRangeToUndefined(argv + 2 + args.length(), nmissing);
-
-  if (constructing) {
-    argv[2 + nformal] = args.newTarget();
-  }
-
-  *pargv = argv + 2;
-  return reinterpret_cast<InterpreterFrame*>(argv + nfunctionState + nformal);
-}
-
-MOZ_ALWAYS_INLINE bool InterpreterStack::pushInlineFrame(
-    JSContext* cx, InterpreterRegs& regs, const CallArgs& args,
-    HandleScript script, MaybeConstruct constructing) {
-  RootedFunction callee(cx, &args.callee().as<JSFunction>());
-  MOZ_ASSERT(regs.sp == args.end());
-  MOZ_ASSERT(callee->nonLazyScript() == script);
-
-  InterpreterFrame* prev = regs.fp();
-  jsbytecode* prevpc = regs.pc;
-  Value* prevsp = regs.sp;
-  MOZ_ASSERT(prev);
-
-  LifoAlloc::Mark mark = allocator_.mark();
-
-  Value* argv;
-  InterpreterFrame* fp = getCallFrame(cx, args, script, constructing, &argv);
-  if (!fp) {
-    return false;
-  }
-
-  fp->mark_ = mark;
-
-  /* Initialize frame, locals, regs. */
-  fp->initCallFrame(prev, prevpc, prevsp, *callee, script, argv, args.length(),
-                    constructing);
-
-  regs.prepareToRun(*fp, script);
-  return true;
-}
-
-MOZ_ALWAYS_INLINE bool InterpreterStack::resumeGeneratorCallFrame(
-    JSContext* cx, InterpreterRegs& regs, HandleFunction callee,
-    HandleObject envChain) {
-  MOZ_ASSERT(callee->isGenerator() || callee->isAsync());
-  RootedScript script(cx, callee->nonLazyScript());
-  InterpreterFrame* prev = regs.fp();
-  jsbytecode* prevpc = regs.pc;
-  Value* prevsp = regs.sp;
-  MOZ_ASSERT(prev);
-
-  LifoAlloc::Mark mark = allocator_.mark();
-
-  // (Async) generators and async functions are not constructors.
-  MOZ_ASSERT(!callee->isConstructor());
-
-  // Include callee, |this|, and maybe |new.target|
-  unsigned nformal = callee->nargs();
-  unsigned nvals = 2 + nformal + script->nslots();
-
-  uint8_t* buffer =
-      allocateFrame(cx, sizeof(InterpreterFrame) + nvals * sizeof(Value));
-  if (!buffer) {
-    return false;
-  }
-
-  Value* argv = reinterpret_cast<Value*>(buffer) + 2;
-  argv[-2] = ObjectValue(*callee);
-  argv[-1] = UndefinedValue();
-  SetValueRangeToUndefined(argv, nformal);
-
-  InterpreterFrame* fp = reinterpret_cast<InterpreterFrame*>(argv + nformal);
-  fp->mark_ = mark;
-  fp->initCallFrame(prev, prevpc, prevsp, *callee, script, argv, 0,
-                    NO_CONSTRUCT);
-  fp->resumeGeneratorFrame(envChain);
-
-  regs.prepareToRun(*fp, script);
-  return true;
-}
-
-MOZ_ALWAYS_INLINE void InterpreterStack::popInlineFrame(InterpreterRegs& regs) {
-  InterpreterFrame* fp = regs.fp();
-  regs.popInlineFrame();
-  regs.sp[-1] = fp->returnValue();
-  releaseFrame(fp);
-  MOZ_ASSERT(regs.fp());
-}
-
-template <class Op>
-inline void FrameIter::unaliasedForEachActual(JSContext* cx, Op op) {
-  switch (data_.state_) {
-    case DONE:
-      break;
-    case INTERP:
-      interpFrame()->unaliasedForEachActual(op);
-      return;
-    case JIT:
-      MOZ_ASSERT(isJSJit());
-      if (jsJitFrame().isIonJS()) {
-        jit::MaybeReadFallback recover(cx, activation()->asJit(),
-                                       &jsJitFrame());
-        ionInlineFrames_.unaliasedForEachActual(cx, op, jit::ReadFrame_Actuals,
-                                                recover);
-      } else if (jsJitFrame().isBailoutJS()) {
-        // :TODO: (Bug 1070962) If we are introspecting the frame which is
-        // being bailed, then we might be in the middle of recovering
-        // instructions. Stacking computeInstructionResults implies that we
-        // might be recovering result twice. In the mean time, to avoid
-        // that, we just return Undefined values for instruction results
-        // which are not yet recovered.
-        jit::MaybeReadFallback fallback;
-        ionInlineFrames_.unaliasedForEachActual(cx, op, jit::ReadFrame_Actuals,
-                                                fallback);
-      } else {
-        MOZ_ASSERT(jsJitFrame().isBaselineJS());
-        jsJitFrame().unaliasedForEachActual(op, jit::ReadFrame_Actuals);
-      }
-      return;
-  }
-  MOZ_CRASH("Unexpected state");
-}
-
-inline HandleValue AbstractFramePtr::returnValue() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->returnValue();
-  }
-  if (isWasmDebugFrame()) {
-    return asWasmDebugFrame()->returnValue();
-  }
-  return asBaselineFrame()->returnValue();
-}
-
-inline void AbstractFramePtr::setReturnValue(const Value& rval) const {
-  if (isInterpreterFrame()) {
-    asInterpreterFrame()->setReturnValue(rval);
-    return;
-  }
-  if (isBaselineFrame()) {
-    asBaselineFrame()->setReturnValue(rval);
-    return;
-  }
-  if (isWasmDebugFrame()) {
-    // TODO handle wasm function return value
-    // The function is called from Debugger::slowPathOnLeaveFrame --
-    // ignoring value for wasm.
-    return;
-  }
-  asRematerializedFrame()->setReturnValue(rval);
-}
-
-inline JSObject* AbstractFramePtr::environmentChain() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->environmentChain();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->environmentChain();
-  }
-  if (isWasmDebugFrame()) {
-    return &global()->lexicalEnvironment();
-  }
-  return asRematerializedFrame()->environmentChain();
-}
-
-template <typename SpecificEnvironment>
-inline void AbstractFramePtr::pushOnEnvironmentChain(SpecificEnvironment& env) {
-  if (isInterpreterFrame()) {
-    asInterpreterFrame()->pushOnEnvironmentChain(env);
-    return;
-  }
-  if (isBaselineFrame()) {
-    asBaselineFrame()->pushOnEnvironmentChain(env);
-    return;
-  }
-  asRematerializedFrame()->pushOnEnvironmentChain(env);
-}
-
-template <typename SpecificEnvironment>
-inline void AbstractFramePtr::popOffEnvironmentChain() {
-  if (isInterpreterFrame()) {
-    asInterpreterFrame()->popOffEnvironmentChain<SpecificEnvironment>();
-    return;
-  }
-  if (isBaselineFrame()) {
-    asBaselineFrame()->popOffEnvironmentChain<SpecificEnvironment>();
-    return;
-  }
-  asRematerializedFrame()->popOffEnvironmentChain<SpecificEnvironment>();
-}
-
-inline CallObject& AbstractFramePtr::callObj() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->callObj();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->callObj();
-  }
-  return asRematerializedFrame()->callObj();
-}
-
-inline bool AbstractFramePtr::initFunctionEnvironmentObjects(JSContext* cx) {
-  return js::InitFunctionEnvironmentObjects(cx, *this);
-}
-
-inline bool AbstractFramePtr::pushVarEnvironment(JSContext* cx,
-                                                 HandleScope scope) {
-  return js::PushVarEnvironmentObject(cx, scope, *this);
-}
-
-inline JS::Realm* AbstractFramePtr::realm() const {
-  return environmentChain()->nonCCWRealm();
-}
-
-inline unsigned AbstractFramePtr::numActualArgs() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->numActualArgs();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->numActualArgs();
-  }
-  return asRematerializedFrame()->numActualArgs();
-}
-
-inline unsigned AbstractFramePtr::numFormalArgs() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->numFormalArgs();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->numFormalArgs();
-  }
-  return asRematerializedFrame()->numFormalArgs();
-}
-
-inline Value& AbstractFramePtr::unaliasedLocal(uint32_t i) {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->unaliasedLocal(i);
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->unaliasedLocal(i);
-  }
-  return asRematerializedFrame()->unaliasedLocal(i);
-}
-
-inline Value& AbstractFramePtr::unaliasedFormal(
-    unsigned i, MaybeCheckAliasing checkAliasing) {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->unaliasedFormal(i, checkAliasing);
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->unaliasedFormal(i, checkAliasing);
-  }
-  return asRematerializedFrame()->unaliasedFormal(i, checkAliasing);
-}
-
-inline Value& AbstractFramePtr::unaliasedActual(
-    unsigned i, MaybeCheckAliasing checkAliasing) {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->unaliasedActual(i, checkAliasing);
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->unaliasedActual(i, checkAliasing);
-  }
-  return asRematerializedFrame()->unaliasedActual(i, checkAliasing);
-}
-
-inline bool AbstractFramePtr::hasInitialEnvironment() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->hasInitialEnvironment();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->hasInitialEnvironment();
-  }
-  return asRematerializedFrame()->hasInitialEnvironment();
-}
-
-inline bool AbstractFramePtr::isGlobalFrame() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->isGlobalFrame();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->isGlobalFrame();
-  }
-  if (isWasmDebugFrame()) {
-    return false;
-  }
-  return asRematerializedFrame()->isGlobalFrame();
-}
-
-inline bool AbstractFramePtr::isModuleFrame() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->isModuleFrame();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->isModuleFrame();
-  }
-  if (isWasmDebugFrame()) {
-    return false;
-  }
-  return asRematerializedFrame()->isModuleFrame();
-}
-
-inline bool AbstractFramePtr::isEvalFrame() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->isEvalFrame();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->isEvalFrame();
-  }
-  if (isWasmDebugFrame()) {
-    return false;
-  }
-  MOZ_ASSERT(isRematerializedFrame());
-  return false;
-}
-
-inline bool AbstractFramePtr::isDebuggerEvalFrame() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->isDebuggerEvalFrame();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->isDebuggerEvalFrame();
-  }
-  MOZ_ASSERT(isRematerializedFrame());
-  return false;
-}
-
-inline bool AbstractFramePtr::isDebuggee() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->isDebuggee();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->isDebuggee();
-  }
-  if (isWasmDebugFrame()) {
-    return asWasmDebugFrame()->isDebuggee();
-  }
-  return asRematerializedFrame()->isDebuggee();
-}
-
-inline void AbstractFramePtr::setIsDebuggee() {
-  if (isInterpreterFrame()) {
-    asInterpreterFrame()->setIsDebuggee();
-  } else if (isBaselineFrame()) {
-    asBaselineFrame()->setIsDebuggee();
-  } else if (isWasmDebugFrame()) {
-    asWasmDebugFrame()->setIsDebuggee();
-  } else {
-    asRematerializedFrame()->setIsDebuggee();
-  }
-}
-
-inline void AbstractFramePtr::unsetIsDebuggee() {
-  if (isInterpreterFrame()) {
-    asInterpreterFrame()->unsetIsDebuggee();
-  } else if (isBaselineFrame()) {
-    asBaselineFrame()->unsetIsDebuggee();
-  } else if (isWasmDebugFrame()) {
-    asWasmDebugFrame()->unsetIsDebuggee();
-  } else {
-    asRematerializedFrame()->unsetIsDebuggee();
-  }
-}
-
-inline bool AbstractFramePtr::isConstructing() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->isConstructing();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->isConstructing();
-  }
-  if (isRematerializedFrame()) {
-    return asRematerializedFrame()->isConstructing();
-  }
-  MOZ_CRASH("Unexpected frame");
-}
-
-inline bool AbstractFramePtr::hasArgs() const { return isFunctionFrame(); }
-
-inline bool AbstractFramePtr::hasScript() const { return !isWasmDebugFrame(); }
-
-inline JSScript* AbstractFramePtr::script() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->script();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->script();
-  }
-  return asRematerializedFrame()->script();
-}
-
-inline wasm::Instance* AbstractFramePtr::wasmInstance() const {
-  return asWasmDebugFrame()->instance();
-}
-
-inline GlobalObject* AbstractFramePtr::global() const {
-  if (isWasmDebugFrame()) {
-    return asWasmDebugFrame()->global();
-  }
-  return &script()->global();
-}
-
-inline bool AbstractFramePtr::hasGlobal(const GlobalObject* global) const {
-  if (isWasmDebugFrame()) {
-    return asWasmDebugFrame()->hasGlobal(global);
-  }
-  return script()->hasGlobal(global);
-}
-
-inline JSFunction* AbstractFramePtr::callee() const {
-  if (isInterpreterFrame()) {
-    return &asInterpreterFrame()->callee();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->callee();
-  }
-  return asRematerializedFrame()->callee();
-}
-
-inline Value AbstractFramePtr::calleev() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->calleev();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->calleev();
-  }
-  return asRematerializedFrame()->calleev();
-}
-
-inline bool AbstractFramePtr::isFunctionFrame() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->isFunctionFrame();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->isFunctionFrame();
-  }
-  if (isWasmDebugFrame()) {
-    return false;
-  }
-  return asRematerializedFrame()->isFunctionFrame();
-}
-
-inline bool AbstractFramePtr::isGeneratorFrame() const {
-  if (!isFunctionFrame()) {
-    return false;
-  }
-  JSScript* s = script();
-  return s->isGenerator() || s->isAsync();
-}
-
-inline bool AbstractFramePtr::isNonStrictDirectEvalFrame() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->isNonStrictDirectEvalFrame();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->isNonStrictDirectEvalFrame();
-  }
-  MOZ_ASSERT(isRematerializedFrame());
-  return false;
-}
-
-inline bool AbstractFramePtr::isStrictEvalFrame() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->isStrictEvalFrame();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->isStrictEvalFrame();
-  }
-  MOZ_ASSERT(isRematerializedFrame());
-  return false;
-}
-
-inline Value* AbstractFramePtr::argv() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->argv();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->argv();
-  }
-  return asRematerializedFrame()->argv();
-}
-
-inline bool AbstractFramePtr::hasArgsObj() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->hasArgsObj();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->hasArgsObj();
-  }
-  return asRematerializedFrame()->hasArgsObj();
-}
-
-inline ArgumentsObject& AbstractFramePtr::argsObj() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->argsObj();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->argsObj();
-  }
-  return asRematerializedFrame()->argsObj();
-}
-
-inline void AbstractFramePtr::initArgsObj(ArgumentsObject& argsobj) const {
-  if (isInterpreterFrame()) {
-    asInterpreterFrame()->initArgsObj(argsobj);
-    return;
-  }
-  asBaselineFrame()->initArgsObj(argsobj);
-}
-
-inline bool AbstractFramePtr::prevUpToDate() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->prevUpToDate();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->prevUpToDate();
-  }
-  if (isWasmDebugFrame()) {
-    return asWasmDebugFrame()->prevUpToDate();
-  }
-  return asRematerializedFrame()->prevUpToDate();
-}
-
-inline void AbstractFramePtr::setPrevUpToDate() const {
-  if (isInterpreterFrame()) {
-    asInterpreterFrame()->setPrevUpToDate();
-    return;
-  }
-  if (isBaselineFrame()) {
-    asBaselineFrame()->setPrevUpToDate();
-    return;
-  }
-  if (isWasmDebugFrame()) {
-    asWasmDebugFrame()->setPrevUpToDate();
-    return;
-  }
-  asRematerializedFrame()->setPrevUpToDate();
-}
-
-inline void AbstractFramePtr::unsetPrevUpToDate() const {
-  if (isInterpreterFrame()) {
-    asInterpreterFrame()->unsetPrevUpToDate();
-    return;
-  }
-  if (isBaselineFrame()) {
-    asBaselineFrame()->unsetPrevUpToDate();
-    return;
-  }
-  if (isWasmDebugFrame()) {
-    asWasmDebugFrame()->unsetPrevUpToDate();
-    return;
-  }
-  asRematerializedFrame()->unsetPrevUpToDate();
-}
-
-inline Value& AbstractFramePtr::thisArgument() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->thisArgument();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->thisArgument();
-  }
-  return asRematerializedFrame()->thisArgument();
-}
-
-inline Value AbstractFramePtr::newTarget() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->newTarget();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->newTarget();
-  }
-  return asRematerializedFrame()->newTarget();
-}
-
-inline bool AbstractFramePtr::debuggerNeedsCheckPrimitiveReturn() const {
-  if (isWasmDebugFrame()) {
-    return false;
-  }
-  return script()->isDerivedClassConstructor();
-}
-
-ActivationEntryMonitor::ActivationEntryMonitor(JSContext* cx)
+inline ActivationEntryMonitor::ActivationEntryMonitor(JSContext* cx)
     : cx_(cx), entryMonitor_(cx->entryMonitor) {
   cx->entryMonitor = nullptr;
 }
 
-ActivationEntryMonitor::ActivationEntryMonitor(JSContext* cx,
-                                               InterpreterFrame* entryFrame)
+inline ActivationEntryMonitor::ActivationEntryMonitor(
+    JSContext* cx, InterpreterFrame* entryFrame)
     : ActivationEntryMonitor(cx) {
   if (MOZ_UNLIKELY(entryMonitor_)) {
     init(cx, entryFrame);
   }
 }
 
-ActivationEntryMonitor::ActivationEntryMonitor(JSContext* cx,
-                                               jit::CalleeToken entryToken)
+inline ActivationEntryMonitor::ActivationEntryMonitor(
+    JSContext* cx, jit::CalleeToken entryToken)
     : ActivationEntryMonitor(cx) {
   if (MOZ_UNLIKELY(entryMonitor_)) {
     init(cx, entryToken);
   }
 }
 
-ActivationEntryMonitor::~ActivationEntryMonitor() {
+inline ActivationEntryMonitor::~ActivationEntryMonitor() {
   if (entryMonitor_) {
     entryMonitor_->Exit(cx_);
   }
 
   cx_->entryMonitor = entryMonitor_;
 }
 
-Activation::Activation(JSContext* cx, Kind kind)
+inline Activation::Activation(JSContext* cx, Kind kind)
     : cx_(cx),
       compartment_(cx->compartment()),
       prev_(cx->activation_),
       prevProfiling_(prev_ ? prev_->mostRecentProfiling() : nullptr),
       hideScriptedCallerCount_(0),
       frameCache_(cx),
       asyncStack_(cx, cx->asyncStackForNewActivations()),
       asyncCause_(cx->asyncCauseForNewActivations),
       asyncCallIsExplicit_(cx->asyncCallIsExplicit),
       kind_(kind) {
   cx->asyncStackForNewActivations() = nullptr;
   cx->asyncCauseForNewActivations = nullptr;
   cx->asyncCallIsExplicit = false;
   cx->activation_ = this;
 }
 
-Activation::~Activation() {
+inline Activation::~Activation() {
   MOZ_ASSERT_IF(isProfiling(), this != cx_->profilingActivation_);
   MOZ_ASSERT(cx_->activation_ == this);
   MOZ_ASSERT(hideScriptedCallerCount_ == 0);
   cx_->activation_ = prev_;
   cx_->asyncCauseForNewActivations = asyncCause_;
   cx_->asyncStackForNewActivations() = asyncStack_;
   cx_->asyncCallIsExplicit = asyncCallIsExplicit_;
 }
 
-bool Activation::isProfiling() const {
+inline bool Activation::isProfiling() const {
   if (isInterpreter()) {
     return asInterpreter()->isProfiling();
   }
 
   MOZ_ASSERT(isJit());
   return asJit()->isProfiling();
 }
 
-Activation* Activation::mostRecentProfiling() {
+inline Activation* Activation::mostRecentProfiling() {
   if (isProfiling()) {
     return this;
   }
   return prevProfiling_;
 }
 
 inline LiveSavedFrameCache* Activation::getLiveSavedFrameCache(JSContext* cx) {
   if (!frameCache_.get().initialized() && !frameCache_.get().init(cx)) {
     return nullptr;
   }
   return frameCache_.address();
 }
 
-InterpreterActivation::InterpreterActivation(RunState& state, JSContext* cx,
-                                             InterpreterFrame* entryFrame)
-    : Activation(cx, Interpreter),
-      entryFrame_(entryFrame),
-      opMask_(0)
-#ifdef DEBUG
-      ,
-      oldFrameCount_(cx->interpreterStack().frameCount_)
-#endif
-{
-  regs_.prepareToRun(*entryFrame, state.script());
-  MOZ_ASSERT(regs_.pc == state.script()->code());
-}
-
-InterpreterActivation::~InterpreterActivation() {
-  // Pop all inline frames.
-  while (regs_.fp() != entryFrame_) {
-    popInlineFrame(regs_.fp());
-  }
-
-  MOZ_ASSERT(oldFrameCount_ == cx_->interpreterStack().frameCount_);
-  MOZ_ASSERT_IF(oldFrameCount_ == 0,
-                cx_->interpreterStack().allocator_.used() == 0);
-
-  if (entryFrame_) {
-    cx_->interpreterStack().releaseFrame(entryFrame_);
-  }
-}
-
-inline bool InterpreterActivation::pushInlineFrame(
-    const CallArgs& args, HandleScript script, MaybeConstruct constructing) {
-  if (!cx_->interpreterStack().pushInlineFrame(cx_, regs_, args, script,
-                                               constructing)) {
-    return false;
-  }
-  MOZ_ASSERT(regs_.fp()->script()->compartment() == compartment());
-  return true;
-}
-
-inline void InterpreterActivation::popInlineFrame(InterpreterFrame* frame) {
-  (void)frame;  // Quell compiler warning.
-  MOZ_ASSERT(regs_.fp() == frame);
-  MOZ_ASSERT(regs_.fp() != entryFrame_);
-
-  cx_->interpreterStack().popInlineFrame(regs_);
-}
-
-inline bool InterpreterActivation::resumeGeneratorFrame(HandleFunction callee,
-                                                        HandleObject envChain) {
-  InterpreterStack& stack = cx_->interpreterStack();
-  if (!stack.resumeGeneratorCallFrame(cx_, regs_, callee, envChain)) {
-    return false;
-  }
-
-  MOZ_ASSERT(regs_.fp()->script()->compartment() == compartment_);
-  return true;
-}
-
 /* static */ inline mozilla::Maybe<LiveSavedFrameCache::FramePtr>
 LiveSavedFrameCache::FramePtr::create(const FrameIter& iter) {
   if (iter.done()) {
     return mozilla::Nothing();
   }
 
   if (iter.isPhysicalJitFrame()) {
     return mozilla::Some(FramePtr(iter.physicalJitFrame()));
@@ -1043,11 +179,15 @@ struct LiveSavedFrameCache::FramePtr::Cl
     f->clearHasCachedSavedFrame();
   }
 };
 
 inline void LiveSavedFrameCache::FramePtr::clearHasCachedSavedFrame() {
   ptr.match(ClearHasCachedMatcher());
 }
 
-} /* namespace js */
+inline bool Activation::hasWasmExitFP() const {
+  return isJit() && asJit()->hasWasmExitFP();
+}
 
-#endif /* vm_Stack_inl_h */
+}  // namespace js
+
+#endif  // vm_Activation_inl_h
copy from js/src/vm/Stack.cpp
copy to js/src/vm/Activation.cpp
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Activation.cpp
@@ -1,1479 +1,52 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * vim: set ts=8 sts=2 et sw=2 tw=80:
  * 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/. */
 
-#include "vm/Stack-inl.h"
+#include "vm/Activation-inl.h"
 
-#include <algorithm>
-#include <utility>
+#include "mozilla/Assertions.h"  // MOZ_ASSERT
+
+#include <stddef.h>  // size_t
+#include <stdint.h>  // uint8_t, uint32_t
 
-#include "debugger/DebugAPI.h"
-#include "gc/Marking.h"
-#include "jit/BaselineFrame.h"
-#include "jit/JitcodeMap.h"
-#include "jit/JitRealm.h"
-#include "jit/shared/CodeGenerator-shared.h"
-#include "vm/JSContext.h"
-#include "vm/Opcodes.h"
-#include "wasm/WasmInstance.h"
+#include "debugger/DebugAPI.h"  // js::DebugAPI
+#include "gc/GC.h"  // js::gc::AutoSuppressGC
+#include "jit/JitFrames.h"  // js::jit::CalleeToken{IsFunction,To{Function,Script}}
+#include "js/RootingAPI.h"  // JS::Rooted
+#include "js/Value.h"  // JS::Value
+#include "vm/JSContext.h"  // JSContext, js::TlsContext
+#include "vm/Stack.h"  // js::InterpreterFrame
 
-#include "jit/JSJitFrameIter-inl.h"
-#include "vm/Compartment-inl.h"
-#include "vm/EnvironmentObject-inl.h"
-#include "vm/Interpreter-inl.h"
-#include "vm/Probes-inl.h"
+#include "vm/Compartment-inl.h"  // JS::Compartment::wrap
 
 using namespace js;
 
-using mozilla::ArrayLength;
-using mozilla::DebugOnly;
-using mozilla::Maybe;
-
-/*****************************************************************************/
-
-void InterpreterFrame::initExecuteFrame(JSContext* cx, HandleScript script,
-                                        AbstractFramePtr evalInFramePrev,
-                                        const Value& newTargetValue,
-                                        HandleObject envChain) {
-  flags_ = 0;
-  script_ = script;
-
-  // newTarget = NullValue is an initial sentinel for "please fill me in from
-  // the stack". It should never be passed from Ion code.
-  RootedValue newTarget(cx, newTargetValue);
-  if (script->isDirectEvalInFunction()) {
-    FrameIter iter(cx);
-    if (newTarget.isNull() && iter.hasScript() &&
-        iter.script()->bodyScope()->hasOnChain(ScopeKind::Function)) {
-      newTarget = iter.newTarget();
-    }
-  } else if (evalInFramePrev) {
-    if (newTarget.isNull() && evalInFramePrev.hasScript() &&
-        evalInFramePrev.script()->bodyScope()->hasOnChain(
-            ScopeKind::Function)) {
-      newTarget = evalInFramePrev.newTarget();
-    }
-  }
-
-  Value* dstvp = (Value*)this - 1;
-  dstvp[0] = newTarget;
-
-  envChain_ = envChain.get();
-  prev_ = nullptr;
-  prevpc_ = nullptr;
-  prevsp_ = nullptr;
-
-  evalInFramePrev_ = evalInFramePrev;
-  MOZ_ASSERT_IF(evalInFramePrev, isDebuggerEvalFrame());
-
-  if (script->isDebuggee()) {
-    setIsDebuggee();
-  }
-
-#ifdef DEBUG
-  Debug_SetValueRangeToCrashOnTouch(&rval_, 1);
-#endif
-}
-
-bool InterpreterFrame::isNonGlobalEvalFrame() const {
-  return isEvalFrame() && script()->bodyScope()->as<EvalScope>().isNonGlobal();
-}
-
-ArrayObject* InterpreterFrame::createRestParameter(JSContext* cx) {
-  MOZ_ASSERT(script()->hasRest());
-  unsigned nformal = callee().nargs() - 1, nactual = numActualArgs();
-  unsigned nrest = (nactual > nformal) ? nactual - nformal : 0;
-  Value* restvp = argv() + nformal;
-  return ObjectGroup::newArrayObject(cx, restvp, nrest, GenericObject,
-                                     ObjectGroup::NewArrayKind::UnknownIndex);
-}
-
-static inline void AssertScopeMatchesEnvironment(Scope* scope,
-                                                 JSObject* originalEnv) {
-#ifdef DEBUG
-  JSObject* env = originalEnv;
-  for (ScopeIter si(scope); si; si++) {
-    if (si.kind() == ScopeKind::NonSyntactic) {
-      while (env->is<WithEnvironmentObject>() ||
-             env->is<NonSyntacticVariablesObject>() ||
-             (env->is<LexicalEnvironmentObject>() &&
-              !env->as<LexicalEnvironmentObject>().isSyntactic())) {
-        MOZ_ASSERT(!IsSyntacticEnvironment(env));
-        env = &env->as<EnvironmentObject>().enclosingEnvironment();
-      }
-    } else if (si.hasSyntacticEnvironment()) {
-      switch (si.kind()) {
-        case ScopeKind::Function:
-          MOZ_ASSERT(env->as<CallObject>()
-                         .callee()
-                         .maybeCanonicalFunction()
-                         ->nonLazyScript() ==
-                     si.scope()->as<FunctionScope>().script());
-          env = &env->as<CallObject>().enclosingEnvironment();
-          break;
-
-        case ScopeKind::FunctionBodyVar:
-        case ScopeKind::ParameterExpressionVar:
-          MOZ_ASSERT(&env->as<VarEnvironmentObject>().scope() == si.scope());
-          env = &env->as<VarEnvironmentObject>().enclosingEnvironment();
-          break;
-
-        case ScopeKind::Lexical:
-        case ScopeKind::SimpleCatch:
-        case ScopeKind::Catch:
-        case ScopeKind::NamedLambda:
-        case ScopeKind::StrictNamedLambda:
-        case ScopeKind::FunctionLexical:
-          MOZ_ASSERT(&env->as<LexicalEnvironmentObject>().scope() ==
-                     si.scope());
-          env = &env->as<LexicalEnvironmentObject>().enclosingEnvironment();
-          break;
-
-        case ScopeKind::With:
-          MOZ_ASSERT(&env->as<WithEnvironmentObject>().scope() == si.scope());
-          env = &env->as<WithEnvironmentObject>().enclosingEnvironment();
-          break;
-
-        case ScopeKind::Eval:
-        case ScopeKind::StrictEval:
-          env = &env->as<VarEnvironmentObject>().enclosingEnvironment();
-          break;
-
-        case ScopeKind::Global:
-          MOZ_ASSERT(env->as<LexicalEnvironmentObject>().isGlobal());
-          env = &env->as<LexicalEnvironmentObject>().enclosingEnvironment();
-          MOZ_ASSERT(env->is<GlobalObject>());
-          break;
-
-        case ScopeKind::NonSyntactic:
-          MOZ_CRASH("NonSyntactic should not have a syntactic environment");
-          break;
-
-        case ScopeKind::Module:
-          MOZ_ASSERT(&env->as<ModuleEnvironmentObject>().module() ==
-                     si.scope()->as<ModuleScope>().module());
-          env = &env->as<ModuleEnvironmentObject>().enclosingEnvironment();
-          break;
-
-        case ScopeKind::WasmInstance:
-          env =
-              &env->as<WasmInstanceEnvironmentObject>().enclosingEnvironment();
-          break;
-
-        case ScopeKind::WasmFunction:
-          env = &env->as<WasmFunctionCallObject>().enclosingEnvironment();
-          break;
-      }
-    }
-  }
-
-  // In the case of a non-syntactic env chain, the immediate parent of the
-  // outermost non-syntactic env may be the global lexical env, or, if
-  // called from Debugger, a DebugEnvironmentProxy.
-  //
-  // In the case of a syntactic env chain, the outermost env is always a
-  // GlobalObject.
-  MOZ_ASSERT(env->is<GlobalObject>() || IsGlobalLexicalEnvironment(env) ||
-             env->is<DebugEnvironmentProxy>());
-#endif
-}
-
-static inline void AssertScopeMatchesEnvironment(InterpreterFrame* fp,
-                                                 jsbytecode* pc) {
-#ifdef DEBUG
-  // If we OOMed before fully initializing the environment chain, the scope
-  // and environment will definitely mismatch.
-  if (fp->script()->initialEnvironmentShape() && fp->hasInitialEnvironment()) {
-    AssertScopeMatchesEnvironment(fp->script()->innermostScope(pc),
-                                  fp->environmentChain());
-  }
-#endif
-}
-
-bool InterpreterFrame::initFunctionEnvironmentObjects(JSContext* cx) {
-  return js::InitFunctionEnvironmentObjects(cx, this);
-}
-
-bool InterpreterFrame::prologue(JSContext* cx) {
-  RootedScript script(cx, this->script());
-
-  MOZ_ASSERT(cx->interpreterRegs().pc == script->code());
-  MOZ_ASSERT(cx->realm() == script->realm());
-
-  if (isEvalFrame() || isGlobalFrame()) {
-    HandleObject env = environmentChain();
-    if (!CheckGlobalOrEvalDeclarationConflicts(cx, env, script)) {
-      // Treat this as a script entry, for consistency with Ion.
-      if (script->trackRecordReplayProgress()) {
-        mozilla::recordreplay::AdvanceExecutionProgressCounter();
-      }
-      return false;
-    }
-    return probes::EnterScript(cx, script, nullptr, this);
-  }
-
-  if (isModuleFrame()) {
-    return probes::EnterScript(cx, script, nullptr, this);
-  }
-
-  MOZ_ASSERT(isFunctionFrame());
-
-  // At this point, we've yet to push any environments. Check that they
-  // match the enclosing scope.
-  AssertScopeMatchesEnvironment(script->enclosingScope(), environmentChain());
-
-  if (callee().needsFunctionEnvironmentObjects() &&
-      !initFunctionEnvironmentObjects(cx)) {
-    return false;
-  }
-
-  MOZ_ASSERT_IF(isConstructing(),
-                thisArgument().isObject() ||
-                    thisArgument().isMagic(JS_UNINITIALIZED_LEXICAL));
-
-  return probes::EnterScript(cx, script, script->function(), this);
-}
-
-void InterpreterFrame::epilogue(JSContext* cx, jsbytecode* pc) {
-  RootedScript script(cx, this->script());
-  MOZ_ASSERT(cx->realm() == script->realm());
-  probes::ExitScript(cx, script, script->function(),
-                     hasPushedGeckoProfilerFrame());
-
-  // Check that the scope matches the environment at the point of leaving
-  // the frame.
-  AssertScopeMatchesEnvironment(this, pc);
-
-  EnvironmentIter ei(cx, this, pc);
-  UnwindAllEnvironmentsInFrame(cx, ei);
-
-  if (isFunctionFrame()) {
-    if (!callee().isGenerator() && !callee().isAsync() && isConstructing() &&
-        thisArgument().isObject() && returnValue().isPrimitive()) {
-      setReturnValue(thisArgument());
-    }
-
-    return;
-  }
-
-  MOZ_ASSERT(isEvalFrame() || isGlobalFrame() || isModuleFrame());
-}
-
-bool InterpreterFrame::checkReturn(JSContext* cx, HandleValue thisv) {
-  MOZ_ASSERT(script()->isDerivedClassConstructor());
-  MOZ_ASSERT(isFunctionFrame());
-  MOZ_ASSERT(callee().isClassConstructor());
-
-  HandleValue retVal = returnValue();
-  if (retVal.isObject()) {
-    return true;
-  }
-
-  if (!retVal.isUndefined()) {
-    ReportValueError(cx, JSMSG_BAD_DERIVED_RETURN, JSDVG_IGNORE_STACK, retVal,
-                     nullptr);
-    return false;
-  }
-
-  if (thisv.isMagic(JS_UNINITIALIZED_LEXICAL)) {
-    return ThrowUninitializedThis(cx, this);
-  }
-
-  setReturnValue(thisv);
-  return true;
-}
-
-bool InterpreterFrame::pushVarEnvironment(JSContext* cx, HandleScope scope) {
-  return js::PushVarEnvironmentObject(cx, scope, this);
-}
-
-bool InterpreterFrame::pushLexicalEnvironment(JSContext* cx,
-                                              Handle<LexicalScope*> scope) {
-  LexicalEnvironmentObject* env =
-      LexicalEnvironmentObject::createForFrame(cx, scope, this);
-  if (!env) {
-    return false;
-  }
-
-  pushOnEnvironmentChain(*env);
-  return true;
-}
-
-bool InterpreterFrame::freshenLexicalEnvironment(JSContext* cx) {
-  Rooted<LexicalEnvironmentObject*> env(
-      cx, &envChain_->as<LexicalEnvironmentObject>());
-  LexicalEnvironmentObject* fresh = LexicalEnvironmentObject::clone(cx, env);
-  if (!fresh) {
-    return false;
-  }
-
-  replaceInnermostEnvironment(*fresh);
-  return true;
-}
-
-bool InterpreterFrame::recreateLexicalEnvironment(JSContext* cx) {
-  Rooted<LexicalEnvironmentObject*> env(
-      cx, &envChain_->as<LexicalEnvironmentObject>());
-  LexicalEnvironmentObject* fresh = LexicalEnvironmentObject::recreate(cx, env);
-  if (!fresh) {
-    return false;
-  }
-
-  replaceInnermostEnvironment(*fresh);
-  return true;
-}
-
-void InterpreterFrame::trace(JSTracer* trc, Value* sp, jsbytecode* pc) {
-  TraceRoot(trc, &envChain_, "env chain");
-  TraceRoot(trc, &script_, "script");
-
-  if (flags_ & HAS_ARGS_OBJ) {
-    TraceRoot(trc, &argsObj_, "arguments");
-  }
-
-  if (hasReturnValue()) {
-    TraceRoot(trc, &rval_, "rval");
-  }
-
-  MOZ_ASSERT(sp >= slots());
-
-  if (hasArgs()) {
-    // Trace the callee and |this|. When we're doing a moving GC, we
-    // need to fix up the callee pointer before we use it below, under
-    // numFormalArgs() and script().
-    TraceRootRange(trc, 2, argv_ - 2, "fp callee and this");
-
-    // Trace arguments.
-    unsigned argc = std::max(numActualArgs(), numFormalArgs());
-    TraceRootRange(trc, argc + isConstructing(), argv_, "fp argv");
-  } else {
-    // Trace newTarget.
-    TraceRoot(trc, ((Value*)this) - 1, "stack newTarget");
-  }
-
-  JSScript* script = this->script();
-  size_t nfixed = script->nfixed();
-  size_t nlivefixed = script->calculateLiveFixed(pc);
-
-  if (nfixed == nlivefixed) {
-    // All locals are live.
-    traceValues(trc, 0, sp - slots());
-  } else {
-    // Trace operand stack.
-    traceValues(trc, nfixed, sp - slots());
-
-    // Clear dead block-scoped locals.
-    while (nfixed > nlivefixed) {
-      unaliasedLocal(--nfixed).setUndefined();
-    }
-
-    // Trace live locals.
-    traceValues(trc, 0, nlivefixed);
-  }
-
-  if (auto* debugEnvs = script->realm()->debugEnvs()) {
-    debugEnvs->traceLiveFrame(trc, this);
-  }
-}
-
-void InterpreterFrame::traceValues(JSTracer* trc, unsigned start,
-                                   unsigned end) {
-  if (start < end) {
-    TraceRootRange(trc, end - start, slots() + start, "vm_stack");
-  }
-}
-
-static void TraceInterpreterActivation(JSTracer* trc,
-                                       InterpreterActivation* act) {
-  for (InterpreterFrameIterator frames(act); !frames.done(); ++frames) {
-    InterpreterFrame* fp = frames.frame();
-    fp->trace(trc, frames.sp(), frames.pc());
-  }
-}
-
-void js::TraceInterpreterActivations(JSContext* cx, JSTracer* trc) {
-  for (ActivationIterator iter(cx); !iter.done(); ++iter) {
-    Activation* act = iter.activation();
-    if (act->isInterpreter()) {
-      TraceInterpreterActivation(trc, act->asInterpreter());
-    }
-  }
-}
-
-/*****************************************************************************/
-
-// Unlike the other methods of this class, this method is defined here so that
-// we don't have to #include jsautooplen.h in vm/Stack.h.
-void InterpreterRegs::setToEndOfScript() { sp = fp()->base(); }
-
-/*****************************************************************************/
-
-InterpreterFrame* InterpreterStack::pushInvokeFrame(
-    JSContext* cx, const CallArgs& args, MaybeConstruct constructing) {
-  LifoAlloc::Mark mark = allocator_.mark();
-
-  RootedFunction fun(cx, &args.callee().as<JSFunction>());
-  RootedScript script(cx, fun->nonLazyScript());
-
-  Value* argv;
-  InterpreterFrame* fp = getCallFrame(cx, args, script, constructing, &argv);
-  if (!fp) {
-    return nullptr;
-  }
-
-  fp->mark_ = mark;
-  fp->initCallFrame(nullptr, nullptr, nullptr, *fun, script, argv,
-                    args.length(), constructing);
-  return fp;
-}
-
-InterpreterFrame* InterpreterStack::pushExecuteFrame(
-    JSContext* cx, HandleScript script, const Value& newTargetValue,
-    HandleObject envChain, AbstractFramePtr evalInFrame) {
-  LifoAlloc::Mark mark = allocator_.mark();
-
-  unsigned nvars = 1 /* newTarget */ + script->nslots();
-  uint8_t* buffer =
-      allocateFrame(cx, sizeof(InterpreterFrame) + nvars * sizeof(Value));
-  if (!buffer) {
-    return nullptr;
-  }
-
-  InterpreterFrame* fp =
-      reinterpret_cast<InterpreterFrame*>(buffer + 1 * sizeof(Value));
-  fp->mark_ = mark;
-  fp->initExecuteFrame(cx, script, evalInFrame, newTargetValue, envChain);
-  fp->initLocals();
-
-  return fp;
-}
-
-/*****************************************************************************/
-
-JitFrameIter::JitFrameIter(const JitFrameIter& another) { *this = another; }
-
-JitFrameIter& JitFrameIter::operator=(const JitFrameIter& another) {
-  MOZ_ASSERT(this != &another);
-
-  act_ = another.act_;
-  mustUnwindActivation_ = another.mustUnwindActivation_;
-
-  if (isSome()) {
-    iter_.destroy();
-  }
-  if (!another.isSome()) {
-    return *this;
-  }
-
-  if (another.isJSJit()) {
-    iter_.construct<jit::JSJitFrameIter>(another.asJSJit());
-  } else {
-    MOZ_ASSERT(another.isWasm());
-    iter_.construct<wasm::WasmFrameIter>(another.asWasm());
-  }
-
-  return *this;
-}
-
-JitFrameIter::JitFrameIter(jit::JitActivation* act, bool mustUnwindActivation) {
-  act_ = act;
-  mustUnwindActivation_ = mustUnwindActivation;
-  MOZ_ASSERT(act->hasExitFP(),
-             "packedExitFP is used to determine if JSJit or wasm");
-  if (act->hasJSExitFP()) {
-    iter_.construct<jit::JSJitFrameIter>(act);
-  } else {
-    MOZ_ASSERT(act->hasWasmExitFP());
-    iter_.construct<wasm::WasmFrameIter>(act);
-  }
-  settle();
-}
-
-void JitFrameIter::skipNonScriptedJSFrames() {
-  if (isJSJit()) {
-    // Stop at the first scripted frame.
-    jit::JSJitFrameIter& frames = asJSJit();
-    while (!frames.isScripted() && !frames.done()) {
-      ++frames;
-    }
-    settle();
-  }
-}
-
-bool JitFrameIter::isSelfHostedIgnoringInlining() const {
-  MOZ_ASSERT(!done());
-
-  if (isWasm()) {
-    return false;
-  }
-
-  return asJSJit().script()->selfHosted();
-}
-
-JS::Realm* JitFrameIter::realm() const {
-  MOZ_ASSERT(!done());
-
-  if (isWasm()) {
-    return asWasm().instance()->realm();
-  }
-
-  return asJSJit().script()->realm();
-}
-
-uint8_t* JitFrameIter::resumePCinCurrentFrame() const {
-  if (isWasm()) {
-    return asWasm().resumePCinCurrentFrame();
-  }
-  return asJSJit().resumePCinCurrentFrame();
-}
-
-bool JitFrameIter::done() const {
-  if (!isSome()) {
-    return true;
-  }
-  if (isJSJit()) {
-    return asJSJit().done();
-  }
-  if (isWasm()) {
-    return asWasm().done();
-  }
-  MOZ_CRASH("unhandled case");
-}
-
-void JitFrameIter::settle() {
-  if (isJSJit()) {
-    const jit::JSJitFrameIter& jitFrame = asJSJit();
-    if (jitFrame.type() != jit::FrameType::WasmToJSJit) {
-      return;
-    }
-
-    // Transition from js jit frames to wasm frames: we're on the
-    // wasm-to-jit fast path. The current stack layout is as follows:
-    // (stack grows downward)
-    //
-    // [--------------------]
-    // [WASM FUNC           ]
-    // [WASM JIT EXIT FRAME ]
-    // [JIT WASM ENTRY FRAME] <-- we're here.
-    //
-    // So prevFP points to the wasm jit exit FP, maintaing the invariant in
-    // WasmFrameIter that the first frame is an exit frame and can be
-    // popped.
-
-    wasm::Frame* prevFP = (wasm::Frame*)jitFrame.prevFp();
-
-    if (mustUnwindActivation_) {
-      act_->setWasmExitFP(prevFP);
-    }
-
-    iter_.destroy();
-    iter_.construct<wasm::WasmFrameIter>(act_, prevFP);
-    MOZ_ASSERT(!asWasm().done());
-    return;
-  }
-
-  if (isWasm()) {
-    const wasm::WasmFrameIter& wasmFrame = asWasm();
-    if (!wasmFrame.unwoundIonCallerFP()) {
-      return;
-    }
-
-    // Transition from wasm frames to jit frames: we're on the
-    // jit-to-wasm fast path. The current stack layout is as follows:
-    // (stack grows downward)
-    //
-    // [--------------------]
-    // [JIT FRAME           ]
-    // [WASM JIT ENTRY FRAME] <-- we're here
-    //
-    // The wasm iterator has saved the previous jit frame pointer for us.
-
-    MOZ_ASSERT(wasmFrame.done());
-    uint8_t* prevFP = wasmFrame.unwoundIonCallerFP();
-    jit::FrameType prevFrameType = wasmFrame.unwoundIonFrameType();
-
-    if (mustUnwindActivation_) {
-      act_->setJSExitFP(prevFP);
-    }
-
-    iter_.destroy();
-    iter_.construct<jit::JSJitFrameIter>(act_, prevFrameType, prevFP);
-    MOZ_ASSERT(!asJSJit().done());
-    return;
-  }
-}
-
-void JitFrameIter::operator++() {
-  MOZ_ASSERT(isSome());
-  if (isJSJit()) {
-    const jit::JSJitFrameIter& jitFrame = asJSJit();
-
-    jit::JitFrameLayout* prevFrame = nullptr;
-    if (mustUnwindActivation_ && jitFrame.isScripted()) {
-      prevFrame = jitFrame.jsFrame();
-    }
-
-    ++asJSJit();
-
-    if (prevFrame) {
-      // Unwind the frame by updating packedExitFP. This is necessary
-      // so that (1) debugger exception unwind and leave frame hooks
-      // don't see this frame when they use ScriptFrameIter, and (2)
-      // ScriptFrameIter does not crash when accessing an IonScript
-      // that's destroyed by the ionScript->decref call.
-      EnsureBareExitFrame(act_, prevFrame);
-    }
-  } else if (isWasm()) {
-    ++asWasm();
-  } else {
-    MOZ_CRASH("unhandled case");
-  }
-  settle();
-}
-
-OnlyJSJitFrameIter::OnlyJSJitFrameIter(jit::JitActivation* act)
-    : JitFrameIter(act) {
-  settle();
-}
-
-OnlyJSJitFrameIter::OnlyJSJitFrameIter(JSContext* cx)
-    : OnlyJSJitFrameIter(cx->activation()->asJit()) {}
-
-OnlyJSJitFrameIter::OnlyJSJitFrameIter(const ActivationIterator& iter)
-    : OnlyJSJitFrameIter(iter->asJit()) {}
-
-/*****************************************************************************/
-
-void FrameIter::popActivation() {
-  ++data_.activations_;
-  settleOnActivation();
-}
-
-bool FrameIter::principalsSubsumeFrame() const {
-  // If the caller supplied principals, only show frames which are
-  // subsumed (of the same origin or of an origin accessible) by these
-  // principals.
-
-  MOZ_ASSERT(!done());
-
-  if (!data_.principals_) {
-    return true;
-  }
-
-  JSSubsumesOp subsumes = data_.cx_->runtime()->securityCallbacks->subsumes;
-  if (!subsumes) {
-    return true;
-  }
-
-  JS::AutoSuppressGCAnalysis nogc;
-  return subsumes(data_.principals_, realm()->principals());
-}
-
-void FrameIter::popInterpreterFrame() {
-  MOZ_ASSERT(data_.state_ == INTERP);
-
-  ++data_.interpFrames_;
-
-  if (data_.interpFrames_.done()) {
-    popActivation();
-  } else {
-    data_.pc_ = data_.interpFrames_.pc();
-  }
-}
-
-void FrameIter::settleOnActivation() {
-  MOZ_ASSERT(!data_.cx_->inUnsafeCallWithABI);
-
-  while (true) {
-    if (data_.activations_.done()) {
-      data_.state_ = DONE;
-      return;
-    }
-
-    Activation* activation = data_.activations_.activation();
-
-    if (activation->isJit()) {
-      data_.jitFrames_ = JitFrameIter(activation->asJit());
-      data_.jitFrames_.skipNonScriptedJSFrames();
-      if (data_.jitFrames_.done()) {
-        // It's possible to have an JitActivation with no scripted
-        // frames, for instance if we hit an over-recursion during
-        // bailout.
-        ++data_.activations_;
-        continue;
-      }
-      data_.state_ = JIT;
-      nextJitFrame();
-      return;
-    }
-
-    MOZ_ASSERT(activation->isInterpreter());
-
-    InterpreterActivation* interpAct = activation->asInterpreter();
-    data_.interpFrames_ = InterpreterFrameIterator(interpAct);
-
-    // If we OSR'ed into JIT code, skip the interpreter frame so that
-    // the same frame is not reported twice.
-    if (data_.interpFrames_.frame()->runningInJit()) {
-      ++data_.interpFrames_;
-      if (data_.interpFrames_.done()) {
-        ++data_.activations_;
-        continue;
-      }
-    }
-
-    MOZ_ASSERT(!data_.interpFrames_.frame()->runningInJit());
-    data_.pc_ = data_.interpFrames_.pc();
-    data_.state_ = INTERP;
-    return;
-  }
-}
-
-FrameIter::Data::Data(JSContext* cx, DebuggerEvalOption debuggerEvalOption,
-                      JSPrincipals* principals)
-    : cx_(cx),
-      debuggerEvalOption_(debuggerEvalOption),
-      principals_(principals),
-      state_(DONE),
-      pc_(nullptr),
-      interpFrames_(nullptr),
-      activations_(cx),
-      ionInlineFrameNo_(0) {}
-
-FrameIter::Data::Data(const FrameIter::Data& other)
-    : cx_(other.cx_),
-      debuggerEvalOption_(other.debuggerEvalOption_),
-      principals_(other.principals_),
-      state_(other.state_),
-      pc_(other.pc_),
-      interpFrames_(other.interpFrames_),
-      activations_(other.activations_),
-      jitFrames_(other.jitFrames_),
-      ionInlineFrameNo_(other.ionInlineFrameNo_) {}
-
-FrameIter::FrameIter(JSContext* cx, DebuggerEvalOption debuggerEvalOption)
-    : data_(cx, debuggerEvalOption, nullptr),
-      ionInlineFrames_(cx, (js::jit::JSJitFrameIter*)nullptr) {
-  settleOnActivation();
-
-  // No principals so we can see all frames.
-  MOZ_ASSERT_IF(!done(), principalsSubsumeFrame());
-}
-
-FrameIter::FrameIter(JSContext* cx, DebuggerEvalOption debuggerEvalOption,
-                     JSPrincipals* principals)
-    : data_(cx, debuggerEvalOption, principals),
-      ionInlineFrames_(cx, (js::jit::JSJitFrameIter*)nullptr) {
-  settleOnActivation();
-
-  // If we're not allowed to see this frame, call operator++ to skip this (and
-  // other) cross-origin frames.
-  if (!done() && !principalsSubsumeFrame()) {
-    ++*this;
-  }
-}
-
-FrameIter::FrameIter(const FrameIter& other)
-    : data_(other.data_),
-      ionInlineFrames_(other.data_.cx_,
-                       isIonScripted() ? &other.ionInlineFrames_ : nullptr) {}
-
-FrameIter::FrameIter(const Data& data)
-    : data_(data),
-      ionInlineFrames_(data.cx_, isIonScripted() ? &jsJitFrame() : nullptr) {
-  MOZ_ASSERT(data.cx_);
-  if (isIonScripted()) {
-    while (ionInlineFrames_.frameNo() != data.ionInlineFrameNo_) {
-      ++ionInlineFrames_;
-    }
-  }
-}
-
-void FrameIter::nextJitFrame() {
-  MOZ_ASSERT(data_.jitFrames_.isSome());
-
-  if (isJSJit()) {
-    if (jsJitFrame().isIonScripted()) {
-      ionInlineFrames_.resetOn(&jsJitFrame());
-      data_.pc_ = ionInlineFrames_.pc();
-    } else {
-      MOZ_ASSERT(jsJitFrame().isBaselineJS());
-      jsJitFrame().baselineScriptAndPc(nullptr, &data_.pc_);
-    }
-    return;
-  }
-
-  MOZ_ASSERT(isWasm());
-  data_.pc_ = nullptr;
-}
-
-void FrameIter::popJitFrame() {
-  MOZ_ASSERT(data_.state_ == JIT);
-  MOZ_ASSERT(data_.jitFrames_.isSome());
-
-  if (isJSJit() && jsJitFrame().isIonScripted() && ionInlineFrames_.more()) {
-    ++ionInlineFrames_;
-    data_.pc_ = ionInlineFrames_.pc();
-    return;
-  }
-
-  ++data_.jitFrames_;
-  data_.jitFrames_.skipNonScriptedJSFrames();
-
-  if (!data_.jitFrames_.done()) {
-    nextJitFrame();
-  } else {
-    data_.jitFrames_.reset();
-    popActivation();
-  }
-}
-
-FrameIter& FrameIter::operator++() {
-  while (true) {
-    switch (data_.state_) {
-      case DONE:
-        MOZ_CRASH("Unexpected state");
-      case INTERP:
-        if (interpFrame()->isDebuggerEvalFrame() &&
-            data_.debuggerEvalOption_ == FOLLOW_DEBUGGER_EVAL_PREV_LINK) {
-          AbstractFramePtr eifPrev = interpFrame()->evalInFramePrev();
-
-          popInterpreterFrame();
-
-          while (!hasUsableAbstractFramePtr() ||
-                 abstractFramePtr() != eifPrev) {
-            if (data_.state_ == JIT) {
-              popJitFrame();
-            } else {
-              popInterpreterFrame();
-            }
-          }
-
-          break;
-        }
-        popInterpreterFrame();
-        break;
-      case JIT:
-        popJitFrame();
-        break;
-    }
-
-    if (done() || principalsSubsumeFrame()) {
-      break;
-    }
-  }
-
-  return *this;
-}
-
-FrameIter::Data* FrameIter::copyData() const {
-  Data* data = data_.cx_->new_<Data>(data_);
-  if (!data) {
-    return nullptr;
-  }
-
-  if (data && isIonScripted()) {
-    data->ionInlineFrameNo_ = ionInlineFrames_.frameNo();
-  }
-  return data;
-}
-
-void* FrameIter::rawFramePtr() const {
-  switch (data_.state_) {
-    case DONE:
-      return nullptr;
-    case INTERP:
-      return interpFrame();
-    case JIT:
-      if (isJSJit()) {
-        return jsJitFrame().fp();
-      }
-      MOZ_ASSERT(isWasm());
-      return nullptr;
-  }
-  MOZ_CRASH("Unexpected state");
-}
-
-JS::Compartment* FrameIter::compartment() const {
-  switch (data_.state_) {
-    case DONE:
-      break;
-    case INTERP:
-    case JIT:
-      return data_.activations_->compartment();
-  }
-  MOZ_CRASH("Unexpected state");
-}
-
-Realm* FrameIter::realm() const {
-  MOZ_ASSERT(!done());
-
-  if (hasScript()) {
-    return script()->realm();
-  }
-
-  return wasmInstance()->realm();
-}
-
-bool FrameIter::isEvalFrame() const {
-  switch (data_.state_) {
-    case DONE:
-      break;
-    case INTERP:
-      return interpFrame()->isEvalFrame();
-    case JIT:
-      if (isJSJit()) {
-        if (jsJitFrame().isBaselineJS()) {
-          return jsJitFrame().baselineFrame()->isEvalFrame();
-        }
-        MOZ_ASSERT(!script()->isForEval());
-        return false;
-      }
-      MOZ_ASSERT(isWasm());
-      return false;
-  }
-  MOZ_CRASH("Unexpected state");
-}
-
-bool FrameIter::isFunctionFrame() const {
-  MOZ_ASSERT(!done());
-  switch (data_.state_) {
-    case DONE:
-      break;
-    case INTERP:
-      return interpFrame()->isFunctionFrame();
-    case JIT:
-      if (isJSJit()) {
-        if (jsJitFrame().isBaselineJS()) {
-          return jsJitFrame().baselineFrame()->isFunctionFrame();
-        }
-        return script()->isFunction();
-      }
-      MOZ_ASSERT(isWasm());
-      return false;
-  }
-  MOZ_CRASH("Unexpected state");
-}
-
-JSAtom* FrameIter::maybeFunctionDisplayAtom() const {
-  switch (data_.state_) {
-    case DONE:
-      break;
-    case INTERP:
-    case JIT:
-      if (isWasm()) {
-        return wasmFrame().functionDisplayAtom();
-      }
-      if (isFunctionFrame()) {
-        return calleeTemplate()->displayAtom();
-      }
-      return nullptr;
-  }
-
-  MOZ_CRASH("Unexpected state");
-}
-
-ScriptSource* FrameIter::scriptSource() const {
-  switch (data_.state_) {
-    case DONE:
-      break;
-    case INTERP:
-    case JIT:
-      return script()->scriptSource();
-  }
-
-  MOZ_CRASH("Unexpected state");
-}
-
-const char* FrameIter::filename() const {
-  switch (data_.state_) {
-    case DONE:
-      break;
-    case INTERP:
-    case JIT:
-      if (isWasm()) {
-        return wasmFrame().filename();
-      }
-      return script()->filename();
-  }
-
-  MOZ_CRASH("Unexpected state");
-}
-
-const char16_t* FrameIter::displayURL() const {
-  switch (data_.state_) {
-    case DONE:
-      break;
-    case INTERP:
-    case JIT:
-      if (isWasm()) {
-        return wasmFrame().displayURL();
-      }
-      ScriptSource* ss = script()->scriptSource();
-      return ss->hasDisplayURL() ? ss->displayURL() : nullptr;
-  }
-  MOZ_CRASH("Unexpected state");
-}
-
-unsigned FrameIter::computeLine(uint32_t* column) const {
-  switch (data_.state_) {
-    case DONE:
-      break;
-    case INTERP:
-    case JIT:
-      if (isWasm()) {
-        return wasmFrame().computeLine(column);
-      }
-      return PCToLineNumber(script(), pc(), column);
-  }
-
-  MOZ_CRASH("Unexpected state");
-}
-
-bool FrameIter::mutedErrors() const {
-  switch (data_.state_) {
-    case DONE:
-      break;
-    case INTERP:
-    case JIT:
-      if (isWasm()) {
-        return wasmFrame().mutedErrors();
-      }
-      return script()->mutedErrors();
-  }
-  MOZ_CRASH("Unexpected state");
-}
-
-bool FrameIter::isConstructing() const {
-  switch (data_.state_) {
-    case DONE:
-      break;
-    case JIT:
-      MOZ_ASSERT(isJSJit());
-      if (jsJitFrame().isIonScripted()) {
-        return ionInlineFrames_.isConstructing();
-      }
-      MOZ_ASSERT(jsJitFrame().isBaselineJS());
-      return jsJitFrame().isConstructing();
-    case INTERP:
-      return interpFrame()->isConstructing();
-  }
-
-  MOZ_CRASH("Unexpected state");
-}
-
-bool FrameIter::ensureHasRematerializedFrame(JSContext* cx) {
-  MOZ_ASSERT(isIon());
-  return !!activation()->asJit()->getRematerializedFrame(cx, jsJitFrame());
-}
-
-bool FrameIter::hasUsableAbstractFramePtr() const {
-  switch (data_.state_) {
-    case DONE:
-      return false;
-    case JIT:
-      if (isJSJit()) {
-        if (jsJitFrame().isBaselineJS()) {
-          return true;
-        }
-
-        MOZ_ASSERT(jsJitFrame().isIonScripted());
-        return !!activation()->asJit()->lookupRematerializedFrame(
-            jsJitFrame().fp(), ionInlineFrames_.frameNo());
-      }
-      MOZ_ASSERT(isWasm());
-      return wasmFrame().debugEnabled();
-    case INTERP:
-      return true;
-  }
-  MOZ_CRASH("Unexpected state");
-}
-
-AbstractFramePtr FrameIter::abstractFramePtr() const {
-  MOZ_ASSERT(hasUsableAbstractFramePtr());
-  switch (data_.state_) {
-    case DONE:
-      break;
-    case JIT: {
-      if (isJSJit()) {
-        if (jsJitFrame().isBaselineJS()) {
-          return jsJitFrame().baselineFrame();
-        }
-        MOZ_ASSERT(isIonScripted());
-        return activation()->asJit()->lookupRematerializedFrame(
-            jsJitFrame().fp(), ionInlineFrames_.frameNo());
-      }
-      MOZ_ASSERT(isWasm());
-      MOZ_ASSERT(wasmFrame().debugEnabled());
-      return wasmFrame().debugFrame();
-    }
-    case INTERP:
-      MOZ_ASSERT(interpFrame());
-      return AbstractFramePtr(interpFrame());
-  }
-  MOZ_CRASH("Unexpected state");
-}
-
-void FrameIter::updatePcQuadratic() {
-  switch (data_.state_) {
-    case DONE:
-      break;
-    case INTERP: {
-      InterpreterFrame* frame = interpFrame();
-      InterpreterActivation* activation = data_.activations_->asInterpreter();
-
-      // Look for the current frame.
-      data_.interpFrames_ = InterpreterFrameIterator(activation);
-      while (data_.interpFrames_.frame() != frame) {
-        ++data_.interpFrames_;
-      }
-
-      // Update the pc.
-      MOZ_ASSERT(data_.interpFrames_.frame() == frame);
-      data_.pc_ = data_.interpFrames_.pc();
-      return;
-    }
-    case JIT:
-      if (jsJitFrame().isBaselineJS()) {
-        jit::BaselineFrame* frame = jsJitFrame().baselineFrame();
-        jit::JitActivation* activation = data_.activations_->asJit();
-
-        // activation's exitFP may be invalid, so create a new
-        // activation iterator.
-        data_.activations_ = ActivationIterator(data_.cx_);
-        while (data_.activations_.activation() != activation) {
-          ++data_.activations_;
-        }
-
-        // Look for the current frame.
-        data_.jitFrames_ = JitFrameIter(data_.activations_->asJit());
-        while (!isJSJit() || !jsJitFrame().isBaselineJS() ||
-               jsJitFrame().baselineFrame() != frame) {
-          ++data_.jitFrames_;
-        }
-
-        // Update the pc.
-        MOZ_ASSERT(jsJitFrame().baselineFrame() == frame);
-        jsJitFrame().baselineScriptAndPc(nullptr, &data_.pc_);
-        return;
-      }
-      break;
-  }
-  MOZ_CRASH("Unexpected state");
-}
-
-void FrameIter::wasmUpdateBytecodeOffset() {
-  MOZ_RELEASE_ASSERT(isWasm(), "Unexpected state");
-
-  wasm::DebugFrame* frame = wasmFrame().debugFrame();
-
-  // Relookup the current frame, updating the bytecode offset in the process.
-  data_.jitFrames_ = JitFrameIter(data_.activations_->asJit());
-  while (wasmFrame().debugFrame() != frame) {
-    ++data_.jitFrames_;
-  }
-
-  MOZ_ASSERT(wasmFrame().debugFrame() == frame);
-}
-
-JSFunction* FrameIter::calleeTemplate() const {
-  switch (data_.state_) {
-    case DONE:
-      break;
-    case INTERP:
-      MOZ_ASSERT(isFunctionFrame());
-      return &interpFrame()->callee();
-    case JIT:
-      if (jsJitFrame().isBaselineJS()) {
-        return jsJitFrame().callee();
-      }
-      MOZ_ASSERT(jsJitFrame().isIonScripted());
-      return ionInlineFrames_.calleeTemplate();
-  }
-  MOZ_CRASH("Unexpected state");
-}
-
-JSFunction* FrameIter::callee(JSContext* cx) const {
-  switch (data_.state_) {
-    case DONE:
-      break;
-    case INTERP:
-      return calleeTemplate();
-    case JIT:
-      if (isIonScripted()) {
-        jit::MaybeReadFallback recover(cx, activation()->asJit(),
-                                       &jsJitFrame());
-        return ionInlineFrames_.callee(recover);
-      }
-      MOZ_ASSERT(jsJitFrame().isBaselineJS());
-      return calleeTemplate();
-  }
-  MOZ_CRASH("Unexpected state");
-}
-
-bool FrameIter::matchCallee(JSContext* cx, HandleFunction fun) const {
-  RootedFunction currentCallee(cx, calleeTemplate());
-
-  // As we do not know if the calleeTemplate is the real function, or the
-  // template from which it would be cloned, we compare properties which are
-  // stable across the cloning of JSFunctions.
-  if (((currentCallee->flags().toRaw() ^ fun->flags().toRaw()) &
-       FunctionFlags::STABLE_ACROSS_CLONES) != 0 ||
-      currentCallee->nargs() != fun->nargs()) {
-    return false;
-  }
-
-  // Use the same condition as |js::CloneFunctionObject|, to know if we should
-  // expect both functions to have the same JSScript. If so, and if they are
-  // different, then they cannot be equal.
-  RootedObject global(cx, &fun->global());
-  bool useSameScript =
-      CanReuseScriptForClone(fun->realm(), currentCallee, global);
-  if (useSameScript &&
-      (currentCallee->hasScript() != fun->hasScript() ||
-       currentCallee->nonLazyScript() != fun->nonLazyScript())) {
-    return false;
-  }
-
-  // If none of the previous filters worked, then take the risk of
-  // invalidating the frame to identify the JSFunction.
-  return callee(cx) == fun;
-}
-
-unsigned FrameIter::numActualArgs() const {
-  switch (data_.state_) {
-    case DONE:
-      break;
-    case INTERP:
-      MOZ_ASSERT(isFunctionFrame());
-      return interpFrame()->numActualArgs();
-    case JIT:
-      if (isIonScripted()) {
-        return ionInlineFrames_.numActualArgs();
-      }
-      MOZ_ASSERT(jsJitFrame().isBaselineJS());
-      return jsJitFrame().numActualArgs();
-  }
-  MOZ_CRASH("Unexpected state");
-}
-
-unsigned FrameIter::numFormalArgs() const {
-  return script()->function()->nargs();
-}
-
-Value FrameIter::unaliasedActual(unsigned i,
-                                 MaybeCheckAliasing checkAliasing) const {
-  return abstractFramePtr().unaliasedActual(i, checkAliasing);
-}
-
-JSObject* FrameIter::environmentChain(JSContext* cx) const {
-  switch (data_.state_) {
-    case DONE:
-      break;
-    case JIT:
-      if (isJSJit()) {
-        if (isIonScripted()) {
-          jit::MaybeReadFallback recover(cx, activation()->asJit(),
-                                         &jsJitFrame());
-          return ionInlineFrames_.environmentChain(recover);
-        }
-        return jsJitFrame().baselineFrame()->environmentChain();
-      }
-      MOZ_ASSERT(isWasm());
-      return wasmFrame().debugFrame()->environmentChain();
-    case INTERP:
-      return interpFrame()->environmentChain();
-  }
-  MOZ_CRASH("Unexpected state");
-}
-
-bool FrameIter::hasInitialEnvironment(JSContext* cx) const {
-  if (hasUsableAbstractFramePtr()) {
-    return abstractFramePtr().hasInitialEnvironment();
-  }
-
-  if (isWasm()) {
-    // See JSFunction::needsFunctionEnvironmentObjects().
-    return false;
-  }
-
-  MOZ_ASSERT(isJSJit() && isIonScripted());
-  bool hasInitialEnv = false;
-  jit::MaybeReadFallback recover(cx, activation()->asJit(), &jsJitFrame());
-  ionInlineFrames_.environmentChain(recover, &hasInitialEnv);
-
-  return hasInitialEnv;
-}
-
-CallObject& FrameIter::callObj(JSContext* cx) const {
-  MOZ_ASSERT(calleeTemplate()->needsCallObject());
-  MOZ_ASSERT(hasInitialEnvironment(cx));
-
-  JSObject* pobj = environmentChain(cx);
-  while (!pobj->is<CallObject>()) {
-    pobj = pobj->enclosingEnvironment();
-  }
-  return pobj->as<CallObject>();
-}
-
-bool FrameIter::hasArgsObj() const { return abstractFramePtr().hasArgsObj(); }
-
-ArgumentsObject& FrameIter::argsObj() const {
-  MOZ_ASSERT(hasArgsObj());
-  return abstractFramePtr().argsObj();
-}
-
-Value FrameIter::thisArgument(JSContext* cx) const {
-  MOZ_ASSERT(isFunctionFrame());
-
-  switch (data_.state_) {
-    case DONE:
-      break;
-    case JIT:
-      if (isIonScripted()) {
-        jit::MaybeReadFallback recover(cx, activation()->asJit(),
-                                       &jsJitFrame());
-        return ionInlineFrames_.thisArgument(recover);
-      }
-      return jsJitFrame().baselineFrame()->thisArgument();
-    case INTERP:
-      return interpFrame()->thisArgument();
-  }
-  MOZ_CRASH("Unexpected state");
-}
-
-Value FrameIter::newTarget() const {
-  switch (data_.state_) {
-    case DONE:
-      break;
-    case INTERP:
-      return interpFrame()->newTarget();
-    case JIT:
-      MOZ_ASSERT(jsJitFrame().isBaselineJS());
-      return jsJitFrame().baselineFrame()->newTarget();
-  }
-  MOZ_CRASH("Unexpected state");
-}
-
-Value FrameIter::returnValue() const {
-  switch (data_.state_) {
-    case DONE:
-      break;
-    case JIT:
-      if (jsJitFrame().isBaselineJS()) {
-        return jsJitFrame().baselineFrame()->returnValue();
-      }
-      break;
-    case INTERP:
-      return interpFrame()->returnValue();
-  }
-  MOZ_CRASH("Unexpected state");
-}
-
-void FrameIter::setReturnValue(const Value& v) {
-  switch (data_.state_) {
-    case DONE:
-      break;
-    case JIT:
-      if (jsJitFrame().isBaselineJS()) {
-        jsJitFrame().baselineFrame()->setReturnValue(v);
-        return;
-      }
-      break;
-    case INTERP:
-      interpFrame()->setReturnValue(v);
-      return;
-  }
-  MOZ_CRASH("Unexpected state");
-}
-
-size_t FrameIter::numFrameSlots() const {
-  switch (data_.state_) {
-    case DONE:
-      break;
-    case JIT: {
-      if (isIonScripted()) {
-        return ionInlineFrames_.snapshotIterator().numAllocations() -
-               ionInlineFrames_.script()->nfixed();
-      }
-      uint32_t numValueSlots = jsJitFrame().baselineFrameNumValueSlots();
-      return numValueSlots - jsJitFrame().script()->nfixed();
-    }
-    case INTERP:
-      MOZ_ASSERT(data_.interpFrames_.sp() >= interpFrame()->base());
-      return data_.interpFrames_.sp() - interpFrame()->base();
-  }
-  MOZ_CRASH("Unexpected state");
-}
-
-Value FrameIter::frameSlotValue(size_t index) const {
-  switch (data_.state_) {
-    case DONE:
-      break;
-    case JIT:
-      if (isIonScripted()) {
-        jit::SnapshotIterator si(ionInlineFrames_.snapshotIterator());
-        index += ionInlineFrames_.script()->nfixed();
-        return si.maybeReadAllocByIndex(index);
-      }
-      index += jsJitFrame().script()->nfixed();
-      return *jsJitFrame().baselineFrame()->valueSlot(index);
-    case INTERP:
-      return interpFrame()->base()[index];
-  }
-  MOZ_CRASH("Unexpected state");
-}
-
-#ifdef DEBUG
-bool js::SelfHostedFramesVisible() {
-  static bool checked = false;
-  static bool visible = false;
-  if (!checked) {
-    checked = true;
-    char* env = getenv("MOZ_SHOW_ALL_JS_FRAMES");
-    visible = !!env;
-  }
-  return visible;
-}
-#endif
-
-void NonBuiltinFrameIter::settle() {
-  if (!SelfHostedFramesVisible()) {
-    while (!done() && hasScript() && script()->selfHosted()) {
-      FrameIter::operator++();
-    }
-  }
-}
-
-void NonBuiltinScriptFrameIter::settle() {
-  if (!SelfHostedFramesVisible()) {
-    while (!done() && script()->selfHosted()) {
-      ScriptFrameIter::operator++();
-    }
-  }
-}
+using JS::ObjectOrNullValue;
+using JS::Rooted;
+using JS::UndefinedValue;
+using JS::Value;
 
 Value ActivationEntryMonitor::asyncStack(JSContext* cx) {
-  RootedValue stack(cx, ObjectOrNullValue(cx->asyncStackForNewActivations()));
+  Rooted<Value> stack(cx, ObjectOrNullValue(cx->asyncStackForNewActivations()));
   if (!cx->compartment()->wrap(cx, &stack)) {
     cx->clearPendingException();
     return UndefinedValue();
   }
   return stack;
 }
 
 void ActivationEntryMonitor::init(JSContext* cx, InterpreterFrame* entryFrame) {
   // The InterpreterFrame is not yet part of an Activation, so it won't
   // be traced if we trigger GC here. Suppress GC to avoid this.
   gc::AutoSuppressGC suppressGC(cx);
-  RootedValue stack(cx, asyncStack(cx));
+  Rooted<Value> stack(cx, asyncStack(cx));
   const char* asyncCause = cx->asyncCauseForNewActivations;
   if (entryFrame->isFunctionFrame()) {
     entryMonitor_->Entry(cx, &entryFrame->callee(), stack, asyncCause);
   } else {
     entryMonitor_->Entry(cx, entryFrame->script(), stack, asyncCause);
   }
 }
 
@@ -1487,260 +60,16 @@ void ActivationEntryMonitor::init(JSCont
     entryMonitor_->Entry(cx_, jit::CalleeTokenToFunction(entryToken), stack,
                          asyncCause);
   } else {
     entryMonitor_->Entry(cx_, jit::CalleeTokenToScript(entryToken), stack,
                          asyncCause);
   }
 }
 
-/*****************************************************************************/
-
-jit::JitActivation::JitActivation(JSContext* cx)
-    : Activation(cx, Jit),
-      packedExitFP_(nullptr),
-      encodedWasmExitReason_(0),
-      prevJitActivation_(cx->jitActivation),
-      rematerializedFrames_(),
-      ionRecovery_(cx),
-      bailoutData_(nullptr),
-      lastProfilingFrame_(nullptr),
-      lastProfilingCallSite_(nullptr) {
-  cx->jitActivation = this;
-  registerProfiling();
-}
-
-jit::JitActivation::~JitActivation() {
-  if (isProfiling()) {
-    unregisterProfiling();
-  }
-  cx_->jitActivation = prevJitActivation_;
-
-  // All reocvered value are taken from activation during the bailout.
-  MOZ_ASSERT(ionRecovery_.empty());
-
-  // The BailoutFrameInfo should have unregistered itself from the
-  // JitActivations.
-  MOZ_ASSERT(!bailoutData_);
-
-  // Traps get handled immediately.
-  MOZ_ASSERT(!isWasmTrapping());
-
-  clearRematerializedFrames();
-}
-
-void jit::JitActivation::setBailoutData(jit::BailoutFrameInfo* bailoutData) {
-  MOZ_ASSERT(!bailoutData_);
-  bailoutData_ = bailoutData;
-}
-
-void jit::JitActivation::cleanBailoutData() {
-  MOZ_ASSERT(bailoutData_);
-  bailoutData_ = nullptr;
-}
-
-void jit::JitActivation::removeRematerializedFrame(uint8_t* top) {
-  if (!rematerializedFrames_) {
-    return;
-  }
-
-  if (RematerializedFrameTable::Ptr p = rematerializedFrames_->lookup(top)) {
-    rematerializedFrames_->remove(p);
-  }
-}
-
-void jit::JitActivation::clearRematerializedFrames() {
-  if (!rematerializedFrames_) {
-    return;
-  }
-
-  for (RematerializedFrameTable::Enum e(*rematerializedFrames_); !e.empty();
-       e.popFront()) {
-    e.removeFront();
-  }
-}
-
-jit::RematerializedFrame* jit::JitActivation::getRematerializedFrame(
-    JSContext* cx, const JSJitFrameIter& iter, size_t inlineDepth) {
-  MOZ_ASSERT(iter.activation() == this);
-  MOZ_ASSERT(iter.isIonScripted());
-
-  if (!rematerializedFrames_) {
-    rematerializedFrames_ = cx->make_unique<RematerializedFrameTable>(cx);
-    if (!rematerializedFrames_) {
-      return nullptr;
-    }
-  }
-
-  uint8_t* top = iter.fp();
-  RematerializedFrameTable::AddPtr p = rematerializedFrames_->lookupForAdd(top);
-  if (!p) {
-    RematerializedFrameVector frames(cx);
-
-    // The unit of rematerialization is an uninlined frame and its inlined
-    // frames. Since inlined frames do not exist outside of snapshots, it
-    // is impossible to synchronize their rematerialized copies to
-    // preserve identity. Therefore, we always rematerialize an uninlined
-    // frame and all its inlined frames at once.
-    InlineFrameIterator inlineIter(cx, &iter);
-    MaybeReadFallback recover(cx, this, &iter);
-
-    // Frames are often rematerialized with the cx inside a Debugger's
-    // realm. To recover slots and to create CallObjects, we need to
-    // be in the script's realm.
-    AutoRealmUnchecked ar(cx, iter.script()->realm());
-
-    if (!RematerializedFrame::RematerializeInlineFrames(cx, top, inlineIter,
-                                                        recover, frames)) {
-      return nullptr;
-    }
-
-    if (!rematerializedFrames_->add(p, top, std::move(frames))) {
-      ReportOutOfMemory(cx);
-      return nullptr;
-    }
-
-    // See comment in unsetPrevUpToDateUntil.
-    DebugEnvironments::unsetPrevUpToDateUntil(cx,
-                                              p->value()[inlineDepth].get());
-  }
-
-  return p->value()[inlineDepth].get();
-}
-
-jit::RematerializedFrame* jit::JitActivation::lookupRematerializedFrame(
-    uint8_t* top, size_t inlineDepth) {
-  if (!rematerializedFrames_) {
-    return nullptr;
-  }
-  if (RematerializedFrameTable::Ptr p = rematerializedFrames_->lookup(top)) {
-    return inlineDepth < p->value().length() ? p->value()[inlineDepth].get()
-                                             : nullptr;
-  }
-  return nullptr;
-}
-
-void jit::JitActivation::removeRematerializedFramesFromDebugger(JSContext* cx,
-                                                                uint8_t* top) {
-  // Ion bailout can fail due to overrecursion and OOM. In such cases we
-  // cannot honor any further Debugger hooks on the frame, and need to
-  // ensure that its Debugger.Frame entry is cleaned up.
-  if (!cx->realm()->isDebuggee() || !rematerializedFrames_) {
-    return;
-  }
-  if (RematerializedFrameTable::Ptr p = rematerializedFrames_->lookup(top)) {
-    for (uint32_t i = 0; i < p->value().length(); i++) {
-      DebugAPI::handleUnrecoverableIonBailoutError(cx, p->value()[i].get());
-    }
-    rematerializedFrames_->remove(p);
-  }
-}
-
-void jit::JitActivation::traceRematerializedFrames(JSTracer* trc) {
-  if (!rematerializedFrames_) {
-    return;
-  }
-  for (RematerializedFrameTable::Enum e(*rematerializedFrames_); !e.empty();
-       e.popFront()) {
-    e.front().value().trace(trc);
-  }
-}
-
-bool jit::JitActivation::registerIonFrameRecovery(
-    RInstructionResults&& results) {
-  // Check that there is no entry in the vector yet.
-  MOZ_ASSERT(!maybeIonFrameRecovery(results.frame()));
-  if (!ionRecovery_.append(std::move(results))) {
-    return false;
-  }
-
-  return true;
-}
-
-jit::RInstructionResults* jit::JitActivation::maybeIonFrameRecovery(
-    JitFrameLayout* fp) {
-  for (RInstructionResults* it = ionRecovery_.begin(); it != ionRecovery_.end();
-       it++) {
-    if (it->frame() == fp) {
-      return it;
-    }
-  }
-
-  return nullptr;
-}
-
-void jit::JitActivation::removeIonFrameRecovery(JitFrameLayout* fp) {
-  RInstructionResults* elem = maybeIonFrameRecovery(fp);
-  if (!elem) {
-    return;
-  }
-
-  ionRecovery_.erase(elem);
-}
-
-void jit::JitActivation::traceIonRecovery(JSTracer* trc) {
-  for (RInstructionResults* it = ionRecovery_.begin(); it != ionRecovery_.end();
-       it++) {
-    it->trace(trc);
-  }
-}
-
-void jit::JitActivation::startWasmTrap(wasm::Trap trap, uint32_t bytecodeOffset,
-                                       const wasm::RegisterState& state) {
-  MOZ_ASSERT(!isWasmTrapping());
-
-  bool unwound;
-  wasm::UnwindState unwindState;
-  MOZ_RELEASE_ASSERT(wasm::StartUnwinding(state, &unwindState, &unwound));
-  MOZ_ASSERT(unwound == (trap == wasm::Trap::IndirectCallBadSig));
-
-  void* pc = unwindState.pc;
-  wasm::Frame* fp = unwindState.fp;
-
-  const wasm::Code& code = fp->tls->instance->code();
-  MOZ_RELEASE_ASSERT(&code == wasm::LookupCode(pc));
-
-  // If the frame was unwound, the bytecodeOffset must be recovered from the
-  // callsite so that it is accurate.
-  if (unwound) {
-    bytecodeOffset = code.lookupCallSite(pc)->lineOrBytecode();
-  }
-
-  setWasmExitFP(fp);
-  wasmTrapData_.emplace();
-  wasmTrapData_->resumePC =
-      ((uint8_t*)state.pc) + jit::WasmTrapInstructionLength;
-  wasmTrapData_->unwoundPC = pc;
-  wasmTrapData_->trap = trap;
-  wasmTrapData_->bytecodeOffset = bytecodeOffset;
-
-  MOZ_ASSERT(isWasmTrapping());
-}
-
-void jit::JitActivation::finishWasmTrap() {
-  MOZ_ASSERT(isWasmTrapping());
-  packedExitFP_ = nullptr;
-  wasmTrapData_.reset();
-  MOZ_ASSERT(!isWasmTrapping());
-}
-
-InterpreterFrameIterator& InterpreterFrameIterator::operator++() {
-  MOZ_ASSERT(!done());
-  if (fp_ != activation_->entryFrame_) {
-    pc_ = fp_->prevpc();
-    sp_ = fp_->prevsp();
-    fp_ = fp_->prev();
-  } else {
-    pc_ = nullptr;
-    sp_ = nullptr;
-    fp_ = nullptr;
-  }
-  return *this;
-}
-
 void Activation::registerProfiling() {
   MOZ_ASSERT(isProfiling());
   cx_->profilingActivation_ = this;
 }
 
 void Activation::unregisterProfiling() {
   MOZ_ASSERT(isProfiling());
   MOZ_ASSERT(cx_->profilingActivation_ == this);
@@ -1752,299 +81,8 @@ ActivationIterator::ActivationIterator(J
   MOZ_ASSERT(cx == TlsContext.get());
 }
 
 ActivationIterator& ActivationIterator::operator++() {
   MOZ_ASSERT(activation_);
   activation_ = activation_->prev();
   return *this;
 }
-
-JS::ProfilingFrameIterator::ProfilingFrameIterator(
-    JSContext* cx, const RegisterState& state,
-    const Maybe<uint64_t>& samplePositionInProfilerBuffer)
-    : cx_(cx),
-      samplePositionInProfilerBuffer_(samplePositionInProfilerBuffer),
-      activation_(nullptr) {
-  if (!cx->runtime()->geckoProfiler().enabled()) {
-    MOZ_CRASH(
-        "ProfilingFrameIterator called when geckoProfiler not enabled for "
-        "runtime.");
-  }
-
-  if (!cx->profilingActivation()) {
-    return;
-  }
-
-  // If profiler sampling is not enabled, skip.
-  if (!cx->isProfilerSamplingEnabled()) {
-    return;
-  }
-
-  activation_ = cx->profilingActivation();
-
-  MOZ_ASSERT(activation_->isProfiling());
-
-  static_assert(sizeof(wasm::ProfilingFrameIterator) <= StorageSpace &&
-                    sizeof(jit::JSJitProfilingFrameIterator) <= StorageSpace,
-                "ProfilingFrameIterator::storage_ is too small");
-  static_assert(alignof(void*) >= alignof(wasm::ProfilingFrameIterator) &&
-                    alignof(void*) >= alignof(jit::JSJitProfilingFrameIterator),
-                "ProfilingFrameIterator::storage_ is too weakly aligned");
-
-  iteratorConstruct(state);
-  settle();
-}
-
-JS::ProfilingFrameIterator::~ProfilingFrameIterator() {
-  if (!done()) {
-    MOZ_ASSERT(activation_->isProfiling());
-    iteratorDestroy();
-  }
-}
-
-void JS::ProfilingFrameIterator::operator++() {
-  MOZ_ASSERT(!done());
-  MOZ_ASSERT(activation_->isJit());
-  if (isWasm()) {
-    ++wasmIter();
-  } else {
-    ++jsJitIter();
-  }
-  settle();
-}
-
-void JS::ProfilingFrameIterator::settleFrames() {
-  // Handle transition frames (see comment in JitFrameIter::operator++).
-  if (isJSJit() && !jsJitIter().done() &&
-      jsJitIter().frameType() == jit::FrameType::WasmToJSJit) {
-    wasm::Frame* fp = (wasm::Frame*)jsJitIter().fp();
-    iteratorDestroy();
-    new (storage()) wasm::ProfilingFrameIterator(fp);
-    kind_ = Kind::Wasm;
-    MOZ_ASSERT(!wasmIter().done());
-    return;
-  }
-
-  if (isWasm() && wasmIter().done() && wasmIter().unwoundIonCallerFP()) {
-    uint8_t* fp = wasmIter().unwoundIonCallerFP();
-    iteratorDestroy();
-    // Using this ctor will skip the first ion->wasm frame, which is
-    // needed because the profiling iterator doesn't know how to unwind
-    // when the callee has no script.
-    new (storage())
-        jit::JSJitProfilingFrameIterator((jit::CommonFrameLayout*)fp);
-    kind_ = Kind::JSJit;
-    MOZ_ASSERT(!jsJitIter().done());
-    return;
-  }
-}
-
-void JS::ProfilingFrameIterator::settle() {
-  settleFrames();
-  while (iteratorDone()) {
-    iteratorDestroy();
-    activation_ = activation_->prevProfiling();
-    if (!activation_) {
-      return;
-    }
-    iteratorConstruct();
-    settleFrames();
-  }
-}
-
-void JS::ProfilingFrameIterator::iteratorConstruct(const RegisterState& state) {
-  MOZ_ASSERT(!done());
-  MOZ_ASSERT(activation_->isJit());
-
-  jit::JitActivation* activation = activation_->asJit();
-
-  // We want to know if we should start with a wasm profiling frame iterator
-  // or not. To determine this, there are three possibilities:
-  // - we've exited to C++ from wasm, in which case the activation
-  //   exitFP low bit is tagged and we can test hasWasmExitFP().
-  // - we're in wasm code, so we can do a lookup on PC.
-  // - in all the other cases, we're not in wasm or we haven't exited from
-  //   wasm.
-  if (activation->hasWasmExitFP() || wasm::InCompiledCode(state.pc)) {
-    new (storage()) wasm::ProfilingFrameIterator(*activation, state);
-    kind_ = Kind::Wasm;
-    return;
-  }
-
-  new (storage()) jit::JSJitProfilingFrameIterator(cx_, state.pc);
-  kind_ = Kind::JSJit;
-}
-
-void JS::ProfilingFrameIterator::iteratorConstruct() {
-  MOZ_ASSERT(!done());
-  MOZ_ASSERT(activation_->isJit());
-
-  jit::JitActivation* activation = activation_->asJit();
-
-  // The same reasoning as in the above iteratorConstruct variant applies
-  // here, except that it's even simpler: since this activation is higher up
-  // on the stack, it can only have exited to C++, through wasm or ion.
-  if (activation->hasWasmExitFP()) {
-    new (storage()) wasm::ProfilingFrameIterator(*activation);
-    kind_ = Kind::Wasm;
-    return;
-  }
-
-  auto* fp = (jit::ExitFrameLayout*)activation->jsExitFP();
-  new (storage()) jit::JSJitProfilingFrameIterator(fp);
-  kind_ = Kind::JSJit;
-}
-
-void JS::ProfilingFrameIterator::iteratorDestroy() {
-  MOZ_ASSERT(!done());
-  MOZ_ASSERT(activation_->isJit());
-
-  if (isWasm()) {
-    wasmIter().~ProfilingFrameIterator();
-    return;
-  }
-
-  jsJitIter().~JSJitProfilingFrameIterator();
-}
-
-bool JS::ProfilingFrameIterator::iteratorDone() {
-  MOZ_ASSERT(!done());
-  MOZ_ASSERT(activation_->isJit());
-
-  if (isWasm()) {
-    return wasmIter().done();
-  }
-
-  return jsJitIter().done();
-}
-
-void* JS::ProfilingFrameIterator::stackAddress() const {
-  MOZ_ASSERT(!done());
-  MOZ_ASSERT(activation_->isJit());
-
-  if (isWasm()) {
-    return wasmIter().stackAddress();
-  }
-
-  return jsJitIter().stackAddress();
-}
-
-Maybe<JS::ProfilingFrameIterator::Frame>
-JS::ProfilingFrameIterator::getPhysicalFrameAndEntry(
-    jit::JitcodeGlobalEntry* entry) const {
-  void* stackAddr = stackAddress();
-
-  if (isWasm()) {
-    Frame frame;
-    frame.kind = Frame_Wasm;
-    frame.stackAddress = stackAddr;
-    frame.returnAddress_ = nullptr;
-    frame.activation = activation_;
-    frame.label = nullptr;
-    frame.endStackAddress = activation_->asJit()->jsOrWasmExitFP();
-    frame.interpreterScript = nullptr;
-    return mozilla::Some(frame);
-  }
-
-  MOZ_ASSERT(isJSJit());
-
-  // Look up an entry for the return address.
-  void* returnAddr = jsJitIter().resumePCinCurrentFrame();
-  jit::JitcodeGlobalTable* table =
-      cx_->runtime()->jitRuntime()->getJitcodeGlobalTable();
-  if (samplePositionInProfilerBuffer_) {
-    *entry = table->lookupForSamplerInfallible(
-        returnAddr, cx_->runtime(), *samplePositionInProfilerBuffer_);
-  } else {
-    *entry = table->lookupInfallible(returnAddr);
-  }
-
-  MOZ_ASSERT(entry->isIon() || entry->isIonCache() || entry->isBaseline() ||
-             entry->isBaselineInterpreter() || entry->isDummy());
-
-  // Dummy frames produce no stack frames.
-  if (entry->isDummy()) {
-    return mozilla::Nothing();
-  }
-
-  Frame frame;
-  if (entry->isBaselineInterpreter()) {
-    frame.kind = Frame_BaselineInterpreter;
-  } else if (entry->isBaseline()) {
-    frame.kind = Frame_Baseline;
-  } else {
-    frame.kind = Frame_Ion;
-  }
-  frame.stackAddress = stackAddr;
-  if (entry->isBaselineInterpreter()) {
-    frame.label = jsJitIter().baselineInterpreterLabel();
-    jsJitIter().baselineInterpreterScriptPC(&frame.interpreterScript,
-                                            &frame.interpreterPC_);
-    MOZ_ASSERT(frame.interpreterScript);
-    MOZ_ASSERT(frame.interpreterPC_);
-  } else {
-    frame.interpreterScript = nullptr;
-    frame.returnAddress_ = returnAddr;
-    frame.label = nullptr;
-  }
-  frame.activation = activation_;
-  frame.endStackAddress = activation_->asJit()->jsOrWasmExitFP();
-  return mozilla::Some(frame);
-}
-
-uint32_t JS::ProfilingFrameIterator::extractStack(Frame* frames,
-                                                  uint32_t offset,
-                                                  uint32_t end) const {
-  if (offset >= end) {
-    return 0;
-  }
-
-  jit::JitcodeGlobalEntry entry;
-  Maybe<Frame> physicalFrame = getPhysicalFrameAndEntry(&entry);
-
-  // Dummy frames produce no stack frames.
-  if (physicalFrame.isNothing()) {
-    return 0;
-  }
-
-  if (isWasm()) {
-    frames[offset] = physicalFrame.value();
-    frames[offset].label = wasmIter().label();
-    return 1;
-  }
-
-  if (physicalFrame->kind == Frame_BaselineInterpreter) {
-    frames[offset] = physicalFrame.value();
-    return 1;
-  }
-
-  // Extract the stack for the entry.  Assume maximum inlining depth is <64
-  const char* labels[64];
-  uint32_t depth = entry.callStackAtAddr(cx_->runtime(),
-                                         jsJitIter().resumePCinCurrentFrame(),
-                                         labels, ArrayLength(labels));
-  MOZ_ASSERT(depth < ArrayLength(labels));
-  for (uint32_t i = 0; i < depth; i++) {
-    if (offset + i >= end) {
-      return i;
-    }
-    frames[offset + i] = physicalFrame.value();
-    frames[offset + i].label = labels[i];
-  }
-
-  return depth;
-}
-
-Maybe<JS::ProfilingFrameIterator::Frame>
-JS::ProfilingFrameIterator::getPhysicalFrameWithoutLabel() const {
-  jit::JitcodeGlobalEntry unused;
-  return getPhysicalFrameAndEntry(&unused);
-}
-
-bool JS::ProfilingFrameIterator::isWasm() const {
-  MOZ_ASSERT(!done());
-  return kind_ == Kind::Wasm;
-}
-
-bool JS::ProfilingFrameIterator::isJSJit() const {
-  return kind_ == Kind::JSJit;
-}
copy from js/src/vm/Stack.h
copy to js/src/vm/Activation.h
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Activation.h
@@ -1,1052 +1,86 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * vim: set ts=8 sts=2 et sw=2 tw=80:
  * 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 vm_Stack_h
-#define vm_Stack_h
+#ifndef vm_Activation_h
+#define vm_Activation_h
 
-#include "mozilla/Atomics.h"
-#include "mozilla/HashFunctions.h"
-#include "mozilla/Maybe.h"
-#include "mozilla/MaybeOneOf.h"
-#include "mozilla/MemoryReporting.h"
-#include "mozilla/Variant.h"
+#include "mozilla/Assertions.h"  // MOZ_ASSERT
+#include "mozilla/Attributes.h"  // MOZ_RAII
 
-#include <algorithm>
+#include <stddef.h>  // size_t
+#include <stdint.h>  // uint8_t, uint32_t
+
+#include "jstypes.h"  // JS_PUBLIC_API
 
-#include "gc/Rooting.h"
-#ifdef CHECK_OSIPOINT_REGISTERS
-#  include "jit/Registers.h"  // for RegisterDump
-#endif
-#include "jit/JSJitFrameIter.h"
-#include "js/RootingAPI.h"
-#include "js/TypeDecls.h"
-#include "js/UniquePtr.h"
-#include "vm/ArgumentsObject.h"
-#include "vm/JSFunction.h"
-#include "vm/JSScript.h"
-#include "vm/SavedFrame.h"
-#include "wasm/WasmFrameIter.h"
+#include "jit/JSJitFrameIter.h"  // js::jit::CalleeToken
+#include "js/CallArgs.h"  // JS::CallArgs
+#include "js/RootingAPI.h"  // JS::Handle, JS::Rooted
+#include "js/TypeDecls.h"  // jsbytecode
+#include "js/UniquePtr.h"  // js::UniquePtr
+#include "js/Value.h"  // JS::Value
+#include "vm/SavedFrame.h"  // js::SavedFrame
+#include "vm/Stack.h"  // js::InterpreterRegs
+
+struct JS_PUBLIC_API JSContext;
+
+class JSFunction;
+class JSObject;
+class JSScript;
 
 namespace JS {
+
+class JS_PUBLIC_API Compartment;
+
 namespace dbg {
 class JS_PUBLIC_API AutoEntryMonitor;
 }  // namespace dbg
+
 }  // namespace JS
 
 namespace js {
 
-class InterpreterRegs;
-class CallObject;
-class FrameIter;
-class EnvironmentObject;
-class ScriptFrameIter;
-class GeckoProfilerRuntime;
+class InterpreterActivation;
 class InterpreterFrame;
-class LexicalEnvironmentObject;
-class EnvironmentIter;
-class EnvironmentCoordinate;
-
-class SavedFrame;
 
 namespace jit {
-class CommonFrameLayout;
-}
-namespace wasm {
-class DebugFrame;
-class Instance;
-}  // namespace wasm
-
-// [SMDOC] VM stack layout
-//
-// A JSRuntime's stack consists of a linked list of activations. Every
-// activation contains a number of scripted frames that are either running in
-// the interpreter (InterpreterActivation) or JIT code (JitActivation). The
-// frames inside a single activation are contiguous: whenever C++ calls back
-// into JS, a new activation is pushed.
-//
-// Every activation is tied to a single JSContext and JS::Compartment. This
-// means we can reconstruct a given context's stack by skipping activations
-// belonging to other contexts. This happens whenever an embedding enters the JS
-// engine on cx1 and then, from a native called by the JS engine, reenters the
-// VM on cx2.
-
-// Interpreter frames (InterpreterFrame)
-//
-// Each interpreter script activation (global or function code) is given a
-// fixed-size header (js::InterpreterFrame). The frame contains bookkeeping
-// information about the activation and links to the previous frame.
-//
-// The values after an InterpreterFrame in memory are its locals followed by its
-// expression stack. InterpreterFrame::argv_ points to the frame's arguments.
-// Missing formal arguments are padded with |undefined|, so the number of
-// arguments is always >= the number of formals.
-//
-// The top of an activation's current frame's expression stack is pointed to by
-// the activation's "current regs", which contains the stack pointer 'sp'. In
-// the interpreter, sp is adjusted as individual values are pushed and popped
-// from the stack and the InterpreterRegs struct (pointed to by the
-// InterpreterActivation) is a local var of js::Interpret.
-
-enum MaybeCheckAliasing { CHECK_ALIASING = true, DONT_CHECK_ALIASING = false };
-enum MaybeCheckTDZ { CheckTDZ = true, DontCheckTDZ = false };
-
-}  // namespace js
-
-namespace mozilla {
-template <>
-struct IsPod<js::MaybeCheckTDZ> : TrueType {};
-}  // namespace mozilla
-
-/*****************************************************************************/
-
-namespace js {
-
-namespace jit {
-class BaselineFrame;
-class RematerializedFrame;
+class JitActivation;
+class JitFrameLayout;
 }  // namespace jit
 
-/**
- * Pointer to a live JS or WASM stack frame.
- */
-class AbstractFramePtr {
-  friend class FrameIter;
-
-  uintptr_t ptr_;
-
-  enum {
-    Tag_InterpreterFrame = 0x1,
-    Tag_BaselineFrame = 0x2,
-    Tag_RematerializedFrame = 0x3,
-    Tag_WasmDebugFrame = 0x4,
-    TagMask = 0x7
-  };
-
- public:
-  AbstractFramePtr() : ptr_(0) {}
-
-  MOZ_IMPLICIT AbstractFramePtr(InterpreterFrame* fp)
-      : ptr_(fp ? uintptr_t(fp) | Tag_InterpreterFrame : 0) {
-    MOZ_ASSERT_IF(fp, asInterpreterFrame() == fp);
-  }
-
-  MOZ_IMPLICIT AbstractFramePtr(jit::BaselineFrame* fp)
-      : ptr_(fp ? uintptr_t(fp) | Tag_BaselineFrame : 0) {
-    MOZ_ASSERT_IF(fp, asBaselineFrame() == fp);
-  }
-
-  MOZ_IMPLICIT AbstractFramePtr(jit::RematerializedFrame* fp)
-      : ptr_(fp ? uintptr_t(fp) | Tag_RematerializedFrame : 0) {
-    MOZ_ASSERT_IF(fp, asRematerializedFrame() == fp);
-  }
-
-  MOZ_IMPLICIT AbstractFramePtr(wasm::DebugFrame* fp)
-      : ptr_(fp ? uintptr_t(fp) | Tag_WasmDebugFrame : 0) {
-    static_assert(wasm::DebugFrame::Alignment >= TagMask, "aligned");
-    MOZ_ASSERT_IF(fp, asWasmDebugFrame() == fp);
-  }
-
-  static AbstractFramePtr FromRaw(void* raw) {
-    AbstractFramePtr frame;
-    frame.ptr_ = uintptr_t(raw);
-    return frame;
-  }
+// This class is separate from Activation, because it calls Compartment::wrap()
+// which can GC and walk the stack. It's not safe to do that within the
+// JitActivation constructor.
+class MOZ_RAII ActivationEntryMonitor {
+  JSContext* cx_;
 
-  bool isInterpreterFrame() const {
-    return (ptr_ & TagMask) == Tag_InterpreterFrame;
-  }
-  InterpreterFrame* asInterpreterFrame() const {
-    MOZ_ASSERT(isInterpreterFrame());
-    InterpreterFrame* res = (InterpreterFrame*)(ptr_ & ~TagMask);
-    MOZ_ASSERT(res);
-    return res;
-  }
-  bool isBaselineFrame() const { return (ptr_ & TagMask) == Tag_BaselineFrame; }
-  jit::BaselineFrame* asBaselineFrame() const {
-    MOZ_ASSERT(isBaselineFrame());
-    jit::BaselineFrame* res = (jit::BaselineFrame*)(ptr_ & ~TagMask);
-    MOZ_ASSERT(res);
-    return res;
-  }
-  bool isRematerializedFrame() const {
-    return (ptr_ & TagMask) == Tag_RematerializedFrame;
-  }
-  jit::RematerializedFrame* asRematerializedFrame() const {
-    MOZ_ASSERT(isRematerializedFrame());
-    jit::RematerializedFrame* res =
-        (jit::RematerializedFrame*)(ptr_ & ~TagMask);
-    MOZ_ASSERT(res);
-    return res;
-  }
-  bool isWasmDebugFrame() const {
-    return (ptr_ & TagMask) == Tag_WasmDebugFrame;
-  }
-  wasm::DebugFrame* asWasmDebugFrame() const {
-    MOZ_ASSERT(isWasmDebugFrame());
-    wasm::DebugFrame* res = (wasm::DebugFrame*)(ptr_ & ~TagMask);
-    MOZ_ASSERT(res);
-    return res;
-  }
-
-  void* raw() const { return reinterpret_cast<void*>(ptr_); }
-
-  bool operator==(const AbstractFramePtr& other) const {
-    return ptr_ == other.ptr_;
-  }
-  bool operator!=(const AbstractFramePtr& other) const {
-    return ptr_ != other.ptr_;
-  }
-
-  explicit operator bool() const { return !!ptr_; }
-
-  inline JSObject* environmentChain() const;
-  inline CallObject& callObj() const;
-  inline bool initFunctionEnvironmentObjects(JSContext* cx);
-  inline bool pushVarEnvironment(JSContext* cx, HandleScope scope);
-  template <typename SpecificEnvironment>
-  inline void pushOnEnvironmentChain(SpecificEnvironment& env);
-  template <typename SpecificEnvironment>
-  inline void popOffEnvironmentChain();
-
-  inline JS::Realm* realm() const;
-
-  inline bool hasInitialEnvironment() const;
-  inline bool isGlobalFrame() const;
-  inline bool isModuleFrame() const;
-  inline bool isEvalFrame() const;
-  inline bool isDebuggerEvalFrame() const;
-
-  inline bool hasScript() const;
-  inline JSScript* script() const;
-  inline wasm::Instance* wasmInstance() const;
-  inline GlobalObject* global() const;
-  inline bool hasGlobal(const GlobalObject* global) const;
-  inline JSFunction* callee() const;
-  inline Value calleev() const;
-  inline Value& thisArgument() const;
-
-  inline bool isConstructing() const;
-  inline Value newTarget() const;
-
-  inline bool debuggerNeedsCheckPrimitiveReturn() const;
-
-  inline bool isFunctionFrame() const;
-  inline bool isGeneratorFrame() const;
-  inline bool isNonStrictDirectEvalFrame() const;
-  inline bool isStrictEvalFrame() const;
-
-  inline unsigned numActualArgs() const;
-  inline unsigned numFormalArgs() const;
-
-  inline Value* argv() const;
+  // The entry point monitor that was set on cx_->runtime() when this
+  // ActivationEntryMonitor was created.
+  JS::dbg::AutoEntryMonitor* entryMonitor_;
 
-  inline bool hasArgs() const;
-  inline bool hasArgsObj() const;
-  inline ArgumentsObject& argsObj() const;
-  inline void initArgsObj(ArgumentsObject& argsobj) const;
-
-  inline Value& unaliasedLocal(uint32_t i);
-  inline Value& unaliasedFormal(
-      unsigned i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING);
-  inline Value& unaliasedActual(
-      unsigned i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING);
-  template <class Op>
-  inline void unaliasedForEachActual(JSContext* cx, Op op);
-
-  inline bool prevUpToDate() const;
-  inline void setPrevUpToDate() const;
-  inline void unsetPrevUpToDate() const;
-
-  inline bool isDebuggee() const;
-  inline void setIsDebuggee();
-  inline void unsetIsDebuggee();
-
-  inline HandleValue returnValue() const;
-  inline void setReturnValue(const Value& rval) const;
-
-  friend void GDBTestInitAbstractFramePtr(AbstractFramePtr&, InterpreterFrame*);
-  friend void GDBTestInitAbstractFramePtr(AbstractFramePtr&,
-                                          jit::BaselineFrame*);
-  friend void GDBTestInitAbstractFramePtr(AbstractFramePtr&,
-                                          jit::RematerializedFrame*);
-  friend void GDBTestInitAbstractFramePtr(AbstractFramePtr& frame,
-                                          wasm::DebugFrame* ptr);
-};
+  explicit inline ActivationEntryMonitor(JSContext* cx);
 
-class NullFramePtr : public AbstractFramePtr {
- public:
-  NullFramePtr() : AbstractFramePtr() {}
-};
-
-enum MaybeConstruct { NO_CONSTRUCT = false, CONSTRUCT = true };
-
-/*****************************************************************************/
-
-class InterpreterFrame {
-  enum Flags : uint32_t {
-    CONSTRUCTING = 0x1, /* frame is for a constructor invocation */
-
-    RESUMED_GENERATOR = 0x2, /* frame is for a resumed generator invocation */
-
-    /* Function prologue state */
-    HAS_INITIAL_ENV =
-        0x4,            /* callobj created for function or var env for eval */
-    HAS_ARGS_OBJ = 0x8, /* ArgumentsObject created for needsArgsObj script */
-
-    /* Lazy frame initialization */
-    HAS_RVAL = 0x10, /* frame has rval_ set */
-
-    /* Debugger state */
-    PREV_UP_TO_DATE = 0x20, /* see DebugScopes::updateLiveScopes */
-
-    /*
-     * See comment above 'isDebuggee' in Realm.h for explanation of
-     * invariants of debuggee compartments, scripts, and frames.
-     */
-    DEBUGGEE = 0x40, /* Execution is being observed by Debugger */
-
-    /* Used in tracking calls and profiling (see vm/GeckoProfiler.cpp) */
-    HAS_PUSHED_PROF_FRAME = 0x80, /* Gecko Profiler was notified of entry */
+  ActivationEntryMonitor(const ActivationEntryMonitor& other) = delete;
+  void operator=(const ActivationEntryMonitor& other) = delete;
 
-    /*
-     * If set, we entered one of the JITs and ScriptFrameIter should skip
-     * this frame.
-     */
-    RUNNING_IN_JIT = 0x100,
-
-    /*
-     * If set, this frame has been on the stack when
-     * |js::SavedStacks::saveCurrentStack| was called, and so there is a
-     * |js::SavedFrame| object cached for this frame.
-     */
-    HAS_CACHED_SAVED_FRAME = 0x200,
-  };
-
-  mutable uint32_t flags_; /* bits described by Flags */
-  uint32_t nactual_;       /* number of actual arguments, for function frames */
-  JSScript* script_;       /* the script we're executing */
-  JSObject* envChain_;     /* current environment chain */
-  Value rval_;             /* if HAS_RVAL, return value of the frame */
-  ArgumentsObject* argsObj_; /* if HAS_ARGS_OBJ, the call's arguments object */
-
-  /*
-   * Previous frame and its pc and sp. Always nullptr for
-   * InterpreterActivation's entry frame, always non-nullptr for inline
-   * frames.
-   */
-  InterpreterFrame* prev_;
-  jsbytecode* prevpc_;
-  Value* prevsp_;
-
-  void* unused;
+  void init(JSContext* cx, jit::CalleeToken entryToken);
+  void init(JSContext* cx, InterpreterFrame* entryFrame);
 
-  /*
-   * For an eval-in-frame DEBUGGER_EVAL frame, the frame in whose scope
-   * we're evaluating code. Iteration treats this as our previous frame.
-   */
-  AbstractFramePtr evalInFramePrev_;
-
-  Value* argv_;          /* If hasArgs(), points to frame's arguments. */
-  LifoAlloc::Mark mark_; /* Used to release memory for this frame. */
-
-  static void staticAsserts() {
-    JS_STATIC_ASSERT(offsetof(InterpreterFrame, rval_) % sizeof(Value) == 0);
-    JS_STATIC_ASSERT(sizeof(InterpreterFrame) % sizeof(Value) == 0);
-  }
-
-  /*
-   * The utilities are private since they are not able to assert that only
-   * unaliased vars/formals are accessed. Normal code should prefer the
-   * InterpreterFrame::unaliased* members (or InterpreterRegs::stackDepth for
-   * the usual "depth is at least" assertions).
-   */
-  Value* slots() const { return (Value*)(this + 1); }
-  Value* base() const { return slots() + script()->nfixed(); }
-
-  friend class FrameIter;
-  friend class InterpreterRegs;
-  friend class InterpreterStack;
-  friend class jit::BaselineFrame;
-
-  /*
-   * Frame initialization, called by InterpreterStack operations after acquiring
-   * the raw memory for the frame:
-   */
-
-  /* Used for Invoke and Interpret. */
-  void initCallFrame(InterpreterFrame* prev, jsbytecode* prevpc, Value* prevsp,
-                     JSFunction& callee, JSScript* script, Value* argv,
-                     uint32_t nactual, MaybeConstruct constructing);
-
-  /* Used for global and eval frames. */
-  void initExecuteFrame(JSContext* cx, HandleScript script,
-                        AbstractFramePtr prev, const Value& newTargetValue,
-                        HandleObject envChain);
+  JS::Value asyncStack(JSContext* cx);
 
  public:
-  /*
-   * Frame prologue/epilogue
-   *
-   * Every stack frame must have 'prologue' called before executing the
-   * first op and 'epilogue' called after executing the last op and before
-   * popping the frame (whether the exit is exceptional or not).
-   *
-   * For inline JS calls/returns, it is easy to call the prologue/epilogue
-   * exactly once. When calling JS from C++, Invoke/Execute push the stack
-   * frame but do *not* call the prologue/epilogue. That means Interpret
-   * must call the prologue/epilogue for the entry frame. This scheme
-   * simplifies jit compilation.
-   *
-   * An important corner case is what happens when an error occurs (OOM,
-   * over-recursed) after pushing the stack frame but before 'prologue' is
-   * called or completes fully. To simplify usage, 'epilogue' does not assume
-   * 'prologue' has completed and handles all the intermediate state details.
-   */
-
-  bool prologue(JSContext* cx);
-  void epilogue(JSContext* cx, jsbytecode* pc);
-
-  bool checkReturn(JSContext* cx, HandleValue thisv);
-
-  bool initFunctionEnvironmentObjects(JSContext* cx);
-
-  /*
-   * Initialize locals of newly-pushed frame to undefined.
-   */
-  void initLocals();
-
-  /*
-   * Stack frame type
-   *
-   * A stack frame may have one of four types, which determines which
-   * members of the frame may be accessed and other invariants:
-   *
-   *  global frame:   execution of global code
-   *  function frame: execution of function code
-   *  module frame:   execution of a module
-   *  eval frame:     execution of eval code
-   */
-
-  bool isGlobalFrame() const { return script_->isGlobalCode(); }
-
-  bool isModuleFrame() const { return script_->isModule(); }
-
-  bool isEvalFrame() const { return script_->isForEval(); }
-
-  bool isFunctionFrame() const { return script_->isFunction(); }
-
-  inline bool isStrictEvalFrame() const {
-    return isEvalFrame() && script()->strict();
-  }
-
-  bool isNonStrictEvalFrame() const {
-    return isEvalFrame() && !script()->strict();
-  }
-
-  bool isNonGlobalEvalFrame() const;
-
-  bool isNonStrictDirectEvalFrame() const {
-    return isNonStrictEvalFrame() && isNonGlobalEvalFrame();
-  }
-
-  /*
-   * Previous frame
-   *
-   * A frame's 'prev' frame is either null or the previous frame pointed to
-   * by cx->regs->fp when this frame was pushed. Often, given two prev-linked
-   * frames, the next-frame is a function or eval that was called by the
-   * prev-frame, but not always: the prev-frame may have called a native that
-   * reentered the VM through JS_CallFunctionValue on the same context
-   * (without calling JS_SaveFrameChain) which pushed the next-frame. Thus,
-   * 'prev' has little semantic meaning and basically just tells the VM what
-   * to set cx->regs->fp to when this frame is popped.
-   */
-
-  InterpreterFrame* prev() const { return prev_; }
-
-  AbstractFramePtr evalInFramePrev() const {
-    MOZ_ASSERT(isEvalFrame());
-    return evalInFramePrev_;
-  }
-
-  /*
-   * (Unaliased) locals and arguments
-   *
-   * Only non-eval function frames have arguments. The arguments pushed by
-   * the caller are the 'actual' arguments. The declared arguments of the
-   * callee are the 'formal' arguments. When the caller passes less actual
-   * arguments, missing formal arguments are padded with |undefined|.
-   *
-   * When a local/formal variable is aliased (accessed by nested closures,
-   * environment operations, or 'arguments'), the canonical location for
-   * that value is the slot of an environment object.  Aliased locals don't
-   * have stack slots assigned to them.  These functions assert that
-   * accesses to stack values are unaliased.
-   */
-
-  inline Value& unaliasedLocal(uint32_t i);
-
-  bool hasArgs() const { return isFunctionFrame(); }
-  inline Value& unaliasedFormal(unsigned i,
-                                MaybeCheckAliasing = CHECK_ALIASING);
-  inline Value& unaliasedActual(unsigned i,
-                                MaybeCheckAliasing = CHECK_ALIASING);
-  template <class Op>
-  inline void unaliasedForEachActual(Op op);
-
-  unsigned numFormalArgs() const {
-    MOZ_ASSERT(hasArgs());
-    return callee().nargs();
-  }
-  unsigned numActualArgs() const {
-    MOZ_ASSERT(hasArgs());
-    return nactual_;
-  }
-
-  /* Watch out, this exposes a pointer to the unaliased formal arg array. */
-  Value* argv() const {
-    MOZ_ASSERT(hasArgs());
-    return argv_;
-  }
-
-  /*
-   * Arguments object
-   *
-   * If a non-eval function has script->needsArgsObj, an arguments object is
-   * created in the prologue and stored in the local variable for the
-   * 'arguments' binding (script->argumentsLocal). Since this local is
-   * mutable, the arguments object can be overwritten and we can "lose" the
-   * arguments object. Thus, InterpreterFrame keeps an explicit argsObj_ field
-   * so that the original arguments object is always available.
-   */
-
-  ArgumentsObject& argsObj() const;
-  void initArgsObj(ArgumentsObject& argsobj);
-
-  ArrayObject* createRestParameter(JSContext* cx);
-
-  /*
-   * Environment chain
-   *
-   * In theory, the environment chain would contain an object for every
-   * lexical scope. However, only objects that are required for dynamic
-   * lookup are actually created.
-   *
-   * Given that an InterpreterFrame corresponds roughly to a ES Execution
-   * Context (ES 10.3), InterpreterFrame::varObj corresponds to the
-   * VariableEnvironment component of a Exection Context. Intuitively, the
-   * variables object is where new bindings (variables and functions) are
-   * stored. One might expect that this is either the Call object or
-   * envChain.globalObj for function or global code, respectively, however
-   * the JSAPI allows calls of Execute to specify a variables object on the
-   * environment chain other than the call/global object. This allows
-   * embeddings to run multiple scripts under the same global, each time
-   * using a new variables object to collect and discard the script's global
-   * variables.
-   */
-
-  inline HandleObject environmentChain() const;
-
-  inline EnvironmentObject& aliasedEnvironment(EnvironmentCoordinate ec) const;
-  inline GlobalObject& global() const;
-  inline CallObject& callObj() const;
-  inline JSObject& varObj() const;
-  inline LexicalEnvironmentObject& extensibleLexicalEnvironment() const;
-
-  template <typename SpecificEnvironment>
-  inline void pushOnEnvironmentChain(SpecificEnvironment& env);
-  template <typename SpecificEnvironment>
-  inline void popOffEnvironmentChain();
-  inline void replaceInnermostEnvironment(EnvironmentObject& env);
-
-  // Push a VarEnvironmentObject for function frames of functions that have
-  // parameter expressions with closed over var bindings.
-  bool pushVarEnvironment(JSContext* cx, HandleScope scope);
-
-  /*
-   * For lexical envs with aliased locals, these interfaces push and pop
-   * entries on the environment chain.  The "freshen" operation replaces the
-   * current lexical env with a fresh copy of it, to implement semantics
-   * providing distinct bindings per iteration of a for(;;) loop whose head
-   * has a lexical declaration.  The "recreate" operation replaces the
-   * current lexical env with a copy of it containing uninitialized
-   * bindings, to implement semantics providing distinct bindings per
-   * iteration of a for-in/of loop.
-   */
-
-  bool pushLexicalEnvironment(JSContext* cx, Handle<LexicalScope*> scope);
-  bool freshenLexicalEnvironment(JSContext* cx);
-  bool recreateLexicalEnvironment(JSContext* cx);
-
-  /*
-   * Script
-   *
-   * All frames have an associated JSScript which holds the bytecode being
-   * executed for the frame.
-   */
-
-  JSScript* script() const { return script_; }
-
-  /* Return the previous frame's pc. */
-  jsbytecode* prevpc() {
-    MOZ_ASSERT(prev_);
-    return prevpc_;
-  }
-
-  /* Return the previous frame's sp. */
-  Value* prevsp() {
-    MOZ_ASSERT(prev_);
-    return prevsp_;
-  }
-
-  /*
-   * Return the 'this' argument passed to a non-eval function frame. This is
-   * not necessarily the frame's this-binding, for instance non-strict
-   * functions will box primitive 'this' values and thisArgument() will
-   * return the original, unboxed Value.
-   */
-  Value& thisArgument() const {
-    MOZ_ASSERT(isFunctionFrame());
-    return argv()[-1];
-  }
-
-  /*
-   * Callee
-   *
-   * Only function frames have a callee. An eval frame in a function has the
-   * same callee as its containing function frame.
-   */
-
-  JSFunction& callee() const {
-    MOZ_ASSERT(isFunctionFrame());
-    return calleev().toObject().as<JSFunction>();
-  }
-
-  const Value& calleev() const {
-    MOZ_ASSERT(isFunctionFrame());
-    return argv()[-2];
-  }
-
-  /*
-   * New Target
-   *
-   * Only function frames have a meaningful newTarget. An eval frame in a
-   * function will have a copy of the newTarget of the enclosing function
-   * frame.
-   */
-  Value newTarget() const {
-    if (isEvalFrame()) {
-      return ((Value*)this)[-1];
-    }
-
-    MOZ_ASSERT(isFunctionFrame());
-
-    if (callee().isArrow()) {
-      return callee().getExtendedSlot(FunctionExtended::ARROW_NEWTARGET_SLOT);
-    }
-
-    if (isConstructing()) {
-      unsigned pushedArgs = std::max(numFormalArgs(), numActualArgs());
-      return argv()[pushedArgs];
-    }
-    return UndefinedValue();
-  }
-
-  /* Profiler flags */
-
-  bool hasPushedGeckoProfilerFrame() {
-    return !!(flags_ & HAS_PUSHED_PROF_FRAME);
-  }
-
-  void setPushedGeckoProfilerFrame() { flags_ |= HAS_PUSHED_PROF_FRAME; }
-
-  void unsetPushedGeckoProfilerFrame() { flags_ &= ~HAS_PUSHED_PROF_FRAME; }
-
-  /* Return value */
-
-  bool hasReturnValue() const { return flags_ & HAS_RVAL; }
-
-  MutableHandleValue returnValue() {
-    if (!hasReturnValue()) {
-      rval_.setUndefined();
-    }
-    return MutableHandleValue::fromMarkedLocation(&rval_);
-  }
-
-  void markReturnValue() { flags_ |= HAS_RVAL; }
-
-  void setReturnValue(const Value& v) {
-    rval_ = v;
-    markReturnValue();
-  }
-
-  void clearReturnValue() {
-    rval_.setUndefined();
-    markReturnValue();
-  }
-
-  void resumeGeneratorFrame(JSObject* envChain) {
-    MOZ_ASSERT(script()->isGenerator() || script()->isAsync());
-    MOZ_ASSERT(isFunctionFrame());
-    flags_ |= HAS_INITIAL_ENV;
-    envChain_ = envChain;
-  }
-
-  /*
-   * Other flags
-   */
-
-  bool isConstructing() const { return !!(flags_ & CONSTRUCTING); }
-
-  void setResumedGenerator() { flags_ |= RESUMED_GENERATOR; }
-  bool isResumedGenerator() const { return !!(flags_ & RESUMED_GENERATOR); }
-
-  /*
-   * These two queries should not be used in general: the presence/absence of
-   * the call/args object is determined by the static(ish) properties of the
-   * JSFunction/JSScript. These queries should only be performed when probing
-   * a stack frame that may be in the middle of the prologue (during which
-   * time the call/args object are created).
-   */
-
-  inline bool hasInitialEnvironment() const;
-
-  bool hasInitialEnvironmentUnchecked() const {
-    return flags_ & HAS_INITIAL_ENV;
-  }
-
-  bool hasArgsObj() const {
-    MOZ_ASSERT(script()->needsArgsObj());
-    return flags_ & HAS_ARGS_OBJ;
-  }
-
-  /*
-   * Debugger eval frames.
-   *
-   * - If evalInFramePrev_ is non-null, frame was created for an "eval in
-   *   frame" call, which can push a successor to any live frame; so its
-   *   logical "prev" frame is not necessarily the previous frame in memory.
-   *   Iteration should treat evalInFramePrev_ as this frame's previous frame.
-   *
-   * - Don't bother to JIT it, because it's probably short-lived.
-   *
-   * - It is required to have a environment chain object outside the
-   *   js::EnvironmentObject hierarchy: either a global object, or a
-   *   DebugEnvironmentProxy.
-   */
-  bool isDebuggerEvalFrame() const {
-    return isEvalFrame() && !!evalInFramePrev_;
-  }
-
-  bool prevUpToDate() const { return !!(flags_ & PREV_UP_TO_DATE); }
-
-  void setPrevUpToDate() { flags_ |= PREV_UP_TO_DATE; }
-
-  void unsetPrevUpToDate() { flags_ &= ~PREV_UP_TO_DATE; }
-
-  bool isDebuggee() const { return !!(flags_ & DEBUGGEE); }
-
-  void setIsDebuggee() { flags_ |= DEBUGGEE; }
-
-  inline void unsetIsDebuggee();
-
-  bool hasCachedSavedFrame() const { return flags_ & HAS_CACHED_SAVED_FRAME; }
-  void setHasCachedSavedFrame() { flags_ |= HAS_CACHED_SAVED_FRAME; }
-  void clearHasCachedSavedFrame() { flags_ &= ~HAS_CACHED_SAVED_FRAME; }
-
- public:
-  void trace(JSTracer* trc, Value* sp, jsbytecode* pc);
-  void traceValues(JSTracer* trc, unsigned start, unsigned end);
-
-  // Entered Baseline/Ion from the interpreter.
-  bool runningInJit() const { return !!(flags_ & RUNNING_IN_JIT); }
-  void setRunningInJit() { flags_ |= RUNNING_IN_JIT; }
-  void clearRunningInJit() { flags_ &= ~RUNNING_IN_JIT; }
+  inline ActivationEntryMonitor(JSContext* cx, InterpreterFrame* entryFrame);
+  inline ActivationEntryMonitor(JSContext* cx, jit::CalleeToken entryToken);
+  inline ~ActivationEntryMonitor();
 };
 
-/*****************************************************************************/
-
-class InterpreterRegs {
- public:
-  Value* sp;
-  jsbytecode* pc;
-
- private:
-  InterpreterFrame* fp_;
-
- public:
-  InterpreterFrame* fp() const { return fp_; }
-
-  unsigned stackDepth() const {
-    MOZ_ASSERT(sp >= fp_->base());
-    return sp - fp_->base();
-  }
-
-  Value* spForStackDepth(unsigned depth) const {
-    MOZ_ASSERT(fp_->script()->nfixed() + depth <= fp_->script()->nslots());
-    return fp_->base() + depth;
-  }
-
-  /* For generators. */
-  void rebaseFromTo(const InterpreterRegs& from, InterpreterFrame& to) {
-    fp_ = &to;
-    sp = to.slots() + (from.sp - from.fp_->slots());
-    pc = from.pc;
-    MOZ_ASSERT(fp_);
-  }
-
-  void popInlineFrame() {
-    pc = fp_->prevpc();
-    unsigned spForNewTarget =
-        fp_->isResumedGenerator() ? 0 : fp_->isConstructing();
-    sp = fp_->prevsp() - fp_->numActualArgs() - 1 - spForNewTarget;
-    fp_ = fp_->prev();
-    MOZ_ASSERT(fp_);
-  }
-  void prepareToRun(InterpreterFrame& fp, JSScript* script) {
-    pc = script->code();
-    sp = fp.slots() + script->nfixed();
-    fp_ = &fp;
-  }
-
-  void setToEndOfScript();
-
-  MutableHandleValue stackHandleAt(int i) {
-    return MutableHandleValue::fromMarkedLocation(&sp[i]);
-  }
-
-  HandleValue stackHandleAt(int i) const {
-    return HandleValue::fromMarkedLocation(&sp[i]);
-  }
-
-  friend void GDBTestInitInterpreterRegs(InterpreterRegs&,
-                                         js::InterpreterFrame*, JS::Value*,
-                                         uint8_t*);
-};
-
-/*****************************************************************************/
-
-class InterpreterStack {
-  friend class InterpreterActivation;
-
-  static const size_t DEFAULT_CHUNK_SIZE = 4 * 1024;
-  LifoAlloc allocator_;
-
-  // Number of interpreter frames on the stack, for over-recursion checks.
-  static const size_t MAX_FRAMES = 50 * 1000;
-  static const size_t MAX_FRAMES_TRUSTED = MAX_FRAMES + 1000;
-  size_t frameCount_;
-
-  inline uint8_t* allocateFrame(JSContext* cx, size_t size);
-
-  inline InterpreterFrame* getCallFrame(JSContext* cx, const CallArgs& args,
-                                        HandleScript script,
-                                        MaybeConstruct constructing,
-                                        Value** pargv);
-
-  void releaseFrame(InterpreterFrame* fp) {
-    frameCount_--;
-    allocator_.release(fp->mark_);
-  }
-
- public:
-  InterpreterStack() : allocator_(DEFAULT_CHUNK_SIZE), frameCount_(0) {}
-
-  ~InterpreterStack() { MOZ_ASSERT(frameCount_ == 0); }
-
-  // For execution of eval or global code.
-  InterpreterFrame* pushExecuteFrame(JSContext* cx, HandleScript script,
-                                     const Value& newTargetValue,
-                                     HandleObject envChain,
-                                     AbstractFramePtr evalInFrame);
-
-  // Called to invoke a function.
-  InterpreterFrame* pushInvokeFrame(JSContext* cx, const CallArgs& args,
-                                    MaybeConstruct constructing);
-
-  // The interpreter can push light-weight, "inline" frames without entering a
-  // new InterpreterActivation or recursively calling Interpret.
-  bool pushInlineFrame(JSContext* cx, InterpreterRegs& regs,
-                       const CallArgs& args, HandleScript script,
-                       MaybeConstruct constructing);
-
-  void popInlineFrame(InterpreterRegs& regs);
-
-  bool resumeGeneratorCallFrame(JSContext* cx, InterpreterRegs& regs,
-                                HandleFunction callee, HandleObject envChain);
-
-  inline void purge(JSRuntime* rt);
-
-  size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
-    return allocator_.sizeOfExcludingThis(mallocSizeOf);
-  }
-};
-
-void TraceInterpreterActivations(JSContext* cx, JSTracer* trc);
-
-/*****************************************************************************/
-
-/** Base class for all function call args. */
-class AnyInvokeArgs : public JS::CallArgs {};
-
-/** Base class for all function construction args. */
-class AnyConstructArgs : public JS::CallArgs {
-  // Only js::Construct (or internal methods that call the qualified CallArgs
-  // versions) should do these things!
-  void setCallee(const Value& v) = delete;
-  void setThis(const Value& v) = delete;
-  MutableHandleValue newTarget() const = delete;
-  MutableHandleValue rval() const = delete;
-};
-
-namespace detail {
-
-/** Function call/construct args of statically-unknown count. */
-template <MaybeConstruct Construct>
-class GenericArgsBase : public mozilla::Conditional<Construct, AnyConstructArgs,
-                                                    AnyInvokeArgs>::Type {
- protected:
-  RootedValueVector v_;
-
-  explicit GenericArgsBase(JSContext* cx) : v_(cx) {}
-
- public:
-  bool init(JSContext* cx, unsigned argc) {
-    if (argc > ARGS_LENGTH_MAX) {
-      JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
-                                JSMSG_TOO_MANY_ARGUMENTS);
-      return false;
-    }
-
-    // callee, this, arguments[, new.target iff constructing]
-    size_t len = 2 + argc + uint32_t(Construct);
-    MOZ_ASSERT(len > argc);  // no overflow
-    if (!v_.resize(len)) {
-      return false;
-    }
-
-    *static_cast<JS::CallArgs*>(this) = CallArgsFromVp(argc, v_.begin());
-    this->constructing_ = Construct;
-    if (Construct) {
-      this->CallArgs::setThis(MagicValue(JS_IS_CONSTRUCTING));
-    }
-    return true;
-  }
-};
-
-/** Function call/construct args of statically-known count. */
-template <MaybeConstruct Construct, size_t N>
-class FixedArgsBase : public mozilla::Conditional<Construct, AnyConstructArgs,
-                                                  AnyInvokeArgs>::Type {
-  static_assert(N <= ARGS_LENGTH_MAX, "o/~ too many args o/~");
-
- protected:
-  JS::AutoValueArray<2 + N + uint32_t(Construct)> v_;
-
-  explicit FixedArgsBase(JSContext* cx) : v_(cx) {
-    *static_cast<JS::CallArgs*>(this) = CallArgsFromVp(N, v_.begin());
-    this->constructing_ = Construct;
-    if (Construct) {
-      this->CallArgs::setThis(MagicValue(JS_IS_CONSTRUCTING));
-    }
-  }
-};
-
-}  // namespace detail
-
-/** Function call args of statically-unknown count. */
-class InvokeArgs : public detail::GenericArgsBase<NO_CONSTRUCT> {
-  using Base = detail::GenericArgsBase<NO_CONSTRUCT>;
-
- public:
-  explicit InvokeArgs(JSContext* cx) : Base(cx) {}
-};
-
-/** Function call args of statically-unknown count. */
-class InvokeArgsMaybeIgnoresReturnValue
-    : public detail::GenericArgsBase<NO_CONSTRUCT> {
-  using Base = detail::GenericArgsBase<NO_CONSTRUCT>;
-
- public:
-  explicit InvokeArgsMaybeIgnoresReturnValue(JSContext* cx,
-                                             bool ignoresReturnValue)
-      : Base(cx) {
-    this->ignoresReturnValue_ = ignoresReturnValue;
-  }
-};
-
-/** Function call args of statically-known count. */
-template <size_t N>
-class FixedInvokeArgs : public detail::FixedArgsBase<NO_CONSTRUCT, N> {
-  using Base = detail::FixedArgsBase<NO_CONSTRUCT, N>;
-
- public:
-  explicit FixedInvokeArgs(JSContext* cx) : Base(cx) {}
-};
-
-/** Function construct args of statically-unknown count. */
-class ConstructArgs : public detail::GenericArgsBase<CONSTRUCT> {
-  using Base = detail::GenericArgsBase<CONSTRUCT>;
-
- public:
-  explicit ConstructArgs(JSContext* cx) : Base(cx) {}
-};
-
-/** Function call args of statically-known count. */
-template <size_t N>
-class FixedConstructArgs : public detail::FixedArgsBase<CONSTRUCT, N> {
-  using Base = detail::FixedArgsBase<CONSTRUCT, N>;
-
- public:
-  explicit FixedConstructArgs(JSContext* cx) : Base(cx) {}
-};
-
-template <class Args, class Arraylike>
-inline bool FillArgumentsFromArraylike(JSContext* cx, Args& args,
-                                       const Arraylike& arraylike) {
-  uint32_t len = arraylike.length();
-  if (!args.init(cx, len)) {
-    return false;
-  }
-
-  for (uint32_t i = 0; i < len; i++) {
-    args[i].set(arraylike[i]);
-  }
-
-  return true;
-}
-
-}  // namespace js
-
-namespace mozilla {
-
-template <>
-struct DefaultHasher<js::AbstractFramePtr> {
-  typedef js::AbstractFramePtr Lookup;
-
-  static js::HashNumber hash(const Lookup& key) {
-    return mozilla::HashGeneric(key.raw());
-  }
-
-  static bool match(const js::AbstractFramePtr& k, const Lookup& l) {
-    return k == l;
-  }
-};
-
-}  // namespace mozilla
-
-namespace js {
-
-/*****************************************************************************/
-
 // [SMDOC] LiveSavedFrameCache: SavedFrame caching to minimize stack walking
 //
 // Since each SavedFrame object includes a 'parent' pointer to the SavedFrame
 // for its caller, if we could easily find the right SavedFrame for a given
 // stack frame, we wouldn't need to walk the rest of the stack. Traversing deep
 // stacks can be expensive, and when we're profiling or instrumenting code, we
 // may want to capture JavaScript stacks frequently, so such cases would benefit
 // if we could avoid walking the entire stack.
@@ -1371,75 +405,41 @@ static_assert(
     sizeof(LiveSavedFrameCache) == sizeof(uintptr_t),
     "Every js::Activation has a LiveSavedFrameCache, so we need to be pretty "
     "careful "
     "about avoiding bloat. If you're adding members to LiveSavedFrameCache, "
     "maybe you "
     "should consider figuring out a way to make js::Activation have a "
     "LiveSavedFrameCache* instead of a Rooted<LiveSavedFrameCache>.");
 
-/*****************************************************************************/
-
-class InterpreterActivation;
-
-namespace jit {
-class JitActivation;
-}  // namespace jit
-
-// This class is separate from Activation, because it calls Compartment::wrap()
-// which can GC and walk the stack. It's not safe to do that within the
-// JitActivation constructor.
-class MOZ_RAII ActivationEntryMonitor {
-  JSContext* cx_;
-
-  // The entry point monitor that was set on cx_->runtime() when this
-  // ActivationEntryMonitor was created.
-  JS::dbg::AutoEntryMonitor* entryMonitor_;
-
-  explicit inline ActivationEntryMonitor(JSContext* cx);
-
-  ActivationEntryMonitor(const ActivationEntryMonitor& other) = delete;
-  void operator=(const ActivationEntryMonitor& other) = delete;
-
-  void init(JSContext* cx, jit::CalleeToken entryToken);
-  void init(JSContext* cx, InterpreterFrame* entryFrame);
-
-  Value asyncStack(JSContext* cx);
-
- public:
-  inline ActivationEntryMonitor(JSContext* cx, InterpreterFrame* entryFrame);
-  inline ActivationEntryMonitor(JSContext* cx, jit::CalleeToken entryToken);
-  inline ~ActivationEntryMonitor();
-};
-
 class Activation {
  protected:
   JSContext* cx_;
   JS::Compartment* compartment_;
   Activation* prev_;
   Activation* prevProfiling_;
 
   // Counter incremented by JS::HideScriptedCaller and decremented by
   // JS::UnhideScriptedCaller. If > 0 for the top activation,
   // DescribeScriptedCaller will return null instead of querying that
   // activation, which should prompt the caller to consult embedding-specific
   // data structures instead.
   size_t hideScriptedCallerCount_;
 
   // The cache of SavedFrame objects we have already captured when walking
   // this activation's stack.
-  Rooted<LiveSavedFrameCache> frameCache_;
+  JS::Rooted<LiveSavedFrameCache> frameCache_;
 
   // Youngest saved frame of an async stack that will be iterated during stack
   // capture in place of the actual stack of previous activations. Note that
   // the stack of this activation is captured entirely before this is used.
   //
   // Usually this is nullptr, meaning that normal stack capture will occur.
   // When this is set, the stack of any previous activation is ignored.
-  Rooted<SavedFrame*> asyncStack_;
+  JS::Rooted<SavedFrame*> asyncStack_;
 
   // Value of asyncCause to be attached to asyncStack_.
   const char* asyncCause_;
 
   // True if the async call was explicitly requested, e.g. via
   // callFunctionWithAsyncStack.
   bool asyncCallIsExplicit_;
 
@@ -1497,17 +497,17 @@ class Activation {
  private:
   Activation(const Activation& other) = delete;
   void operator=(const Activation& other) = delete;
 };
 
 // This variable holds a special opcode value which is greater than all normal
 // opcodes, and is chosen such that the bitwise or of this value with any
 // opcode is this value.
-static const jsbytecode EnableInterruptsPseudoOpcode = -1;
+constexpr jsbytecode EnableInterruptsPseudoOpcode = -1;
 
 static_assert(EnableInterruptsPseudoOpcode >= JSOP_LIMIT,
               "EnableInterruptsPseudoOpcode must be greater than any opcode");
 static_assert(
     EnableInterruptsPseudoOpcode == jsbytecode(-1),
     "EnableInterruptsPseudoOpcode must be the maximum jsbytecode value");
 
 class InterpreterFrameIterator;
@@ -1524,22 +524,23 @@ class InterpreterActivation : public Act
   size_t oldFrameCount_;
 #endif
 
  public:
   inline InterpreterActivation(RunState& state, JSContext* cx,
                                InterpreterFrame* entryFrame);
   inline ~InterpreterActivation();
 
-  inline bool pushInlineFrame(const CallArgs& args, HandleScript script,
+  inline bool pushInlineFrame(const JS::CallArgs& args,
+                              JS::Handle<JSScript*> script,
                               MaybeConstruct constructing);
   inline void popInlineFrame(InterpreterFrame* frame);
 
-  inline bool resumeGeneratorFrame(HandleFunction callee,
-                                   HandleObject envChain);
+  inline bool resumeGeneratorFrame(JS::Handle<JSFunction*> callee,
+                                   JS::Handle<JSObject*> envChain);
 
   InterpreterFrame* current() const { return regs_.fp(); }
   InterpreterRegs& regs() { return regs_; }
   InterpreterFrame* entryFrame() const { return entryFrame_; }
   size_t opMask() const { return opMask_; }
 
   bool isProfiling() const { return false; }
 
@@ -1565,792 +566,11 @@ class ActivationIterator {
 
   ActivationIterator& operator++();
 
   Activation* operator->() const { return activation_; }
   Activation* activation() const { return activation_; }
   bool done() const { return activation_ == nullptr; }
 };
 
-namespace jit {
-
-class BailoutFrameInfo;
-
-// A JitActivation is used for frames running in Baseline or Ion.
-class JitActivation : public Activation {
-  // If Baseline, Ion or Wasm code is on the stack, and has called into C++,
-  // this will be aligned to an ExitFrame. The last bit indicates if it's a
-  // wasm frame (bit set to wasm::ExitOrJitEntryFPTag) or not
-  // (bit set to ~wasm::ExitOrJitEntryFPTag).
-  uint8_t* packedExitFP_;
-
-  // When hasWasmExitFP(), encodedWasmExitReason_ holds ExitReason.
-  uint32_t encodedWasmExitReason_;
-
-  JitActivation* prevJitActivation_;
-
-  // Rematerialized Ion frames which has info copied out of snapshots. Maps
-  // frame pointers (i.e. packedExitFP_) to a vector of rematerializations of
-  // all inline frames associated with that frame.
-  //
-  // This table is lazily initialized by calling getRematerializedFrame.
-  typedef GCVector<UniquePtr<RematerializedFrame>> RematerializedFrameVector;
-  typedef HashMap<uint8_t*, RematerializedFrameVector> RematerializedFrameTable;
-  js::UniquePtr<RematerializedFrameTable> rematerializedFrames_;
-
-  // This vector is used to remember the outcome of the evaluation of recover
-  // instructions.
-  //
-  // RInstructionResults are appended into this vector when Snapshot values
-  // have to be read, or when the evaluation has to run before some mutating
-  // code.  Each RInstructionResults belongs to one frame which has to bailout
-  // as soon as we get back to it.
-  typedef Vector<RInstructionResults, 1> IonRecoveryMap;
-  IonRecoveryMap ionRecovery_;
-
-  // If we are bailing out from Ion, then this field should be a non-null
-  // pointer which references the BailoutFrameInfo used to walk the inner
-  // frames. This field is used for all newly constructed JSJitFrameIters to
-  // read the innermost frame information from this bailout data instead of
-  // reading it from the stack.
-  BailoutFrameInfo* bailoutData_;
-
-  // When profiling is enabled, these fields will be updated to reflect the
-  // last pushed frame for this activation, and if that frame has been
-  // left for a call, the native code site of the call.
-  mozilla::Atomic<void*, mozilla::Relaxed> lastProfilingFrame_;
-  mozilla::Atomic<void*, mozilla::Relaxed> lastProfilingCallSite_;
-  static_assert(sizeof(mozilla::Atomic<void*, mozilla::Relaxed>) ==
-                    sizeof(void*),
-                "Atomic should have same memory format as underlying type.");
-
-  // When wasm traps, the signal handler records some data for unwinding
-  // purposes. Wasm code can't trap reentrantly.
-  mozilla::Maybe<wasm::TrapData> wasmTrapData_;
-
-  void clearRematerializedFrames();
-
-#ifdef CHECK_OSIPOINT_REGISTERS
- protected:
-  // Used to verify that live registers don't change between a VM call and
-  // the OsiPoint that follows it. Protected to silence Clang warning.
-  uint32_t checkRegs_ = 0;
-  RegisterDump regs_;
-#endif
-
- public:
-  explicit JitActivation(JSContext* cx);
-  ~JitActivation();
-
-  bool isProfiling() const {
-    // All JitActivations can be profiled.
-    return true;
-  }
-
-  JitActivation* prevJitActivation() const { return prevJitActivation_; }
-  static size_t offsetOfPrevJitActivation() {
-    return offsetof(JitActivation, prevJitActivation_);
-  }
-
-  bool hasExitFP() const { return !!packedExitFP_; }
-  uint8_t* jsOrWasmExitFP() const {
-    return (uint8_t*)(uintptr_t(packedExitFP_) & ~wasm::ExitOrJitEntryFPTag);
-  }
-  static size_t offsetOfPackedExitFP() {
-    return offsetof(JitActivation, packedExitFP_);
-  }
-
-  bool hasJSExitFP() const {
-    return !(uintptr_t(packedExitFP_) & wasm::ExitOrJitEntryFPTag);
-  }
-  uint8_t* jsExitFP() const {
-    MOZ_ASSERT(hasJSExitFP());
-    return packedExitFP_;
-  }
-  void setJSExitFP(uint8_t* fp) { packedExitFP_ = fp; }
-
-#ifdef CHECK_OSIPOINT_REGISTERS
-  void setCheckRegs(bool check) { checkRegs_ = check; }
-  static size_t offsetOfCheckRegs() {
-    return offsetof(JitActivation, checkRegs_);
-  }
-  static size_t offsetOfRegs() { return offsetof(JitActivation, regs_); }
-#endif
-
-  // Look up a rematerialized frame keyed by the fp, rematerializing the
-  // frame if one doesn't already exist. A frame can only be rematerialized
-  // if an IonFrameIterator pointing to the nearest uninlined frame can be
-  // provided, as values need to be read out of snapshots.
-  //
-  // The inlineDepth must be within bounds of the frame pointed to by iter.
-  RematerializedFrame* getRematerializedFrame(JSContext* cx,
-                                              const JSJitFrameIter& iter,
-                                              size_t inlineDepth = 0);
-
-  // Look up a rematerialized frame by the fp. If inlineDepth is out of
-  // bounds of what has been rematerialized, nullptr is returned.
-  RematerializedFrame* lookupRematerializedFrame(uint8_t* top,
-                                                 size_t inlineDepth = 0);
-
-  // Remove all rematerialized frames associated with the fp top from the
-  // Debugger.
-  void removeRematerializedFramesFromDebugger(JSContext* cx, uint8_t* top);
-
-  bool hasRematerializedFrame(uint8_t* top, size_t inlineDepth = 0) {
-    return !!lookupRematerializedFrame(top, inlineDepth);
-  }
-
-  // Remove a previous rematerialization by fp.
-  void removeRematerializedFrame(uint8_t* top);
-
-  void traceRematerializedFrames(JSTracer* trc);
-
-  // Register the results of on Ion frame recovery.
-  bool registerIonFrameRecovery(RInstructionResults&& results);
-
-  // Return the pointer to the Ion frame recovery, if it is already registered.
-  RInstructionResults* maybeIonFrameRecovery(JitFrameLayout* fp);
-
-  // If an Ion frame recovery exists for the |fp| frame exists, then remove it
-  // from the activation.
-  void removeIonFrameRecovery(JitFrameLayout* fp);
-
-  void traceIonRecovery(JSTracer* trc);
-
-  // Return the bailout information if it is registered.
-  const BailoutFrameInfo* bailoutData() const { return bailoutData_; }
-
-  // Register the bailout data when it is constructed.
-  void setBailoutData(BailoutFrameInfo* bailoutData);
-
-  // Unregister the bailout data when the frame is reconstructed.
-  void cleanBailoutData();
-
-  static size_t offsetOfLastProfilingFrame() {
-    return offsetof(JitActivation, lastProfilingFrame_);
-  }
-  void* lastProfilingFrame() { return lastProfilingFrame_; }
-  void setLastProfilingFrame(void* ptr) { lastProfilingFrame_ = ptr; }
-
-  static size_t offsetOfLastProfilingCallSite() {
-    return offsetof(JitActivation, lastProfilingCallSite_);
-  }
-  void* lastProfilingCallSite() { return lastProfilingCallSite_; }
-  void setLastProfilingCallSite(void* ptr) { lastProfilingCallSite_ = ptr; }
-
-  // WebAssembly specific attributes.
-  bool hasWasmExitFP() const {
-    return uintptr_t(packedExitFP_) & wasm::ExitOrJitEntryFPTag;
-  }
-  wasm::Frame* wasmExitFP() const {
-    MOZ_ASSERT(hasWasmExitFP());
-    return (wasm::Frame*)(uintptr_t(packedExitFP_) &
-                          ~wasm::ExitOrJitEntryFPTag);
-  }
-  void setWasmExitFP(const wasm::Frame* fp) {
-    if (fp) {
-      MOZ_ASSERT(!(uintptr_t(fp) & wasm::ExitOrJitEntryFPTag));
-      packedExitFP_ = (uint8_t*)(uintptr_t(fp) | wasm::ExitOrJitEntryFPTag);
-      MOZ_ASSERT(hasWasmExitFP());
-    } else {
-      packedExitFP_ = nullptr;
-    }
-  }
-  wasm::ExitReason wasmExitReason() const {
-    MOZ_ASSERT(hasWasmExitFP());
-    return wasm::ExitReason::Decode(encodedWasmExitReason_);
-  }
-  static size_t offsetOfEncodedWasmExitReason() {
-    return offsetof(JitActivation, encodedWasmExitReason_);
-  }
-
-  void startWasmTrap(wasm::Trap trap, uint32_t bytecodeOffset,
-                     const wasm::RegisterState& state);
-  void finishWasmTrap();
-  bool isWasmTrapping() const { return !!wasmTrapData_; }
-  const wasm::TrapData& wasmTrapData() { return *wasmTrapData_; }
-};
-
-// A filtering of the ActivationIterator to only stop at JitActivations.
-class JitActivationIterator : public ActivationIterator {
-  void settle() {
-    while (!done() && !activation_->isJit()) {
-      ActivationIterator::operator++();
-    }
-  }
-
- public:
-  explicit JitActivationIterator(JSContext* cx) : ActivationIterator(cx) {
-    settle();
-  }
-
-  JitActivationIterator& operator++() {
-    ActivationIterator::operator++();
-    settle();
-    return *this;
-  }
-};
-
-}  // namespace jit
-
-inline bool Activation::hasWasmExitFP() const {
-  return isJit() && asJit()->hasWasmExitFP();
-}
-
-// Iterates over the frames of a single InterpreterActivation.
-class InterpreterFrameIterator {
-  InterpreterActivation* activation_;
-  InterpreterFrame* fp_;
-  jsbytecode* pc_;
-  Value* sp_;
-
- public:
-  explicit InterpreterFrameIterator(InterpreterActivation* activation)
-      : activation_(activation), fp_(nullptr), pc_(nullptr), sp_(nullptr) {
-    if (activation) {
-      fp_ = activation->current();
-      pc_ = activation->regs().pc;
-      sp_ = activation->regs().sp;
-    }
-  }
-
-  InterpreterFrame* frame() const {
-    MOZ_ASSERT(!done());
-    return fp_;
-  }
-  jsbytecode* pc() const {
-    MOZ_ASSERT(!done());
-    return pc_;
-  }
-  Value* sp() const {
-    MOZ_ASSERT(!done());
-    return sp_;
-  }
-
-  InterpreterFrameIterator& operator++();
-
-  bool done() const { return fp_ == nullptr; }
-};
-
-// A JitFrameIter can iterate over all kind of frames emitted by our code
-// generators, be they composed of JS jit frames or wasm frames, interleaved or
-// not, in any order.
-//
-// In the following class:
-// - code generated for JS is referred to as JSJit.
-// - code generated for wasm is referred to as Wasm.
-// Also, Jit refers to any one of them.
-//
-// JitFrameIter uses JSJitFrameIter to iterate over JSJit code or a
-// WasmFrameIter to iterate over wasm code; only one of them is active at the
-// time. When a sub-iterator is done, the JitFrameIter knows how to stop, move
-// onto the next activation or move onto another kind of Jit code.
-//
-// For ease of use, there is also OnlyJSJitFrameIter, which skips all the
-// non-JSJit frames.
-//
-// Note it is allowed to get a handle to the internal frame iterator via
-// asJSJit() and asWasm(), but the user has to be careful not to have those be
-// used after JitFrameIter leaves the scope or the operator++ is called.
-//
-// In particular, this can handle the transition from wasm to jit and from jit
-// to wasm, since these can be interleaved in the same JitActivation.
-class JitFrameIter {
- protected:
-  jit::JitActivation* act_;
-  mozilla::MaybeOneOf<jit::JSJitFrameIter, wasm::WasmFrameIter> iter_;
-  bool mustUnwindActivation_;
-
-  void settle();
-
- public:
-  JitFrameIter() : act_(nullptr), iter_(), mustUnwindActivation_(false) {}
-  explicit JitFrameIter(jit::JitActivation* activation,
-                        bool mustUnwindActivation = false);
-
-  explicit JitFrameIter(const JitFrameIter& another);
-  JitFrameIter& operator=(const JitFrameIter& another);
-
-  bool isSome() const { return !iter_.empty(); }
-  void reset() {
-    MOZ_ASSERT(isSome());
-    iter_.destroy();
-  }
-
-  bool isJSJit() const {
-    return isSome() && iter_.constructed<jit::JSJitFrameIter>();
-  }
-  jit::JSJitFrameIter& asJSJit() { return iter_.ref<jit::JSJitFrameIter>(); }
-  const jit::JSJitFrameIter& asJSJit() const {
-    return iter_.ref<jit::JSJitFrameIter>();
-  }
-
-  bool isWasm() const {
-    return isSome() && iter_.constructed<wasm::WasmFrameIter>();
-  }
-  wasm::WasmFrameIter& asWasm() { return iter_.ref<wasm::WasmFrameIter>(); }
-  const wasm::WasmFrameIter& asWasm() const {
-    return iter_.ref<wasm::WasmFrameIter>();
-  }
-
-  // Operations common to all frame iterators.
-  const jit::JitActivation* activation() const { return act_; }
-  bool done() const;
-  void operator++();
-
-  JS::Realm* realm() const;
-
-  // Returns the address of the next instruction that will execute in this
-  // frame, once control returns to this frame.
-  uint8_t* resumePCinCurrentFrame() const;
-
-  // Operations which have an effect only on JIT frames.
-  void skipNonScriptedJSFrames();
-
-  // Returns true iff this is a JIT frame with a self-hosted script. Note: be
-  // careful, JitFrameIter does not consider functions inlined by Ion.
-  bool isSelfHostedIgnoringInlining() const;
-};
-
-// A JitFrameIter that skips all the non-JSJit frames, skipping interleaved
-// frames of any another kind.
-
-class OnlyJSJitFrameIter : public JitFrameIter {
-  void settle() {
-    while (!done() && !isJSJit()) {
-      JitFrameIter::operator++();
-    }
-  }
-
- public:
-  explicit OnlyJSJitFrameIter(jit::JitActivation* act);
-  explicit OnlyJSJitFrameIter(JSContext* cx);
-  explicit OnlyJSJitFrameIter(const ActivationIterator& cx);
-
-  void operator++() {
-    JitFrameIter::operator++();
-    settle();
-  }
-
-  const jit::JSJitFrameIter& frame() const { return asJSJit(); }
-};
-
-// A FrameIter walks over a context's stack of JS script activations,
-// abstracting over whether the JS scripts were running in the interpreter or
-// different modes of compiled code.
-//
-// FrameIter is parameterized by what it includes in the stack iteration:
-//  - When provided, the optional JSPrincipal argument will cause FrameIter to
-//    only show frames in globals whose JSPrincipals are subsumed (via
-//    JSSecurityCallbacks::subsume) by the given JSPrincipal.
-//
-// Additionally, there are derived FrameIter types that automatically skip
-// certain frames:
-//  - ScriptFrameIter only shows frames that have an associated JSScript
-//    (currently everything other than wasm stack frames). When !hasScript(),
-//    clients must stick to the portion of the
-//    interface marked below.
-//  - NonBuiltinScriptFrameIter additionally filters out builtin (self-hosted)
-//    scripts.
-class FrameIter {
- public:
-  enum DebuggerEvalOption {
-    FOLLOW_DEBUGGER_EVAL_PREV_LINK,
-    IGNORE_DEBUGGER_EVAL_PREV_LINK
-  };
+}  // namespace js
 
-  enum State {
-    DONE,    // when there are no more frames nor activations to unwind.
-    INTERP,  // interpreter activation on the stack
-    JIT      // jit or wasm activations on the stack
-  };
-
-  // Unlike ScriptFrameIter itself, ScriptFrameIter::Data can be allocated on
-  // the heap, so this structure should not contain any GC things.
-  struct Data {
-    JSContext* cx_;
-    DebuggerEvalOption debuggerEvalOption_;
-    JSPrincipals* principals_;
-
-    State state_;
-
-    jsbytecode* pc_;
-
-    InterpreterFrameIterator interpFrames_;
-    ActivationIterator activations_;
-
-    JitFrameIter jitFrames_;
-    unsigned ionInlineFrameNo_;
-
-    Data(JSContext* cx, DebuggerEvalOption debuggerEvalOption,
-         JSPrincipals* principals);
-    Data(const Data& other);
-  };
-
-  explicit FrameIter(JSContext* cx,
-                     DebuggerEvalOption = FOLLOW_DEBUGGER_EVAL_PREV_LINK);
-  FrameIter(JSContext* cx, DebuggerEvalOption, JSPrincipals*);
-  FrameIter(const FrameIter& iter);
-  MOZ_IMPLICIT FrameIter(const Data& data);
-  MOZ_IMPLICIT FrameIter(AbstractFramePtr frame);
-
-  bool done() const { return data_.state_ == DONE; }
-
-  // -------------------------------------------------------
-  // The following functions can only be called when !done()
-  // -------------------------------------------------------
-
-  FrameIter& operator++();
-
-  JS::Realm* realm() const;
-  JS::Compartment* compartment() const;
-  Activation* activation() const { return data_.activations_.activation(); }
-
-  bool isInterp() const {
-    MOZ_ASSERT(!done());
-    return data_.state_ == INTERP;
-  }
-  bool isJSJit() const {
-    MOZ_ASSERT(!done());
-    return data_.state_ == JIT && data_.jitFrames_.isJSJit();
-  }
-  bool isWasm() const {
-    MOZ_ASSERT(!done());
-    return data_.state_ == JIT && data_.jitFrames_.isWasm();
-  }
-
-  inline bool isIon() const;
-  inline bool isBaseline() const;
-  inline bool isPhysicalJitFrame() const;
-
-  bool isEvalFrame() const;
-  bool isFunctionFrame() const;
-  bool hasArgs() const { return isFunctionFrame(); }
-
-  ScriptSource* scriptSource() const;
-  const char* filename() const;
-  const char16_t* displayURL() const;
-  unsigned computeLine(uint32_t* column = nullptr) const;
-  JSAtom* maybeFunctionDisplayAtom() const;
-  bool mutedErrors() const;
-
-  bool hasScript() const { return !isWasm(); }
-
-  // -----------------------------------------------------------
-  //  The following functions can only be called when isWasm()
-  // -----------------------------------------------------------
-
-  inline bool wasmDebugEnabled() const;
-  inline wasm::Instance* wasmInstance() const;
-  inline uint32_t wasmFuncIndex() const;
-  inline unsigned wasmBytecodeOffset() const;
-  void wasmUpdateBytecodeOffset();
-
-  // -----------------------------------------------------------
-  // The following functions can only be called when hasScript()
-  // -----------------------------------------------------------
-
-  inline JSScript* script() const;
-
-  bool isConstructing() const;
-  jsbytecode* pc() const {
-    MOZ_ASSERT(!done());
-    return data_.pc_;
-  }
-  void updatePcQuadratic();
-
-  // The function |calleeTemplate()| returns either the function from which
-  // the current |callee| was cloned or the |callee| if it can be read. As
-  // long as we do not have to investigate the environment chain or build a
-  // new frame, we should prefer to use |calleeTemplate| instead of
-  // |callee|, as requesting the |callee| might cause the invalidation of
-  // the frame. (see js::Lambda)
-  JSFunction* calleeTemplate() const;
-  JSFunction* callee(JSContext* cx) const;
-
-  JSFunction* maybeCallee(JSContext* cx) const {
-    return isFunctionFrame() ? callee(cx) : nullptr;
-  }
-
-  bool matchCallee(JSContext* cx, HandleFunction fun) const;
-
-  unsigned numActualArgs() const;
-  unsigned numFormalArgs() const;
-  Value unaliasedActual(unsigned i, MaybeCheckAliasing = CHECK_ALIASING) const;
-  template <class Op>
-  inline void unaliasedForEachActual(JSContext* cx, Op op);
-
-  JSObject* environmentChain(JSContext* cx) const;
-  bool hasInitialEnvironment(JSContext* cx) const;
-  CallObject& callObj(JSContext* cx) const;
-
-  bool hasArgsObj() const;
-  ArgumentsObject& argsObj() const;
-
-  // Get the original |this| value passed to this function. May not be the
-  // actual this-binding (for instance, derived class constructors will
-  // change their this-value later and non-strict functions will box
-  // primitives).
-  Value thisArgument(JSContext* cx) const;
-
-  Value newTarget() const;
-
-  Value returnValue() const;
-  void setReturnValue(const Value& v);
-
-  // These are only valid for the top frame.
-  size_t numFrameSlots() const;
-  Value frameSlotValue(size_t index) const;
-
-  // Ensures that we have rematerialized the top frame and its associated
-  // inline frames. Can only be called when isIon().
-  bool ensureHasRematerializedFrame(JSContext* cx);
-
-  // True when isInterp() or isBaseline(). True when isIon() if it
-  // has a rematerialized frame. False otherwise.
-  bool hasUsableAbstractFramePtr() const;
-
-  // -----------------------------------------------------------
-  // The following functions can only be called when isInterp(),
-  // isBaseline(), isWasm() or isIon(). Further, abstractFramePtr() can
-  // only be called when hasUsableAbstractFramePtr().
-  // -----------------------------------------------------------
-
-  AbstractFramePtr abstractFramePtr() const;
-  Data* copyData() const;
-
-  // This can only be called when isInterp():
-  inline InterpreterFrame* interpFrame() const;
-
-  // This can only be called when isPhysicalJitFrame():
-  inline jit::CommonFrameLayout* physicalJitFrame() const;
-
-  // This is used to provide a raw interface for debugging.
-  void* rawFramePtr() const;
-
- private:
-  Data data_;
-  jit::InlineFrameIterator ionInlineFrames_;
-
-  const jit::JSJitFrameIter& jsJitFrame() const {
-    return data_.jitFrames_.asJSJit();
-  }
-  const wasm::WasmFrameIter& wasmFrame() const {
-    return data_.jitFrames_.asWasm();
-  }
-
-  jit::JSJitFrameIter& jsJitFrame() { return data_.jitFrames_.asJSJit(); }
-  wasm::WasmFrameIter& wasmFrame() { return data_.jitFrames_.asWasm(); }
-
-  bool isIonScripted() const {
-    return isJSJit() && jsJitFrame().isIonScripted();
-  }
-
-  bool principalsSubsumeFrame() const;
-
-  void popActivation();
-  void popInterpreterFrame();
-  void nextJitFrame();
-  void popJitFrame();
-  void settleOnActivation();
-};
-
-class ScriptFrameIter : public FrameIter {
-  void settle() {
-    while (!done() && !hasScript()) {
-      FrameIter::operator++();
-    }
-  }
-
- public:
-  explicit ScriptFrameIter(
-      JSContext* cx,
-      DebuggerEvalOption debuggerEvalOption = FOLLOW_DEBUGGER_EVAL_PREV_LINK)
-      : FrameIter(cx, debuggerEvalOption) {
-    settle();
-  }
-
-  ScriptFrameIter(JSContext* cx, DebuggerEvalOption debuggerEvalOption,
-                  JSPrincipals* prin)
-      : FrameIter(cx, debuggerEvalOption, prin) {
-    settle();
-  }
-
-  ScriptFrameIter(const ScriptFrameIter& iter) : FrameIter(iter) { settle(); }
-  explicit ScriptFrameIter(const FrameIter::Data& data) : FrameIter(data) {
-    settle();
-  }
-  explicit ScriptFrameIter(AbstractFramePtr frame) : FrameIter(frame) {
-    settle();
-  }
-
-  ScriptFrameIter& operator++() {
-    FrameIter::operator++();
-    settle();
-    return *this;
-  }
-};
-
-#ifdef DEBUG
-bool SelfHostedFramesVisible();
-#else
-static inline bool SelfHostedFramesVisible() { return false; }
-#endif
-
-/* A filtering of the FrameIter to only stop at non-self-hosted scripts. */
-class NonBuiltinFrameIter : public FrameIter {
-  void settle();
-
- public:
-  explicit NonBuiltinFrameIter(
-      JSContext* cx, FrameIter::DebuggerEvalOption debuggerEvalOption =
-                         FrameIter::FOLLOW_DEBUGGER_EVAL_PREV_LINK)
-      : FrameIter(cx, debuggerEvalOption) {
-    settle();
-  }
-
-  NonBuiltinFrameIter(JSContext* cx,
-                      FrameIter::DebuggerEvalOption debuggerEvalOption,
-                      JSPrincipals* principals)
-      : FrameIter(cx, debuggerEvalOption, principals) {
-    settle();
-  }
-
-  NonBuiltinFrameIter(JSContext* cx, JSPrincipals* principals)
-      : FrameIter(cx, FrameIter::FOLLOW_DEBUGGER_EVAL_PREV_LINK, principals) {
-    settle();
-  }
-
-  explicit NonBuiltinFrameIter(const FrameIter::Data& data) : FrameIter(data) {}
-
-  NonBuiltinFrameIter& operator++() {
-    FrameIter::operator++();
-    settle();
-    return *this;
-  }
-};
-
-// A filtering of the ScriptFrameIter to only stop at non-self-hosted scripts.
-class NonBuiltinScriptFrameIter : public ScriptFrameIter {
-  void settle();
-
- public:
-  explicit NonBuiltinScriptFrameIter(
-      JSContext* cx, ScriptFrameIter::DebuggerEvalOption debuggerEvalOption =
-                         ScriptFrameIter::FOLLOW_DEBUGGER_EVAL_PREV_LINK)
-      : ScriptFrameIter(cx, debuggerEvalOption) {
-    settle();
-  }
-
-  NonBuiltinScriptFrameIter(
-      JSContext* cx, ScriptFrameIter::DebuggerEvalOption debuggerEvalOption,
-      JSPrincipals* principals)
-      : ScriptFrameIter(cx, debuggerEvalOption, principals) {
-    settle();
-  }
-
-  explicit NonBuiltinScriptFrameIter(const ScriptFrameIter::Data& data)
-      : ScriptFrameIter(data) {}
-
-  NonBuiltinScriptFrameIter& operator++() {
-    ScriptFrameIter::operator++();
-    settle();
-    return *this;
-  }
-};
-
-/*
- * Blindly iterate over all frames in the current thread's stack. These frames
- * can be from different contexts and compartments, so beware.
- */
-class AllFramesIter : public FrameIter {
- public:
-  explicit AllFramesIter(JSContext* cx)
-      : FrameIter(cx, ScriptFrameIter::IGNORE_DEBUGGER_EVAL_PREV_LINK) {}
-};
-
-/* Iterates over all script frame in the current thread's stack.
- * See also AllFramesIter and ScriptFrameIter.
- */
-class AllScriptFramesIter : public ScriptFrameIter {
- public:
-  explicit AllScriptFramesIter(JSContext* cx)
-      : ScriptFrameIter(cx, ScriptFrameIter::IGNORE_DEBUGGER_EVAL_PREV_LINK) {}
-};
-
-/* Popular inline definitions. */
-
-inline JSScript* FrameIter::script() const {
-  MOZ_ASSERT(!done());
-  MOZ_ASSERT(hasScript());
-  if (data_.state_ == INTERP) {
-    return interpFrame()->script();
-  }
-  if (jsJitFrame().isIonJS()) {
-    return ionInlineFrames_.script();
-  }
-  return jsJitFrame().script();
-}
-
-inline bool FrameIter::wasmDebugEnabled() const {
-  MOZ_ASSERT(!done());
-  MOZ_ASSERT(isWasm());
-  return wasmFrame().debugEnabled();
-}
-
-inline wasm::Instance* FrameIter::wasmInstance() const {
-  MOZ_ASSERT(!done());
-  MOZ_ASSERT(isWasm());
-  return wasmFrame().instance();
-}
-
-inline unsigned FrameIter::wasmBytecodeOffset() const {
-  MOZ_ASSERT(!done());
-  MOZ_ASSERT(isWasm());
-  return wasmFrame().lineOrBytecode();
-}
-
-inline uint32_t FrameIter::wasmFuncIndex() const {
-  MOZ_ASSERT(!done());
-  MOZ_ASSERT(isWasm());
-  return wasmFrame().funcIndex();
-}
-
-inline bool FrameIter::isIon() const {
-  return isJSJit() && jsJitFrame().isIonJS();
-}
-
-inline bool FrameIter::isBaseline() const {
-  return isJSJit() && jsJitFrame().isBaselineJS();
-}
-
-inline InterpreterFrame* FrameIter::interpFrame() const {
-  MOZ_ASSERT(data_.state_ == INTERP);
-  return data_.interpFrames_.frame();
-}
-
-inline bool FrameIter::isPhysicalJitFrame() const {
-  if (!isJSJit()) {
-    return false;
-  }
-
-  auto& jitFrame = jsJitFrame();
-
-  if (jitFrame.isBaselineJS()) {
-    return true;
-  }
-
-  if (jitFrame.isIonScripted()) {
-    // Only the bottom of a group of inlined Ion frames is a physical frame.
-    return ionInlineFrames_.frameNo() == 0;
-  }
-
-  return false;
-}
-
-inline jit::CommonFrameLayout* FrameIter::physicalJitFrame() const {
-  MOZ_ASSERT(isPhysicalJitFrame());
-  return jsJitFrame().current();
-}
-
-} /* namespace js */
-
-#endif /* vm_Stack_h */
+#endif  // vm_Activation_h
--- a/js/src/vm/ArgumentsObject.cpp
+++ b/js/src/vm/ArgumentsObject.cpp
@@ -14,16 +14,17 @@
 #include "jit/JitFrames.h"
 #include "js/StableStringChars.h"
 #include "util/BitArray.h"
 #include "vm/AsyncFunction.h"
 #include "vm/GlobalObject.h"
 #include "vm/Stack.h"
 
 #include "gc/Nursery-inl.h"
+#include "vm/FrameIter-inl.h"  // js::FrameIter::unaliasedForEachActual
 #include "vm/JSObject-inl.h"
 #include "vm/NativeObject-inl.h"
 #include "vm/Stack-inl.h"
 
 using namespace js;
 
 using JS::AutoStableStringChars;
 
--- a/js/src/vm/BytecodeUtil.cpp
+++ b/js/src/vm/BytecodeUtil.cpp
@@ -32,16 +32,17 @@
 #include "js/Printf.h"
 #include "js/Symbol.h"
 #include "util/Memory.h"
 #include "util/StringBuffer.h"
 #include "util/Text.h"
 #include "vm/BytecodeLocation.h"
 #include "vm/CodeCoverage.h"
 #include "vm/EnvironmentObject.h"
+#include "vm/FrameIter.h"  // js::{,Script}FrameIter
 #include "vm/JSAtom.h"
 #include "vm/JSContext.h"
 #include "vm/JSFunction.h"
 #include "vm/JSObject.h"
 #include "vm/JSScript.h"
 #include "vm/Opcodes.h"
 #include "vm/Realm.h"
 #include "vm/Shape.h"
copy from js/src/vm/Stack-inl.h
copy to js/src/vm/FrameIter-inl.h
--- a/js/src/vm/Stack-inl.h
+++ b/js/src/vm/FrameIter-inl.h
@@ -1,346 +1,28 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * vim: set ts=8 sts=2 et sw=2 tw=80:
  * 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 vm_Stack_inl_h
-#define vm_Stack_inl_h
+#ifndef vm_FrameIter_inl_h
+#define vm_FrameIter_inl_h
 
-#include "vm/Stack.h"
-
-#include "mozilla/Maybe.h"
-#include "mozilla/PodOperations.h"
+#include "vm/FrameIter.h"
 
-#include "jit/BaselineFrame.h"
-#include "jit/RematerializedFrame.h"
-#include "js/Debug.h"
-#include "vm/EnvironmentObject.h"
-#include "vm/JSContext.h"
-#include "vm/JSScript.h"
+#include "mozilla/Assertions.h"  // MOZ_ASSERT, MOZ_CRASH
 
-#include "jit/BaselineFrame-inl.h"
-#include "vm/JSObject-inl.h"
-#include "vm/JSScript-inl.h"
-#include "vm/NativeObject-inl.h"
+#include "jit/JSJitFrameIter.h"  // js::jit::{InlineFrameIterator,MaybeReadFallback,ReadFrame_Actuals}
+#include "vm/Stack.h"  // js::InterpreterFrame
+
+#include "vm/Stack-inl.h"  // js::InterpreterFrame::unaliasedForEachActual
 
 namespace js {
 
-inline HandleObject InterpreterFrame::environmentChain() const {
-  return HandleObject::fromMarkedLocation(&envChain_);
-}
-
-inline GlobalObject& InterpreterFrame::global() const {
-  return script()->global();
-}
-
-inline JSObject& InterpreterFrame::varObj() const {
-  return GetVariablesObject(environmentChain());
-}
-
-inline LexicalEnvironmentObject&
-InterpreterFrame::extensibleLexicalEnvironment() const {
-  return NearestEnclosingExtensibleLexicalEnvironment(environmentChain());
-}
-
-inline void InterpreterFrame::initCallFrame(InterpreterFrame* prev,
-                                            jsbytecode* prevpc, Value* prevsp,
-                                            JSFunction& callee,
-                                            JSScript* script, Value* argv,
-                                            uint32_t nactual,
-                                            MaybeConstruct constructing) {
-  MOZ_ASSERT(callee.nonLazyScript() == script);
-
-  /* Initialize stack frame members. */
-  flags_ = 0;
-  if (constructing) {
-    flags_ |= CONSTRUCTING;
-  }
-  argv_ = argv;
-  script_ = script;
-  nactual_ = nactual;
-  envChain_ = callee.environment();
-  prev_ = prev;
-  prevpc_ = prevpc;
-  prevsp_ = prevsp;
-
-  if (script->isDebuggee()) {
-    setIsDebuggee();
-  }
-
-  initLocals();
-}
-
-inline void InterpreterFrame::initLocals() {
-  SetValueRangeToUndefined(slots(), script()->nfixed());
-}
-
-inline Value& InterpreterFrame::unaliasedLocal(uint32_t i) {
-  MOZ_ASSERT(i < script()->nfixed());
-  return slots()[i];
-}
-
-inline Value& InterpreterFrame::unaliasedFormal(
-    unsigned i, MaybeCheckAliasing checkAliasing) {
-  MOZ_ASSERT(i < numFormalArgs());
-  MOZ_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals());
-  MOZ_ASSERT_IF(checkAliasing, !script()->formalIsAliased(i));
-  return argv()[i];
-}
-
-inline Value& InterpreterFrame::unaliasedActual(
-    unsigned i, MaybeCheckAliasing checkAliasing) {
-  MOZ_ASSERT(i < numActualArgs());
-  MOZ_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals());
-  MOZ_ASSERT_IF(checkAliasing && i < numFormalArgs(),
-                !script()->formalIsAliased(i));
-  return argv()[i];
-}
-
-template <class Op>
-inline void InterpreterFrame::unaliasedForEachActual(Op op) {
-  // Don't assert !script()->funHasAnyAliasedFormal() since this function is
-  // called from ArgumentsObject::createUnexpected() which can access aliased
-  // slots.
-
-  const Value* argsEnd = argv() + numActualArgs();
-  for (const Value* p = argv(); p < argsEnd; ++p) {
-    op(*p);
-  }
-}
-
-struct CopyTo {
-  Value* dst;
-  explicit CopyTo(Value* dst) : dst(dst) {}
-  void operator()(const Value& src) { *dst++ = src; }
-};
-
-struct CopyToHeap {
-  GCPtrValue* dst;
-  explicit CopyToHeap(GCPtrValue* dst) : dst(dst) {}
-  void operator()(const Value& src) {
-    dst->init(src);
-    ++dst;
-  }
-};
-
-inline ArgumentsObject& InterpreterFrame::argsObj() const {
-  MOZ_ASSERT(script()->needsArgsObj());
-  MOZ_ASSERT(flags_ & HAS_ARGS_OBJ);
-  return *argsObj_;
-}
-
-inline void InterpreterFrame::initArgsObj(ArgumentsObject& argsobj) {
-  MOZ_ASSERT(script()->needsArgsObj());
-  flags_ |= HAS_ARGS_OBJ;
-  argsObj_ = &argsobj;
-}
-
-inline EnvironmentObject& InterpreterFrame::aliasedEnvironment(
-    EnvironmentCoordinate ec) const {
-  JSObject* env = &environmentChain()->as<EnvironmentObject>();
-  for (unsigned i = ec.hops(); i; i--) {
-    env = &env->as<EnvironmentObject>().enclosingEnvironment();
-  }
-  return env->as<EnvironmentObject>();
-}
-
-template <typename SpecificEnvironment>
-inline void InterpreterFrame::pushOnEnvironmentChain(SpecificEnvironment& env) {
-  MOZ_ASSERT(*environmentChain() == env.enclosingEnvironment());
-  envChain_ = &env;
-  if (IsFrameInitialEnvironment(this, env)) {
-    flags_ |= HAS_INITIAL_ENV;
-  }
-}
-
-template <typename SpecificEnvironment>
-inline void InterpreterFrame::popOffEnvironmentChain() {
-  MOZ_ASSERT(envChain_->is<SpecificEnvironment>());
-  envChain_ = &envChain_->as<SpecificEnvironment>().enclosingEnvironment();
-}
-
-inline void InterpreterFrame::replaceInnermostEnvironment(
-    EnvironmentObject& env) {
-  MOZ_ASSERT(env.enclosingEnvironment() ==
-             envChain_->as<EnvironmentObject>().enclosingEnvironment());
-  envChain_ = &env;
-}
-
-bool InterpreterFrame::hasInitialEnvironment() const {
-  MOZ_ASSERT(script()->initialEnvironmentShape());
-  return flags_ & HAS_INITIAL_ENV;
-}
-
-inline CallObject& InterpreterFrame::callObj() const {
-  MOZ_ASSERT(callee().needsCallObject());
-
-  JSObject* pobj = environmentChain();
-  while (MOZ_UNLIKELY(!pobj->is<CallObject>())) {
-    pobj = pobj->enclosingEnvironment();
-  }
-  return pobj->as<CallObject>();
-}
-
-inline void InterpreterFrame::unsetIsDebuggee() {
-  MOZ_ASSERT(!script()->isDebuggee());
-  flags_ &= ~DEBUGGEE;
-}
-
-/*****************************************************************************/
-
-inline void InterpreterStack::purge(JSRuntime* rt) {
-  rt->gc.queueUnusedLifoBlocksForFree(&allocator_);
-}
-
-uint8_t* InterpreterStack::allocateFrame(JSContext* cx, size_t size) {
-  size_t maxFrames;
-  if (cx->realm()->principals() == cx->runtime()->trustedPrincipals()) {
-    maxFrames = MAX_FRAMES_TRUSTED;
-  } else {
-    maxFrames = MAX_FRAMES;
-  }
-
-  if (MOZ_UNLIKELY(frameCount_ >= maxFrames)) {
-    ReportOverRecursed(cx);
-    return nullptr;
-  }
-
-  uint8_t* buffer = reinterpret_cast<uint8_t*>(allocator_.alloc(size));
-  if (!buffer) {
-    ReportOutOfMemory(cx);
-    return nullptr;
-  }
-
-  frameCount_++;
-  return buffer;
-}
-
-MOZ_ALWAYS_INLINE InterpreterFrame* InterpreterStack::getCallFrame(
-    JSContext* cx, const CallArgs& args, HandleScript script,
-    MaybeConstruct constructing, Value** pargv) {
-  JSFunction* fun = &args.callee().as<JSFunction>();
-
-  MOZ_ASSERT(fun->nonLazyScript() == script);
-  unsigned nformal = fun->nargs();
-  unsigned nvals = script->nslots();
-
-  if (args.length() >= nformal) {
-    *pargv = args.array();
-    uint8_t* buffer =
-        allocateFrame(cx, sizeof(InterpreterFrame) + nvals * sizeof(Value));
-    return reinterpret_cast<InterpreterFrame*>(buffer);
-  }
-
-  // Pad any missing arguments with |undefined|.
-  MOZ_ASSERT(args.length() < nformal);
-
-  unsigned nfunctionState = 2 + constructing;  // callee, |this|, |new.target|
-
-  nvals += nformal + nfunctionState;
-  uint8_t* buffer =
-      allocateFrame(cx, sizeof(InterpreterFrame) + nvals * sizeof(Value));
-  if (!buffer) {
-    return nullptr;
-  }
-
-  Value* argv = reinterpret_cast<Value*>(buffer);
-  unsigned nmissing = nformal - args.length();
-
-  mozilla::PodCopy(argv, args.base(), 2 + args.length());
-  SetValueRangeToUndefined(argv + 2 + args.length(), nmissing);
-
-  if (constructing) {
-    argv[2 + nformal] = args.newTarget();
-  }
-
-  *pargv = argv + 2;
-  return reinterpret_cast<InterpreterFrame*>(argv + nfunctionState + nformal);
-}
-
-MOZ_ALWAYS_INLINE bool InterpreterStack::pushInlineFrame(
-    JSContext* cx, InterpreterRegs& regs, const CallArgs& args,
-    HandleScript script, MaybeConstruct constructing) {
-  RootedFunction callee(cx, &args.callee().as<JSFunction>());
-  MOZ_ASSERT(regs.sp == args.end());
-  MOZ_ASSERT(callee->nonLazyScript() == script);
-
-  InterpreterFrame* prev = regs.fp();
-  jsbytecode* prevpc = regs.pc;
-  Value* prevsp = regs.sp;
-  MOZ_ASSERT(prev);
-
-  LifoAlloc::Mark mark = allocator_.mark();
-
-  Value* argv;
-  InterpreterFrame* fp = getCallFrame(cx, args, script, constructing, &argv);
-  if (!fp) {
-    return false;
-  }
-
-  fp->mark_ = mark;
-
-  /* Initialize frame, locals, regs. */
-  fp->initCallFrame(prev, prevpc, prevsp, *callee, script, argv, args.length(),
-                    constructing);
-
-  regs.prepareToRun(*fp, script);
-  return true;
-}
-
-MOZ_ALWAYS_INLINE bool InterpreterStack::resumeGeneratorCallFrame(
-    JSContext* cx, InterpreterRegs& regs, HandleFunction callee,
-    HandleObject envChain) {
-  MOZ_ASSERT(callee->isGenerator() || callee->isAsync());
-  RootedScript script(cx, callee->nonLazyScript());
-  InterpreterFrame* prev = regs.fp();
-  jsbytecode* prevpc = regs.pc;
-  Value* prevsp = regs.sp;
-  MOZ_ASSERT(prev);
-
-  LifoAlloc::Mark mark = allocator_.mark();
-
-  // (Async) generators and async functions are not constructors.
-  MOZ_ASSERT(!callee->isConstructor());
-
-  // Include callee, |this|, and maybe |new.target|
-  unsigned nformal = callee->nargs();
-  unsigned nvals = 2 + nformal + script->nslots();
-
-  uint8_t* buffer =
-      allocateFrame(cx, sizeof(InterpreterFrame) + nvals * sizeof(Value));
-  if (!buffer) {
-    return false;
-  }
-
-  Value* argv = reinterpret_cast<Value*>(buffer) + 2;
-  argv[-2] = ObjectValue(*callee);
-  argv[-1] = UndefinedValue();
-  SetValueRangeToUndefined(argv, nformal);
-
-  InterpreterFrame* fp = reinterpret_cast<InterpreterFrame*>(argv + nformal);
-  fp->mark_ = mark;
-  fp->initCallFrame(prev, prevpc, prevsp, *callee, script, argv, 0,
-                    NO_CONSTRUCT);
-  fp->resumeGeneratorFrame(envChain);
-
-  regs.prepareToRun(*fp, script);
-  return true;
-}
-
-MOZ_ALWAYS_INLINE void InterpreterStack::popInlineFrame(InterpreterRegs& regs) {
-  InterpreterFrame* fp = regs.fp();
-  regs.popInlineFrame();
-  regs.sp[-1] = fp->returnValue();
-  releaseFrame(fp);
-  MOZ_ASSERT(regs.fp());
-}
-
 template <class Op>
 inline void FrameIter::unaliasedForEachActual(JSContext* cx, Op op) {
   switch (data_.state_) {
     case DONE:
       break;
     case INTERP:
       interpFrame()->unaliasedForEachActual(op);
       return;
@@ -365,689 +47,11 @@ inline void FrameIter::unaliasedForEachA
         MOZ_ASSERT(jsJitFrame().isBaselineJS());
         jsJitFrame().unaliasedForEachActual(op, jit::ReadFrame_Actuals);
       }
       return;
   }
   MOZ_CRASH("Unexpected state");
 }
 
-inline HandleValue AbstractFramePtr::returnValue() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->returnValue();
-  }
-  if (isWasmDebugFrame()) {
-    return asWasmDebugFrame()->returnValue();
-  }
-  return asBaselineFrame()->returnValue();
-}
-
-inline void AbstractFramePtr::setReturnValue(const Value& rval) const {
-  if (isInterpreterFrame()) {
-    asInterpreterFrame()->setReturnValue(rval);
-    return;
-  }
-  if (isBaselineFrame()) {
-    asBaselineFrame()->setReturnValue(rval);
-    return;
-  }
-  if (isWasmDebugFrame()) {
-    // TODO handle wasm function return value
-    // The function is called from Debugger::slowPathOnLeaveFrame --
-    // ignoring value for wasm.
-    return;
-  }
-  asRematerializedFrame()->setReturnValue(rval);
-}
-
-inline JSObject* AbstractFramePtr::environmentChain() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->environmentChain();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->environmentChain();
-  }
-  if (isWasmDebugFrame()) {
-    return &global()->lexicalEnvironment();
-  }
-  return asRematerializedFrame()->environmentChain();
-}
-
-template <typename SpecificEnvironment>
-inline void AbstractFramePtr::pushOnEnvironmentChain(SpecificEnvironment& env) {
-  if (isInterpreterFrame()) {
-    asInterpreterFrame()->pushOnEnvironmentChain(env);
-    return;
-  }
-  if (isBaselineFrame()) {
-    asBaselineFrame()->pushOnEnvironmentChain(env);
-    return;
-  }
-  asRematerializedFrame()->pushOnEnvironmentChain(env);
-}
-
-template <typename SpecificEnvironment>
-inline void AbstractFramePtr::popOffEnvironmentChain() {
-  if (isInterpreterFrame()) {
-    asInterpreterFrame()->popOffEnvironmentChain<SpecificEnvironment>();
-    return;
-  }
-  if (isBaselineFrame()) {
-    asBaselineFrame()->popOffEnvironmentChain<SpecificEnvironment>();
-    return;
-  }
-  asRematerializedFrame()->popOffEnvironmentChain<SpecificEnvironment>();
-}
-
-inline CallObject& AbstractFramePtr::callObj() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->callObj();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->callObj();
-  }
-  return asRematerializedFrame()->callObj();
-}
-
-inline bool AbstractFramePtr::initFunctionEnvironmentObjects(JSContext* cx) {
-  return js::InitFunctionEnvironmentObjects(cx, *this);
-}
-
-inline bool AbstractFramePtr::pushVarEnvironment(JSContext* cx,
-                                                 HandleScope scope) {
-  return js::PushVarEnvironmentObject(cx, scope, *this);
-}
-
-inline JS::Realm* AbstractFramePtr::realm() const {
-  return environmentChain()->nonCCWRealm();
-}
-
-inline unsigned AbstractFramePtr::numActualArgs() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->numActualArgs();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->numActualArgs();
-  }
-  return asRematerializedFrame()->numActualArgs();
-}
-
-inline unsigned AbstractFramePtr::numFormalArgs() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->numFormalArgs();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->numFormalArgs();
-  }
-  return asRematerializedFrame()->numFormalArgs();
-}
-
-inline Value& AbstractFramePtr::unaliasedLocal(uint32_t i) {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->unaliasedLocal(i);
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->unaliasedLocal(i);
-  }
-  return asRematerializedFrame()->unaliasedLocal(i);
-}
-
-inline Value& AbstractFramePtr::unaliasedFormal(
-    unsigned i, MaybeCheckAliasing checkAliasing) {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->unaliasedFormal(i, checkAliasing);
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->unaliasedFormal(i, checkAliasing);
-  }
-  return asRematerializedFrame()->unaliasedFormal(i, checkAliasing);
-}
-
-inline Value& AbstractFramePtr::unaliasedActual(
-    unsigned i, MaybeCheckAliasing checkAliasing) {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->unaliasedActual(i, checkAliasing);
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->unaliasedActual(i, checkAliasing);
-  }
-  return asRematerializedFrame()->unaliasedActual(i, checkAliasing);
-}
-
-inline bool AbstractFramePtr::hasInitialEnvironment() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->hasInitialEnvironment();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->hasInitialEnvironment();
-  }
-  return asRematerializedFrame()->hasInitialEnvironment();
-}
-
-inline bool AbstractFramePtr::isGlobalFrame() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->isGlobalFrame();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->isGlobalFrame();
-  }
-  if (isWasmDebugFrame()) {
-    return false;
-  }
-  return asRematerializedFrame()->isGlobalFrame();
-}
-
-inline bool AbstractFramePtr::isModuleFrame() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->isModuleFrame();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->isModuleFrame();
-  }
-  if (isWasmDebugFrame()) {
-    return false;
-  }
-  return asRematerializedFrame()->isModuleFrame();
-}
-
-inline bool AbstractFramePtr::isEvalFrame() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->isEvalFrame();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->isEvalFrame();
-  }
-  if (isWasmDebugFrame()) {
-    return false;
-  }
-  MOZ_ASSERT(isRematerializedFrame());
-  return false;
-}
-
-inline bool AbstractFramePtr::isDebuggerEvalFrame() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->isDebuggerEvalFrame();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->isDebuggerEvalFrame();
-  }
-  MOZ_ASSERT(isRematerializedFrame());
-  return false;
-}
-
-inline bool AbstractFramePtr::isDebuggee() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->isDebuggee();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->isDebuggee();
-  }
-  if (isWasmDebugFrame()) {
-    return asWasmDebugFrame()->isDebuggee();
-  }
-  return asRematerializedFrame()->isDebuggee();
-}
-
-inline void AbstractFramePtr::setIsDebuggee() {
-  if (isInterpreterFrame()) {
-    asInterpreterFrame()->setIsDebuggee();
-  } else if (isBaselineFrame()) {
-    asBaselineFrame()->setIsDebuggee();
-  } else if (isWasmDebugFrame()) {
-    asWasmDebugFrame()->setIsDebuggee();
-  } else {
-    asRematerializedFrame()->setIsDebuggee();
-  }
-}
-
-inline void AbstractFramePtr::unsetIsDebuggee() {
-  if (isInterpreterFrame()) {
-    asInterpreterFrame()->unsetIsDebuggee();
-  } else if (isBaselineFrame()) {
-    asBaselineFrame()->unsetIsDebuggee();
-  } else if (isWasmDebugFrame()) {
-    asWasmDebugFrame()->unsetIsDebuggee();
-  } else {
-    asRematerializedFrame()->unsetIsDebuggee();
-  }
-}
-
-inline bool AbstractFramePtr::isConstructing() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->isConstructing();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->isConstructing();
-  }
-  if (isRematerializedFrame()) {
-    return asRematerializedFrame()->isConstructing();
-  }
-  MOZ_CRASH("Unexpected frame");
-}
-
-inline bool AbstractFramePtr::hasArgs() const { return isFunctionFrame(); }
-
-inline bool AbstractFramePtr::hasScript() const { return !isWasmDebugFrame(); }
-
-inline JSScript* AbstractFramePtr::script() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->script();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->script();
-  }
-  return asRematerializedFrame()->script();
-}
-
-inline wasm::Instance* AbstractFramePtr::wasmInstance() const {
-  return asWasmDebugFrame()->instance();
-}
-
-inline GlobalObject* AbstractFramePtr::global() const {
-  if (isWasmDebugFrame()) {
-    return asWasmDebugFrame()->global();
-  }
-  return &script()->global();
-}
-
-inline bool AbstractFramePtr::hasGlobal(const GlobalObject* global) const {
-  if (isWasmDebugFrame()) {
-    return asWasmDebugFrame()->hasGlobal(global);
-  }
-  return script()->hasGlobal(global);
-}
-
-inline JSFunction* AbstractFramePtr::callee() const {
-  if (isInterpreterFrame()) {
-    return &asInterpreterFrame()->callee();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->callee();
-  }
-  return asRematerializedFrame()->callee();
-}
-
-inline Value AbstractFramePtr::calleev() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->calleev();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->calleev();
-  }
-  return asRematerializedFrame()->calleev();
-}
-
-inline bool AbstractFramePtr::isFunctionFrame() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->isFunctionFrame();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->isFunctionFrame();
-  }
-  if (isWasmDebugFrame()) {
-    return false;
-  }
-  return asRematerializedFrame()->isFunctionFrame();
-}
-
-inline bool AbstractFramePtr::isGeneratorFrame() const {
-  if (!isFunctionFrame()) {
-    return false;
-  }
-  JSScript* s = script();
-  return s->isGenerator() || s->isAsync();
-}
-
-inline bool AbstractFramePtr::isNonStrictDirectEvalFrame() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->isNonStrictDirectEvalFrame();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->isNonStrictDirectEvalFrame();
-  }
-  MOZ_ASSERT(isRematerializedFrame());
-  return false;
-}
+}  // namespace js
 
-inline bool AbstractFramePtr::isStrictEvalFrame() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->isStrictEvalFrame();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->isStrictEvalFrame();
-  }
-  MOZ_ASSERT(isRematerializedFrame());
-  return false;
-}
-
-inline Value* AbstractFramePtr::argv() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->argv();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->argv();
-  }
-  return asRematerializedFrame()->argv();
-}
-
-inline bool AbstractFramePtr::hasArgsObj() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->hasArgsObj();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->hasArgsObj();
-  }
-  return asRematerializedFrame()->hasArgsObj();
-}
-
-inline ArgumentsObject& AbstractFramePtr::argsObj() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->argsObj();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->argsObj();
-  }
-  return asRematerializedFrame()->argsObj();
-}
-
-inline void AbstractFramePtr::initArgsObj(ArgumentsObject& argsobj) const {
-  if (isInterpreterFrame()) {
-    asInterpreterFrame()->initArgsObj(argsobj);
-    return;
-  }
-  asBaselineFrame()->initArgsObj(argsobj);
-}
-
-inline bool AbstractFramePtr::prevUpToDate() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->prevUpToDate();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->prevUpToDate();
-  }
-  if (isWasmDebugFrame()) {
-    return asWasmDebugFrame()->prevUpToDate();
-  }
-  return asRematerializedFrame()->prevUpToDate();
-}
-
-inline void AbstractFramePtr::setPrevUpToDate() const {
-  if (isInterpreterFrame()) {
-    asInterpreterFrame()->setPrevUpToDate();
-    return;
-  }
-  if (isBaselineFrame()) {
-    asBaselineFrame()->setPrevUpToDate();
-    return;
-  }
-  if (isWasmDebugFrame()) {
-    asWasmDebugFrame()->setPrevUpToDate();
-    return;
-  }
-  asRematerializedFrame()->setPrevUpToDate();
-}
-
-inline void AbstractFramePtr::unsetPrevUpToDate() const {
-  if (isInterpreterFrame()) {
-    asInterpreterFrame()->unsetPrevUpToDate();
-    return;
-  }
-  if (isBaselineFrame()) {
-    asBaselineFrame()->unsetPrevUpToDate();
-    return;
-  }
-  if (isWasmDebugFrame()) {
-    asWasmDebugFrame()->unsetPrevUpToDate();
-    return;
-  }
-  asRematerializedFrame()->unsetPrevUpToDate();
-}
-
-inline Value& AbstractFramePtr::thisArgument() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->thisArgument();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->thisArgument();
-  }
-  return asRematerializedFrame()->thisArgument();
-}
-
-inline Value AbstractFramePtr::newTarget() const {
-  if (isInterpreterFrame()) {
-    return asInterpreterFrame()->newTarget();
-  }
-  if (isBaselineFrame()) {
-    return asBaselineFrame()->newTarget();
-  }
-  return asRematerializedFrame()->newTarget();
-}
-
-inline bool AbstractFramePtr::debuggerNeedsCheckPrimitiveReturn() const {
-  if (isWasmDebugFrame()) {
-    return false;
-  }
-  return script()->isDerivedClassConstructor();
-}
-
-ActivationEntryMonitor::ActivationEntryMonitor(JSContext* cx)
-    : cx_(cx), entryMonitor_(cx->entryMonitor) {
-  cx->entryMonitor = nullptr;
-}
-
-ActivationEntryMonitor::ActivationEntryMonitor(JSContext* cx,
-                                               InterpreterFrame* entryFrame)
-    : ActivationEntryMonitor(cx) {
-  if (MOZ_UNLIKELY(entryMonitor_)) {
-    init(cx, entryFrame);
-  }
-}
-
-ActivationEntryMonitor::ActivationEntryMonitor(JSContext* cx,
-                                               jit::CalleeToken entryToken)
-    : ActivationEntryMonitor(cx) {
-  if (MOZ_UNLIKELY(entryMonitor_)) {
-    init(cx, entryToken);
-  }
-}
-
-ActivationEntryMonitor::~ActivationEntryMonitor() {
-  if (entryMonitor_) {
-    entryMonitor_->Exit(cx_);
-  }
-
-  cx_->entryMonitor = entryMonitor_;
-}
-
-Activation::Activation(JSContext* cx, Kind kind)
-    : cx_(cx),
-      compartment_(cx->compartment()),
-      prev_(cx->activation_),
-      prevProfiling_(prev_ ? prev_->mostRecentProfiling() : nullptr),
-      hideScriptedCallerCount_(0),
-      frameCache_(cx),
-      asyncStack_(cx, cx->asyncStackForNewActivations()),
-      asyncCause_(cx->asyncCauseForNewActivations),
-      asyncCallIsExplicit_(cx->asyncCallIsExplicit),
-      kind_(kind) {
-  cx->asyncStackForNewActivations() = nullptr;
-  cx->asyncCauseForNewActivations = nullptr;
-  cx->asyncCallIsExplicit = false;
-  cx->activation_ = this;
-}
-
-Activation::~Activation() {
-  MOZ_ASSERT_IF(isProfiling(), this != cx_->profilingActivation_);
-  MOZ_ASSERT(cx_->activation_ == this);
-  MOZ_ASSERT(hideScriptedCallerCount_ == 0);
-  cx_->activation_ = prev_;
-  cx_->asyncCauseForNewActivations = asyncCause_;
-  cx_->asyncStackForNewActivations() = asyncStack_;
-  cx_->asyncCallIsExplicit = asyncCallIsExplicit_;
-}
-
-bool Activation::isProfiling() const {
-  if (isInterpreter()) {
-    return asInterpreter()->isProfiling();
-  }
-
-  MOZ_ASSERT(isJit());
-  return asJit()->isProfiling();
-}
-
-Activation* Activation::mostRecentProfiling() {
-  if (isProfiling()) {
-    return this;
-  }
-  return prevProfiling_;
-}
-
-inline LiveSavedFrameCache* Activation::getLiveSavedFrameCache(JSContext* cx) {
-  if (!frameCache_.get().initialized() && !frameCache_.get().init(cx)) {
-    return nullptr;
-  }
-  return frameCache_.address();
-}
-
-InterpreterActivation::InterpreterActivation(RunState& state, JSContext* cx,
-                                             InterpreterFrame* entryFrame)
-    : Activation(cx, Interpreter),
-      entryFrame_(entryFrame),
-      opMask_(0)
-#ifdef DEBUG
-      ,
-      oldFrameCount_(cx->interpreterStack().frameCount_)
-#endif
-{
-  regs_.prepareToRun(*entryFrame, state.script());
-  MOZ_ASSERT(regs_.pc == state.script()->code());
-}
-
-InterpreterActivation::~InterpreterActivation() {
-  // Pop all inline frames.
-  while (regs_.fp() != entryFrame_) {
-    popInlineFrame(regs_.fp());
-  }
-
-  MOZ_ASSERT(oldFrameCount_ == cx_->interpreterStack().frameCount_);
-  MOZ_ASSERT_IF(oldFrameCount_ == 0,
-                cx_->interpreterStack().allocator_.used() == 0);
-
-  if (entryFrame_) {
-    cx_->interpreterStack().releaseFrame(entryFrame_);
-  }
-}
-
-inline bool InterpreterActivation::pushInlineFrame(
-    const CallArgs& args, HandleScript script, MaybeConstruct constructing) {
-  if (!cx_->interpreterStack().pushInlineFrame(cx_, regs_, args, script,
-                                               constructing)) {
-    return false;
-  }
-  MOZ_ASSERT(regs_.fp()->script()->compartment() == compartment());
-  return true;
-}
-
-inline void InterpreterActivation::popInlineFrame(InterpreterFrame* frame) {
-  (void)frame;  // Quell compiler warning.
-  MOZ_ASSERT(regs_.fp() == frame);
-  MOZ_ASSERT(regs_.fp() != entryFrame_);
-
-  cx_->interpreterStack().popInlineFrame(regs_);
-}
-
-inline bool InterpreterActivation::resumeGeneratorFrame(HandleFunction callee,
-                                                        HandleObject envChain) {
-  InterpreterStack& stack = cx_->interpreterStack();
-  if (!stack.resumeGeneratorCallFrame(cx_, regs_, callee, envChain)) {
-    return false;
-  }
-
-  MOZ_ASSERT(regs_.fp()->script()->compartment() == compartment_);
-  return true;
-}
-
-/* static */ inline mozilla::Maybe<LiveSavedFrameCache::FramePtr>
-LiveSavedFrameCache::FramePtr::create(const FrameIter& iter) {
-  if (iter.done()) {
-    return mozilla::Nothing();
-  }
-
-  if (iter.isPhysicalJitFrame()) {
-    return mozilla::Some(FramePtr(iter.physicalJitFrame()));
-  }
-
-  if (!iter.hasUsableAbstractFramePtr()) {
-    return mozilla::Nothing();
-  }
-
-  auto afp = iter.abstractFramePtr();
-
-  if (afp.isInterpreterFrame()) {
-    return mozilla::Some(FramePtr(afp.asInterpreterFrame()));
-  }
-  if (afp.isWasmDebugFrame()) {
-    return mozilla::Some(FramePtr(afp.asWasmDebugFrame()));
-  }
-  if (afp.isRematerializedFrame()) {
-    return mozilla::Some(FramePtr(afp.asRematerializedFrame()));
-  }
-
-  MOZ_CRASH("unexpected frame type");
-}
-
-/* static */ inline LiveSavedFrameCache::FramePtr
-LiveSavedFrameCache::FramePtr::create(AbstractFramePtr afp) {
-  MOZ_ASSERT(afp);
-
-  if (afp.isBaselineFrame()) {
-    js::jit::CommonFrameLayout* common = afp.asBaselineFrame()->framePrefix();
-    return FramePtr(common);
-  }
-  if (afp.isInterpreterFrame()) {
-    return FramePtr(afp.asInterpreterFrame());
-  }
-  if (afp.isWasmDebugFrame()) {
-    return FramePtr(afp.asWasmDebugFrame());
-  }
-  if (afp.isRematerializedFrame()) {
-    return FramePtr(afp.asRematerializedFrame());
-  }
-
-  MOZ_CRASH("unexpected frame type");
-}
-
-struct LiveSavedFrameCache::FramePtr::HasCachedMatcher {
-  template <typename Frame>
-  bool operator()(Frame* f) const {
-    return f->hasCachedSavedFrame();
-  }
-};
-
-inline bool LiveSavedFrameCache::FramePtr::hasCachedSavedFrame() const {
-  return ptr.match(HasCachedMatcher());
-}
-
-struct LiveSavedFrameCache::FramePtr::SetHasCachedMatcher {
-  template <typename Frame>
-  void operator()(Frame* f) {
-    f->setHasCachedSavedFrame();
-  }
-};
-
-inline void LiveSavedFrameCache::FramePtr::setHasCachedSavedFrame() {
-  ptr.match(SetHasCachedMatcher());
-}
-
-struct LiveSavedFrameCache::FramePtr::ClearHasCachedMatcher {
-  template <typename Frame>
-  void operator()(Frame* f) {
-    f->clearHasCachedSavedFrame();
-  }
-};
-
-inline void LiveSavedFrameCache::FramePtr::clearHasCachedSavedFrame() {
-  ptr.match(ClearHasCachedMatcher());
-}
-
-} /* namespace js */
-
-#endif /* vm_Stack_inl_h */
+#endif  // vm_FrameIter_inl_h
copy from js/src/vm/Stack.cpp
copy to js/src/vm/FrameIter.cpp
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/FrameIter.cpp
@@ -1,461 +1,64 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * vim: set ts=8 sts=2 et sw=2 tw=80:
  * 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/. */
 
-#include "vm/Stack-inl.h"
-
-#include <algorithm>
-#include <utility>
-
-#include "debugger/DebugAPI.h"
-#include "gc/Marking.h"
-#include "jit/BaselineFrame.h"
-#include "jit/JitcodeMap.h"
-#include "jit/JitRealm.h"
-#include "jit/shared/CodeGenerator-shared.h"
-#include "vm/JSContext.h"
-#include "vm/Opcodes.h"
-#include "wasm/WasmInstance.h"
-
-#include "jit/JSJitFrameIter-inl.h"
-#include "vm/Compartment-inl.h"
-#include "vm/EnvironmentObject-inl.h"
-#include "vm/Interpreter-inl.h"
-#include "vm/Probes-inl.h"
-
-using namespace js;
-
-using mozilla::ArrayLength;
-using mozilla::DebugOnly;
-using mozilla::Maybe;
-
-/*****************************************************************************/
-
-void InterpreterFrame::initExecuteFrame(JSContext* cx, HandleScript script,
-                                        AbstractFramePtr evalInFramePrev,
-                                        const Value& newTargetValue,
-                                        HandleObject envChain) {
-  flags_ = 0;
-  script_ = script;
-
-  // newTarget = NullValue is an initial sentinel for "please fill me in from
-  // the stack". It should never be passed from Ion code.
-  RootedValue newTarget(cx, newTargetValue);
-  if (script->isDirectEvalInFunction()) {
-    FrameIter iter(cx);
-    if (newTarget.isNull() && iter.hasScript() &&
-        iter.script()->bodyScope()->hasOnChain(ScopeKind::Function)) {
-      newTarget = iter.newTarget();
-    }
-  } else if (evalInFramePrev) {
-    if (newTarget.isNull() && evalInFramePrev.hasScript() &&
-        evalInFramePrev.script()->bodyScope()->hasOnChain(
-            ScopeKind::Function)) {
-      newTarget = evalInFramePrev.newTarget();
-    }
-  }
+#include "vm/FrameIter-inl.h"
 
-  Value* dstvp = (Value*)this - 1;
-  dstvp[0] = newTarget;
-
-  envChain_ = envChain.get();
-  prev_ = nullptr;
-  prevpc_ = nullptr;
-  prevsp_ = nullptr;
-
-  evalInFramePrev_ = evalInFramePrev;
-  MOZ_ASSERT_IF(evalInFramePrev, isDebuggerEvalFrame());
-
-  if (script->isDebuggee()) {
-    setIsDebuggee();
-  }
-
-#ifdef DEBUG
-  Debug_SetValueRangeToCrashOnTouch(&rval_, 1);
-#endif
-}
-
-bool InterpreterFrame::isNonGlobalEvalFrame() const {
-  return isEvalFrame() && script()->bodyScope()->as<EvalScope>().isNonGlobal();
-}
+#include "mozilla/Assertions.h"  // MOZ_ASSERT, MOZ_CRASH
+#include "mozilla/MaybeOneOf.h"  // mozilla::MaybeOneOf
 
-ArrayObject* InterpreterFrame::createRestParameter(JSContext* cx) {
-  MOZ_ASSERT(script()->hasRest());
-  unsigned nformal = callee().nargs() - 1, nactual = numActualArgs();
-  unsigned nrest = (nactual > nformal) ? nactual - nformal : 0;
-  Value* restvp = argv() + nformal;
-  return ObjectGroup::newArrayObject(cx, restvp, nrest, GenericObject,
-                                     ObjectGroup::NewArrayKind::UnknownIndex);
-}
-
-static inline void AssertScopeMatchesEnvironment(Scope* scope,
-                                                 JSObject* originalEnv) {
-#ifdef DEBUG
-  JSObject* env = originalEnv;
-  for (ScopeIter si(scope); si; si++) {
-    if (si.kind() == ScopeKind::NonSyntactic) {
-      while (env->is<WithEnvironmentObject>() ||
-             env->is<NonSyntacticVariablesObject>() ||
-             (env->is<LexicalEnvironmentObject>() &&
-              !env->as<LexicalEnvironmentObject>().isSyntactic())) {
-        MOZ_ASSERT(!IsSyntacticEnvironment(env));
-        env = &env->as<EnvironmentObject>().enclosingEnvironment();
-      }
-    } else if (si.hasSyntacticEnvironment()) {
-      switch (si.kind()) {
-        case ScopeKind::Function:
-          MOZ_ASSERT(env->as<CallObject>()
-                         .callee()
-                         .maybeCanonicalFunction()
-                         ->nonLazyScript() ==
-                     si.scope()->as<FunctionScope>().script());
-          env = &env->as<CallObject>().enclosingEnvironment();
-          break;
+#include <stddef.h>  // size_t
+#include <stdint.h>  // uint8_t, uint32_t
+#include <stdlib.h>  // getenv
 
-        case ScopeKind::FunctionBodyVar:
-        case ScopeKind::ParameterExpressionVar:
-          MOZ_ASSERT(&env->as<VarEnvironmentObject>().scope() == si.scope());
-          env = &env->as<VarEnvironmentObject>().enclosingEnvironment();
-          break;
-
-        case ScopeKind::Lexical:
-        case ScopeKind::SimpleCatch:
-        case ScopeKind::Catch:
-        case ScopeKind::NamedLambda:
-        case ScopeKind::StrictNamedLambda:
-        case ScopeKind::FunctionLexical:
-          MOZ_ASSERT(&env->as<LexicalEnvironmentObject>().scope() ==
-                     si.scope());
-          env = &env->as<LexicalEnvironmentObject>().enclosingEnvironment();
-          break;
-
-        case ScopeKind::With:
-          MOZ_ASSERT(&env->as<WithEnvironmentObject>().scope() == si.scope());
-          env = &env->as<WithEnvironmentObject>().enclosingEnvironment();
-          break;
-
-        case ScopeKind::Eval:
-        case ScopeKind::StrictEval:
-          env = &env->as<VarEnvironmentObject>().enclosingEnvironment();
-          break;
-
-        case ScopeKind::Global:
-          MOZ_ASSERT(env->as<LexicalEnvironmentObject>().isGlobal());
-          env = &env->as<LexicalEnvironmentObject>().enclosingEnvironment();
-          MOZ_ASSERT(env->is<GlobalObject>());
-          break;
-
-        case ScopeKind::NonSyntactic:
-          MOZ_CRASH("NonSyntactic should not have a syntactic environment");
-          break;
-
-        case ScopeKind::Module:
-          MOZ_ASSERT(&env->as<ModuleEnvironmentObject>().module() ==
-                     si.scope()->as<ModuleScope>().module());
-          env = &env->as<ModuleEnvironmentObject>().enclosingEnvironment();
-          break;
-
-        case ScopeKind::WasmInstance:
-          env =
-              &env->as<WasmInstanceEnvironmentObject>().enclosingEnvironment();
-          break;
-
-        case ScopeKind::WasmFunction:
-          env = &env->as<WasmFunctionCallObject>().enclosingEnvironment();
-          break;
-      }
-    }
-  }
-
-  // In the case of a non-syntactic env chain, the immediate parent of the
-  // outermost non-syntactic env may be the global lexical env, or, if
-  // called from Debugger, a DebugEnvironmentProxy.
-  //
-  // In the case of a syntactic env chain, the outermost env is always a
-  // GlobalObject.
-  MOZ_ASSERT(env->is<GlobalObject>() || IsGlobalLexicalEnvironment(env) ||
-             env->is<DebugEnvironmentProxy>());
-#endif
-}
-
-static inline void AssertScopeMatchesEnvironment(InterpreterFrame* fp,
-                                                 jsbytecode* pc) {
-#ifdef DEBUG
-  // If we OOMed before fully initializing the environment chain, the scope
-  // and environment will definitely mismatch.
-  if (fp->script()->initialEnvironmentShape() && fp->hasInitialEnvironment()) {
-    AssertScopeMatchesEnvironment(fp->script()->innermostScope(pc),
-                                  fp->environmentChain());
-  }
-#endif
-}
-
-bool InterpreterFrame::initFunctionEnvironmentObjects(JSContext* cx) {
-  return js::InitFunctionEnvironmentObjects(cx, this);
-}
-
-bool InterpreterFrame::prologue(JSContext* cx) {
-  RootedScript script(cx, this->script());
-
-  MOZ_ASSERT(cx->interpreterRegs().pc == script->code());
-  MOZ_ASSERT(cx->realm() == script->realm());
-
-  if (isEvalFrame() || isGlobalFrame()) {
-    HandleObject env = environmentChain();
-    if (!CheckGlobalOrEvalDeclarationConflicts(cx, env, script)) {
-      // Treat this as a script entry, for consistency with Ion.
-      if (script->trackRecordReplayProgress()) {
-        mozilla::recordreplay::AdvanceExecutionProgressCounter();
-      }
-      return false;
-    }
-    return probes::EnterScript(cx, script, nullptr, this);
-  }
-
-  if (isModuleFrame()) {
-    return probes::EnterScript(cx, script, nullptr, this);
-  }
-
-  MOZ_ASSERT(isFunctionFrame());
-
-  // At this point, we've yet to push any environments. Check that they
-  // match the enclosing scope.
-  AssertScopeMatchesEnvironment(script->enclosingScope(), environmentChain());
+#include "jit/BaselineFrame.h"  // js::jit::BaselineFrame
+#include "jit/JSJitFrameIter.h"  // js::jit::{FrameType,InlineFrameIterator,JSJitFrameIter,MaybeReadFallback,SnapshotIterator}
+#include "js/GCAPI.h"  // JS::AutoSuppressGCAnalysis
+#include "js/Principals.h"  // JSSubsumesOp
+#include "js/RootingAPI.h"  // JS::Rooted
+#include "vm/Activation.h"  // js::Activation{,Iterator}
+#include "vm/EnvironmentObject.h"  // js::CallObject
+#include "vm/JitActivation.h"  // js::jit::JitActivation
+#include "vm/JSContext.h"  // JSContext
+#include "vm/JSFunction.h"  // js::CanReuseScriptForClone, js::FunctionFlags, JSFunction
+#include "vm/JSScript.h"  // js::PCToLineNumber, JSScript, js::ScriptSource
+#include "vm/Runtime.h"  // JSRuntime
+#include "vm/Stack.h"  // js::{AbstractFramePtr,InterpreterFrame,MaybeCheckAliasing}
+#include "wasm/WasmFrameIter.h"  // js::wasm::WasmFrameIter
+#include "wasm/WasmInstance.h"  // js::wasm::Instance
 
-  if (callee().needsFunctionEnvironmentObjects() &&
-      !initFunctionEnvironmentObjects(cx)) {
-    return false;
-  }
-
-  MOZ_ASSERT_IF(isConstructing(),
-                thisArgument().isObject() ||
-                    thisArgument().isMagic(JS_UNINITIALIZED_LEXICAL));
-
-  return probes::EnterScript(cx, script, script->function(), this);
-}
-
-void InterpreterFrame::epilogue(JSContext* cx, jsbytecode* pc) {
-  RootedScript script(cx, this->script());
-  MOZ_ASSERT(cx->realm() == script->realm());
-  probes::ExitScript(cx, script, script->function(),
-                     hasPushedGeckoProfilerFrame());
-
-  // Check that the scope matches the environment at the point of leaving
-  // the frame.
-  AssertScopeMatchesEnvironment(this, pc);
-
-  EnvironmentIter ei(cx, this, pc);
-  UnwindAllEnvironmentsInFrame(cx, ei);
-
-  if (isFunctionFrame()) {
-    if (!callee().isGenerator() && !callee().isAsync() && isConstructing() &&
-        thisArgument().isObject() && returnValue().isPrimitive()) {
-      setReturnValue(thisArgument());
-    }
-
-    return;
-  }
-
-  MOZ_ASSERT(isEvalFrame() || isGlobalFrame() || isModuleFrame());
-}
-
-bool InterpreterFrame::checkReturn(JSContext* cx, HandleValue thisv) {
-  MOZ_ASSERT(script()->isDerivedClassConstructor());
-  MOZ_ASSERT(isFunctionFrame());
-  MOZ_ASSERT(callee().isClassConstructor());
-
-  HandleValue retVal = returnValue();
-  if (retVal.isObject()) {
-    return true;
-  }
-
-  if (!retVal.isUndefined()) {
-    ReportValueError(cx, JSMSG_BAD_DERIVED_RETURN, JSDVG_IGNORE_STACK, retVal,
-                     nullptr);
-    return false;
-  }
+#include "jit/JSJitFrameIter-inl.h"  // js::jit::JSJitFrameIter::baselineFrame{,NumValueSlots}
+#include "vm/Stack-inl.h"  // js::AbstractFramePtr::*
 
-  if (thisv.isMagic(JS_UNINITIALIZED_LEXICAL)) {
-    return ThrowUninitializedThis(cx, this);
-  }
-
-  setReturnValue(thisv);
-  return true;
-}
-
-bool InterpreterFrame::pushVarEnvironment(JSContext* cx, HandleScope scope) {
-  return js::PushVarEnvironmentObject(cx, scope, this);
-}
-
-bool InterpreterFrame::pushLexicalEnvironment(JSContext* cx,
-                                              Handle<LexicalScope*> scope) {
-  LexicalEnvironmentObject* env =
-      LexicalEnvironmentObject::createForFrame(cx, scope, this);
-  if (!env) {
-    return false;
-  }
-
-  pushOnEnvironmentChain(*env);
-  return true;
-}
+namespace JS {
+class JS_PUBLIC_API Realm;
+}  // namespace JS
 
-bool InterpreterFrame::freshenLexicalEnvironment(JSContext* cx) {
-  Rooted<LexicalEnvironmentObject*> env(
-      cx, &envChain_->as<LexicalEnvironmentObject>());
-  LexicalEnvironmentObject* fresh = LexicalEnvironmentObject::clone(cx, env);
-  if (!fresh) {
-    return false;
-  }
-
-  replaceInnermostEnvironment(*fresh);
-  return true;
-}
-
-bool InterpreterFrame::recreateLexicalEnvironment(JSContext* cx) {
-  Rooted<LexicalEnvironmentObject*> env(
-      cx, &envChain_->as<LexicalEnvironmentObject>());
-  LexicalEnvironmentObject* fresh = LexicalEnvironmentObject::recreate(cx, env);
-  if (!fresh) {
-    return false;
-  }
-
-  replaceInnermostEnvironment(*fresh);
-  return true;
-}
-
-void InterpreterFrame::trace(JSTracer* trc, Value* sp, jsbytecode* pc) {
-  TraceRoot(trc, &envChain_, "env chain");
-  TraceRoot(trc, &script_, "script");
-
-  if (flags_ & HAS_ARGS_OBJ) {
-    TraceRoot(trc, &argsObj_, "arguments");
-  }
-
-  if (hasReturnValue()) {
-    TraceRoot(trc, &rval_, "rval");
-  }
+namespace js {
+class ArgumentsObject;
+}  // namespace js
 
-  MOZ_ASSERT(sp >= slots());
-
-  if (hasArgs()) {
-    // Trace the callee and |this|. When we're doing a moving GC, we
-    // need to fix up the callee pointer before we use it below, under
-    // numFormalArgs() and script().
-    TraceRootRange(trc, 2, argv_ - 2, "fp callee and this");
-
-    // Trace arguments.
-    unsigned argc = std::max(numActualArgs(), numFormalArgs());
-    TraceRootRange(trc, argc + isConstructing(), argv_, "fp argv");
-  } else {
-    // Trace newTarget.
-    TraceRoot(trc, ((Value*)this) - 1, "stack newTarget");
-  }
-
-  JSScript* script = this->script();
-  size_t nfixed = script->nfixed();
-  size_t nlivefixed = script->calculateLiveFixed(pc);
-
-  if (nfixed == nlivefixed) {
-    // All locals are live.
-    traceValues(trc, 0, sp - slots());
-  } else {
-    // Trace operand stack.
-    traceValues(trc, nfixed, sp - slots());
-
-    // Clear dead block-scoped locals.
-    while (nfixed > nlivefixed) {
-      unaliasedLocal(--nfixed).setUndefined();
-    }
-
-    // Trace live locals.
-    traceValues(trc, 0, nlivefixed);
-  }
-
-  if (auto* debugEnvs = script->realm()->debugEnvs()) {
-    debugEnvs->traceLiveFrame(trc, this);
-  }
-}
-
-void InterpreterFrame::traceValues(JSTracer* trc, unsigned start,
-                                   unsigned end) {
-  if (start < end) {
-    TraceRootRange(trc, end - start, slots() + start, "vm_stack");
-  }
-}
-
-static void TraceInterpreterActivation(JSTracer* trc,
-                                       InterpreterActivation* act) {
-  for (InterpreterFrameIterator frames(act); !frames.done(); ++frames) {
-    InterpreterFrame* fp = frames.frame();
-    fp->trace(trc, frames.sp(), frames.pc());
-  }
-}
+using JS::Realm;
+using JS::Rooted;
+using JS::Value;
 
-void js::TraceInterpreterActivations(JSContext* cx, JSTracer* trc) {
-  for (ActivationIterator iter(cx); !iter.done(); ++iter) {
-    Activation* act = iter.activation();
-    if (act->isInterpreter()) {
-      TraceInterpreterActivation(trc, act->asInterpreter());
-    }
-  }
-}
-
-/*****************************************************************************/
-
-// Unlike the other methods of this class, this method is defined here so that
-// we don't have to #include jsautooplen.h in vm/Stack.h.
-void InterpreterRegs::setToEndOfScript() { sp = fp()->base(); }
-
-/*****************************************************************************/
-
-InterpreterFrame* InterpreterStack::pushInvokeFrame(
-    JSContext* cx, const CallArgs& args, MaybeConstruct constructing) {
-  LifoAlloc::Mark mark = allocator_.mark();
-
-  RootedFunction fun(cx, &args.callee().as<JSFunction>());
-  RootedScript script(cx, fun->nonLazyScript());
-
-  Value* argv;
-  InterpreterFrame* fp = getCallFrame(cx, args, script, constructing, &argv);
-  if (!fp) {
-    return nullptr;
-  }
-
-  fp->mark_ = mark;
-  fp->initCallFrame(nullptr, nullptr, nullptr, *fun, script, argv,
-                    args.length(), constructing);
-  return fp;
-}
-
-InterpreterFrame* InterpreterStack::pushExecuteFrame(
-    JSContext* cx, HandleScript script, const Value& newTargetValue,
-    HandleObject envChain, AbstractFramePtr evalInFrame) {
-  LifoAlloc::Mark mark = allocator_.mark();
-
-  unsigned nvars = 1 /* newTarget */ + script->nslots();
-  uint8_t* buffer =
-      allocateFrame(cx, sizeof(InterpreterFrame) + nvars * sizeof(Value));
-  if (!buffer) {
-    return nullptr;
-  }
-
-  InterpreterFrame* fp =
-      reinterpret_cast<InterpreterFrame*>(buffer + 1 * sizeof(Value));
-  fp->mark_ = mark;
-  fp->initExecuteFrame(cx, script, evalInFrame, newTargetValue, envChain);
-  fp->initLocals();
-
-  return fp;
-}
-
-/*****************************************************************************/
+using js::AbstractFramePtr;
+using js::ArgumentsObject;
+using js::CallObject;
+using js::FrameIter;
+using js::JitFrameIter;
+using js::jit::JSJitFrameIter;
+using js::NonBuiltinFrameIter;
+using js::NonBuiltinScriptFrameIter;
+using js::OnlyJSJitFrameIter;
+using js::ScriptSource;
 
 JitFrameIter::JitFrameIter(const JitFrameIter& another) { *this = another; }
 
 JitFrameIter& JitFrameIter::operator=(const JitFrameIter& another) {
   MOZ_ASSERT(this != &another);
 
   act_ = another.act_;
   mustUnwindActivation_ = another.mustUnwindActivation_;
@@ -1208,32 +811,32 @@ JSFunction* FrameIter::callee(JSContext*
         return ionInlineFrames_.callee(recover);
       }
       MOZ_ASSERT(jsJitFrame().isBaselineJS());
       return calleeTemplate();
   }
   MOZ_CRASH("Unexpected state");
 }
 
-bool FrameIter::matchCallee(JSContext* cx, HandleFunction fun) const {
-  RootedFunction currentCallee(cx, calleeTemplate());
+bool FrameIter::matchCallee(JSContext* cx, JS::Handle<JSFunction*> fun) const {
+  Rooted<JSFunction*> currentCallee(cx, calleeTemplate());
 
   // As we do not know if the calleeTemplate is the real function, or the
   // template from which it would be cloned, we compare properties which are
   // stable across the cloning of JSFunctions.
   if (((currentCallee->flags().toRaw() ^ fun->flags().toRaw()) &
        FunctionFlags::STABLE_ACROSS_CLONES) != 0 ||
       currentCallee->nargs() != fun->nargs()) {
     return false;
   }
 
   // Use the same condition as |js::CloneFunctionObject|, to know if we should
   // expect both functions to have the same JSScript. If so, and if they are
   // different, then they cannot be equal.
-  RootedObject global(cx, &fun->global());
+  Rooted<JSObject*> global(cx, &fun->global());
   bool useSameScript =
       CanReuseScriptForClone(fun->realm(), currentCallee, global);
   if (useSameScript &&
       (currentCallee->hasScript() != fun->hasScript() ||
        currentCallee->nonLazyScript() != fun->nonLazyScript())) {
     return false;
   }
 
@@ -1294,17 +897,19 @@ bool FrameIter::hasInitialEnvironment(JS
     return abstractFramePtr().hasInitialEnvironment();
   }
 
   if (isWasm()) {
     // See JSFunction::needsFunctionEnvironmentObjects().
     return false;
   }
 
-  MOZ_ASSERT(isJSJit() && isIonScripted());
+  MOZ_ASSERT(isJSJit());
+  MOZ_ASSERT(isIonScripted());
+
   bool hasInitialEnv = false;
   jit::MaybeReadFallback recover(cx, activation()->asJit(), &jsJitFrame());
   ionInlineFrames_.environmentChain(recover, &hasInitialEnv);
 
   return hasInitialEnv;
 }
 
 CallObject& FrameIter::callObj(JSContext* cx) const {
@@ -1449,602 +1054,8 @@ void NonBuiltinFrameIter::settle() {
 
 void NonBuiltinScriptFrameIter::settle() {
   if (!SelfHostedFramesVisible()) {
     while (!done() && script()->selfHosted()) {
       ScriptFrameIter::operator++();
     }
   }
 }
-
-Value ActivationEntryMonitor::asyncStack(JSContext* cx) {
-  RootedValue stack(cx, ObjectOrNullValue(cx->asyncStackForNewActivations()));
-  if (!cx->compartment()->wrap(cx, &stack)) {
-    cx->clearPendingException();
-    return UndefinedValue();
-  }
-  return stack;
-}
-
-void ActivationEntryMonitor::init(JSContext* cx, InterpreterFrame* entryFrame) {
-  // The InterpreterFrame is not yet part of an Activation, so it won't
-  // be traced if we trigger GC here. Suppress GC to avoid this.
-  gc::AutoSuppressGC suppressGC(cx);
-  RootedValue stack(cx, asyncStack(cx));
-  const char* asyncCause = cx->asyncCauseForNewActivations;
-  if (entryFrame->isFunctionFrame()) {
-    entryMonitor_->Entry(cx, &entryFrame->callee(), stack, asyncCause);
-  } else {
-    entryMonitor_->Entry(cx, entryFrame->script(), stack, asyncCause);
-  }
-}
-
-void ActivationEntryMonitor::init(JSContext* cx, jit::CalleeToken entryToken) {
-  // The CalleeToken is not traced at this point and we also don't want
-  // a GC to discard the code we're about to enter, so we suppress GC.
-  gc::AutoSuppressGC suppressGC(cx);
-  RootedValue stack(cx, asyncStack(cx));
-  const char* asyncCause = cx->asyncCauseForNewActivations;
-  if (jit::CalleeTokenIsFunction(entryToken)) {
-    entryMonitor_->Entry(cx_, jit::CalleeTokenToFunction(entryToken), stack,
-                         asyncCause);
-  } else {
-    entryMonitor_->Entry(cx_, jit::CalleeTokenToScript(entryToken), stack,
-                         asyncCause);
-  }
-}
-
-/*****************************************************************************/
-
-jit::JitActivation::JitActivation(JSContext* cx)
-    : Activation(cx, Jit),
-      packedExitFP_(nullptr),
-      encodedWasmExitReason_(0),
-      prevJitActivation_(cx->jitActivation),
-      rematerializedFrames_(),
-      ionRecovery_(cx),
-      bailoutData_(nullptr),
-      lastProfilingFrame_(nullptr),
-      lastProfilingCallSite_(nullptr) {
-  cx->jitActivation = this;
-  registerProfiling();
-}
-
-jit::JitActivation::~JitActivation() {
-  if (isProfiling()) {
-    unregisterProfiling();
-  }
-  cx_->jitActivation = prevJitActivation_;
-
-  // All reocvered value are taken from activation during the bailout.
-  MOZ_ASSERT(ionRecovery_.empty());
-
-  // The BailoutFrameInfo should have unregistered itself from the
-  // JitActivations.
-  MOZ_ASSERT(!bailoutData_);
-
-  // Traps get handled immediately.
-  MOZ_ASSERT(!isWasmTrapping());
-
-  clearRematerializedFrames();
-}
-
-void jit::JitActivation::setBailoutData(jit::BailoutFrameInfo* bailoutData) {
-  MOZ_ASSERT(!bailoutData_);
-  bailoutData_ = bailoutData;
-}
-
-void jit::JitActivation::cleanBailoutData() {
-  MOZ_ASSERT(bailoutData_);
-  bailoutData_ = nullptr;
-}
-
-void jit::JitActivation::removeRematerializedFrame(uint8_t* top) {
-  if (!rematerializedFrames_) {
-    return;
-  }
-
-  if (RematerializedFrameTable::Ptr p = rematerializedFrames_->lookup(top)) {
-    rematerializedFrames_->remove(p);
-  }
-}
-
-void jit::JitActivation::clearRematerializedFrames() {
-  if (!rematerializedFrames_) {
-    return;
-  }
-
-  for (RematerializedFrameTable::Enum e(*rematerializedFrames_); !e.empty();
-       e.popFront()) {
-    e.removeFront();
-  }
-}
-
-jit::RematerializedFrame* jit::JitActivation::getRematerializedFrame(
-    JSContext* cx, const JSJitFrameIter& iter, size_t inlineDepth) {
-  MOZ_ASSERT(iter.activation() == this);
-  MOZ_ASSERT(iter.isIonScripted());
-
-  if (!rematerializedFrames_) {
-    rematerializedFrames_ = cx->make_unique<RematerializedFrameTable>(cx);
-    if (!rematerializedFrames_) {
-      return nullptr;
-    }
-  }
-
-  uint8_t* top = iter.fp();
-  RematerializedFrameTable::AddPtr p = rematerializedFrames_->lookupForAdd(top);
-  if (!p) {
-    RematerializedFrameVector frames(cx);
-
-    // The unit of rematerialization is an uninlined frame and its inlined
-    // frames. Since inlined frames do not exist outside of snapshots, it
-    // is impossible to synchronize their rematerialized copies to
-    // preserve identity. Therefore, we always rematerialize an uninlined
-    // frame and all its inlined frames at once.
-    InlineFrameIterator inlineIter(cx, &iter);
-    MaybeReadFallback recover(cx, this, &iter);
-
-    // Frames are often rematerialized with the cx inside a Debugger's
-    // realm. To recover slots and to create CallObjects, we need to
-    // be in the script's realm.
-    AutoRealmUnchecked ar(cx, iter.script()->realm());
-
-    if (!RematerializedFrame::RematerializeInlineFrames(cx, top, inlineIter,
-                                                        recover, frames)) {
-      return nullptr;
-    }
-
-    if (!rematerializedFrames_->add(p, top, std::move(frames))) {
-      ReportOutOfMemory(cx);
-      return nullptr;
-    }
-
-    // See comment in unsetPrevUpToDateUntil.
-    DebugEnvironments::unsetPrevUpToDateUntil(cx,
-                                              p->value()[inlineDepth].get());
-  }
-
-  return p->value()[inlineDepth].get();
-}
-
-jit::RematerializedFrame* jit::JitActivation::lookupRematerializedFrame(
-    uint8_t* top, size_t inlineDepth) {
-  if (!rematerializedFrames_) {
-    return nullptr;
-  }
-  if (RematerializedFrameTable::Ptr p = rematerializedFrames_->lookup(top)) {
-    return inlineDepth < p->value().length() ? p->value()[inlineDepth].get()
-                                             : nullptr;
-  }
-  return nullptr;
-}
-
-void jit::JitActivation::removeRematerializedFramesFromDebugger(JSContext* cx,
-                                                                uint8_t* top) {
-  // Ion bailout can fail due to overrecursion and OOM. In such cases we
-  // cannot honor any further Debugger hooks on the frame, and need to
-  // ensure that its Debugger.Frame entry is cleaned up.
-  if (!cx->realm()->isDebuggee() || !rematerializedFrames_) {
-    return;
-  }
-  if (RematerializedFrameTable::Ptr p = rematerializedFrames_->lookup(top)) {
-    for (uint32_t i = 0; i < p->value().length(); i++) {
-      DebugAPI::handleUnrecoverableIonBailoutError(cx, p->value()[i].get());
-    }
-    rematerializedFrames_->remove(p);
-  }
-}
-
-void jit::JitActivation::traceRematerializedFrames(JSTracer* trc) {
-  if (!rematerializedFrames_) {
-    return;
-  }
-  for (RematerializedFrameTable::Enum e(*rematerializedFrames_); !e.empty();
-       e.popFront()) {
-    e.front().value().trace(trc);
-  }
-}
-
-bool jit::JitActivation::registerIonFrameRecovery(
-    RInstructionResults&& results) {
-  // Check that there is no entry in the vector yet.
-  MOZ_ASSERT(!maybeIonFrameRecovery(results.frame()));
-  if (!ionRecovery_.append(std::move(results))) {
-    return false;
-  }
-
-  return true;
-}
-
-jit::RInstructionResults* jit::JitActivation::maybeIonFrameRecovery(
-    JitFrameLayout* fp) {
-  for (RInstructionResults* it = ionRecovery_.begin(); it != ionRecovery_.end();
-       it++) {
-    if (it->frame() == fp) {
-      return it;
-    }
-  }
-
-  return nullptr;
-}
-
-void jit::JitActivation::removeIonFrameRecovery(JitFrameLayout* fp) {
-  RInstructionResults* elem = maybeIonFrameRecovery(fp);
-  if (!elem) {
-    return;
-  }
-
-  ionRecovery_.erase(elem);
-}
-
-void jit::JitActivation::traceIonRecovery(JSTracer* trc) {
-  for (RInstructionResults* it = ionRecovery_.begin(); it != ionRecovery_.end();
-       it++) {
-    it->trace(trc);
-  }
-}
-
-void jit::JitActivation::startWasmTrap(wasm::Trap trap, uint32_t bytecodeOffset,
-                                       const wasm::RegisterState& state) {
-  MOZ_ASSERT(!isWasmTrapping());
-
-  bool unwound;
-  wasm::UnwindState unwindState;
-  MOZ_RELEASE_ASSERT(wasm::StartUnwinding(state, &unwindState, &unwound));
-  MOZ_ASSERT(unwound == (trap == wasm::Trap::IndirectCallBadSig));
-
-  void* pc = unwindState.pc;
-  wasm::Frame* fp = unwindState.fp;
-
-  const wasm::Code& code = fp->tls->instance->code();
-  MOZ_RELEASE_ASSERT(&code == wasm::LookupCode(pc));
-
-  // If the frame was unwound, the bytecodeOffset must be recovered from the
-  // callsite so that it is accurate.
-  if (unwound) {
-    bytecodeOffset = code.lookupCallSite(pc)->lineOrBytecode();
-  }
-
-  setWasmExitFP(fp);
-  wasmTrapData_.emplace();
-  wasmTrapData_->resumePC =
-      ((uint8_t*)state.pc) + jit::WasmTrapInstructionLength;
-  wasmTrapData_->unwoundPC = pc;
-  wasmTrapData_->trap = trap;
-  wasmTrapData_->bytecodeOffset = bytecodeOffset;
-
-  MOZ_ASSERT(isWasmTrapping());
-}
-
-void jit::JitActivation::finishWasmTrap() {
-  MOZ_ASSERT(isWasmTrapping());
-  packedExitFP_ = nullptr;
-  wasmTrapData_.reset();
-  MOZ_ASSERT(!isWasmTrapping());
-}
-
-InterpreterFrameIterator& InterpreterFrameIterator::operator++() {
-  MOZ_ASSERT(!done());
-  if (fp_ != activation_->entryFrame_) {
-    pc_ = fp_->prevpc();
-    sp_ = fp_->prevsp();
-    fp_ = fp_->prev();
-  } else {
-    pc_ = nullptr;
-    sp_ = nullptr;
-    fp_ = nullptr;
-  }
-  return *this;
-}
-
-void Activation::registerProfiling() {
-  MOZ_ASSERT(isProfiling());
-  cx_->profilingActivation_ = this;
-}
-
-void Activation::unregisterProfiling() {
-  MOZ_ASSERT(isProfiling());
-  MOZ_ASSERT(cx_->profilingActivation_ == this);
-  cx_->profilingActivation_ = prevProfiling_;
-}
-
-ActivationIterator::ActivationIterator(JSContext* cx)
-    : activation_(cx->activation_) {
-  MOZ_ASSERT(cx == TlsContext.get());
-}
-
-ActivationIterator& ActivationIterator::operator++() {
-  MOZ_ASSERT(activation_);
-  activation_ = activation_->prev();
-  return *this;
-}
-
-JS::ProfilingFrameIterator::ProfilingFrameIterator(
-    JSContext* cx, const RegisterState& state,
-    const Maybe<uint64_t>& samplePositionInProfilerBuffer)
-    : cx_(cx),
-      samplePositionInProfilerBuffer_(samplePositionInProfilerBuffer),
-      activation_(nullptr) {
-  if (!cx->runtime()->geckoProfiler().enabled()) {
-    MOZ_CRASH(
-        "ProfilingFrameIterator called when geckoProfiler not enabled for "
-        "runtime.");
-  }
-
-  if (!cx->profilingActivation()) {
-    return;
-  }
-
-  // If profiler sampling is not enabled, skip.
-  if (!cx->isProfilerSamplingEnabled()) {
-    return;
-  }
-
-  activation_ = cx->profilingActivation();
-
-  MOZ_ASSERT(activation_->isProfiling());
-
-  static_assert(sizeof(wasm::ProfilingFrameIterator) <= StorageSpace &&
-                    sizeof(jit::JSJitProfilingFrameIterator) <= StorageSpace,
-                "ProfilingFrameIterator::storage_ is too small");
-  static_assert(alignof(void*) >= alignof(wasm::ProfilingFrameIterator) &&
-                    alignof(void*) >= alignof(jit::JSJitProfilingFrameIterator),
-                "ProfilingFrameIterator::storage_ is too weakly aligned");
-
-  iteratorConstruct(state);
-  settle();
-}
-
-JS::ProfilingFrameIterator::~ProfilingFrameIterator() {
-  if (!done()) {
-    MOZ_ASSERT(activation_->isProfiling());
-    iteratorDestroy();
-  }
-}
-
-void JS::ProfilingFrameIterator::operator++() {
-  MOZ_ASSERT(!done());
-  MOZ_ASSERT(activation_->isJit());
-  if (isWasm()) {
-    ++wasmIter();
-  } else {
-    ++jsJitIter();
-  }
-  settle();
-}
-
-void JS::ProfilingFrameIterator::settleFrames() {
-  // Handle transition frames (see comment in JitFrameIter::operator++).
-  if (isJSJit() && !jsJitIter().done() &&
-      jsJitIter().frameType() == jit::FrameType::WasmToJSJit) {
-    wasm::Frame* fp = (wasm::Frame*)jsJitIter().fp();
-    iteratorDestroy();
-    new (storage()) wasm::ProfilingFrameIterator(fp);
-    kind_ = Kind::Wasm;
-    MOZ_ASSERT(!wasmIter().done());
-    return;
-  }
-
-  if (isWasm() && wasmIter().done() && wasmIter().unwoundIonCallerFP()) {
-    uint8_t* fp = wasmIter().unwoundIonCallerFP();
-    iteratorDestroy();
-    // Using this ctor will skip the first ion->wasm frame, which is
-    // needed because the profiling iterator doesn't know how to unwind
-    // when the callee has no script.
-    new (storage())
-        jit::JSJitProfilingFrameIterator((jit::CommonFrameLayout*)fp);
-    kind_ = Kind::JSJit;
-    MOZ_ASSERT(!jsJitIter().done());
-    return;
-  }
-}
-
-void JS::ProfilingFrameIterator::settle() {
-  settleFrames();
-  while (iteratorDone()) {
-    iteratorDestroy();
-    activation_ = activation_->prevProfiling();
-    if (!activation_) {
-      return;
-    }
-    iteratorConstruct();
-    settleFrames();
-  }
-}
-
-void JS::ProfilingFrameIterator::iteratorConstruct(const RegisterState& state) {
-  MOZ_ASSERT(!done());
-  MOZ_ASSERT(activation_->isJit());
-
-  jit::JitActivation* activation = activation_->asJit();
-
-  // We want to know if we should start with a wasm profiling frame iterator
-  // or not. To determine this, there are three possibilities:
-  // - we've exited to C++ from wasm, in which case the activation
-  //   exitFP low bit is tagged and we can test hasWasmExitFP().
-  // - we're in wasm code, so we can do a lookup on PC.
-  // - in all the other cases, we're not in wasm or we haven't exited from
-  //   wasm.
-  if (activation->hasWasmExitFP() || wasm::InCompiledCode(state.pc)) {
-    new (storage()) wasm::ProfilingFrameIterator(*activation, state);
-    kind_ = Kind::Wasm;
-    return;
-  }
-
-  new (storage()) jit::JSJitProfilingFrameIterator(cx_, state.pc);
-  kind_ = Kind::JSJit;
-}
-
-void JS::ProfilingFrameIterator::iteratorConstruct() {
-  MOZ_ASSERT(!done());
-  MOZ_ASSERT(activation_->isJit());
-
-  jit::JitActivation* activation = activation_->asJit();
-
-  // The same reasoning as in the above iteratorConstruct variant applies
-  // here, except that it's even simpler: since this activation is higher up
-  // on the stack, it can only have exited to C++, through wasm or ion.
-  if (activation->hasWasmExitFP()) {
-    new (storage()) wasm::ProfilingFrameIterator(*activation);
-    kind_ = Kind::Wasm;
-    return;
-  }
-
-  auto* fp = (jit::ExitFrameLayout*)activation->jsExitFP();
-  new (storage()) jit::JSJitProfilingFrameIterator(fp);
-  kind_ = Kind::JSJit;
-}
-
-void JS::ProfilingFrameIterator::iteratorDestroy() {
-  MOZ_ASSERT(!done());
-  MOZ_ASSERT(activation_->isJit());
-
-  if (isWasm()) {
-    wasmIter().~ProfilingFrameIterator();
-    return;
-  }
-
-  jsJitIter().~JSJitProfilingFrameIterator();
-}
-
-bool JS::ProfilingFrameIterator::iteratorDone() {
-  MOZ_ASSERT(!done());
-  MOZ_ASSERT(activation_->isJit());
-
-  if (isWasm()) {
-    return wasmIter().done();
-  }
-
-  return jsJitIter().done();
-}
-
-void* JS::ProfilingFrameIterator::stackAddress() const {
-  MOZ_ASSERT(!done());
-  MOZ_ASSERT(activation_->isJit());
-
-  if (isWasm()) {
-    return wasmIter().stackAddress();
-  }
-
-  return jsJitIter().stackAddress();
-}
-
-Maybe<JS::ProfilingFrameIterator::Frame>
-JS::ProfilingFrameIterator::getPhysicalFrameAndEntry(
-    jit::JitcodeGlobalEntry* entry) const {
-  void* stackAddr = stackAddress();
-
-  if (isWasm()) {
-    Frame frame;
-    frame.kind = Frame_Wasm;
-    frame.stackAddress = stackAddr;
-    frame.returnAddress_ = nullptr;
-    frame.activation = activation_;
-    frame.label = nullptr;
-    frame.endStackAddress = activation_->asJit()->jsOrWasmExitFP();
-    frame.interpreterScript = nullptr;
-    return mozilla::Some(frame);
-  }
-
-  MOZ_ASSERT(isJSJit());
-
-  // Look up an entry for the return address.
-  void* returnAddr = jsJitIter().resumePCinCurrentFrame();
-  jit::JitcodeGlobalTable* table =
-      cx_->runtime()->jitRuntime()->getJitcodeGlobalTable();
-  if (samplePositionInProfilerBuffer_) {
-    *entry = table->lookupForSamplerInfallible(
-        returnAddr, cx_->runtime(), *samplePositionInProfilerBuffer_);
-  } else {
-    *entry = table->lookupInfallible(returnAddr);
-  }
-
-  MOZ_ASSERT(entry->isIon() || entry->isIonCache() || entry->isBaseline() ||
-             entry->isBaselineInterpreter() || entry->isDummy());
-
-  // Dummy frames produce no stack frames.
-  if (entry->isDummy()) {
-    return mozilla::Nothing();
-  }
-
-  Frame frame;
-  if (entry->isBaselineInterpreter()) {
-    frame.kind = Frame_BaselineInterpreter;
-  } else if (entry->isBaseline()) {
-    frame.kind = Frame_Baseline;
-  } else {
-    frame.kind = Frame_Ion;
-  }
-  frame.stackAddress = stackAddr;
-  if (entry->isBaselineInterpreter()) {
-    frame.label = jsJitIter().baselineInterpreterLabel();
-    jsJitIter().baselineInterpreterScriptPC(&frame.interpreterScript,
-                                            &frame.interpreterPC_);
-    MOZ_ASSERT(frame.interpreterScript);
-    MOZ_ASSERT(frame.interpreterPC_);
-  } else {
-    frame.interpreterScript = nullptr;
-    frame.returnAddress_ = returnAddr;
-    frame.label = nullptr;
-  }
-  frame.activation = activation_;
-  frame.endStackAddress = activation_->asJit()->jsOrWasmExitFP();
-  return mozilla::Some(frame);
-}
-
-uint32_t JS::ProfilingFrameIterator::extractStack(Frame* frames,
-                                                  uint32_t offset,
-                                                  uint32_t end) const {
-  if (offset >= end) {
-    return 0;
-  }
-
-  jit::JitcodeGlobalEntry entry;
-  Maybe<Frame> physicalFrame = getPhysicalFrameAndEntry(&entry);
-
-  // Dummy frames produce no stack frames.
-  if (physicalFrame.isNothing()) {
-    return 0;
-  }
-
-  if (isWasm()) {
-    frames[offset] = physicalFrame.value();
-    frames[offset].label = wasmIter().label();
-    return 1;
-  }
-
-  if (physicalFrame->kind == Frame_BaselineInterpreter) {
-    frames[offset] = physicalFrame.value();
-    return 1;
-  }
-
-  // Extract the stack for the entry.  Assume maximum inlining depth is <64
-  const char* labels[64];
-  uint32_t depth = entry.callStackAtAddr(cx_->runtime(),
-                                         jsJitIter().resumePCinCurrentFrame(),
-                                         labels, ArrayLength(labels));
-  MOZ_ASSERT(depth < ArrayLength(labels));
-  for (uint32_t i = 0; i < depth; i++) {
-    if (offset + i >= end) {
-      return i;
-    }
-    frames[offset + i] = physicalFrame.value();
-    frames[offset + i].label = labels[i];
-  }
-
-  return depth;
-}
-
-Maybe<JS::ProfilingFrameIterator::Frame>
-JS::ProfilingFrameIterator::getPhysicalFrameWithoutLabel() const {
-  jit::JitcodeGlobalEntry unused;
-  return getPhysicalFrameAndEntry(&unused);
-}
-
-bool JS::ProfilingFrameIterator::isWasm() const {
-  MOZ_ASSERT(!done());
-  return kind_ == Kind::Wasm;
-}
-
-bool JS::ProfilingFrameIterator::isJSJit() const {
-  return kind_ == Kind::JSJit;
-}
copy from js/src/vm/Stack.h
copy to js/src/vm/FrameIter.h
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/FrameIter.h
@@ -1,1811 +1,75 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * vim: set ts=8 sts=2 et sw=2 tw=80:
  * 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 vm_Stack_h
-#define vm_Stack_h
+#ifndef vm_FrameIter_h
+#define vm_FrameIter_h
 
-#include "mozilla/Atomics.h"
-#include "mozilla/HashFunctions.h"
-#include "mozilla/Maybe.h"
-#include "mozilla/MaybeOneOf.h"
-#include "mozilla/MemoryReporting.h"
-#include "mozilla/Variant.h"
+#include "mozilla/Assertions.h"  // MOZ_ASSERT
+#include "mozilla/Atomics.h"  // mozilla::Atomic, mozilla::Relaxed
+#include "mozilla/Attributes.h"  // MOZ_IMPLICIT, MOZ_RAII
+#include "mozilla/Maybe.h"  // mozilla::Maybe
+#include "mozilla/MaybeOneOf.h"  // mozilla::MaybeOneOf
 
-#include <algorithm>
+#include <stddef.h>  // size_t
+#include <stdint.h>  // uint8_t, uint32_t, uintptr_t
+
+#include "jstypes.h"  // JS_PUBLIC_API
 
-#include "gc/Rooting.h"
-#ifdef CHECK_OSIPOINT_REGISTERS
-#  include "jit/Registers.h"  // for RegisterDump
-#endif
-#include "jit/JSJitFrameIter.h"
-#include "js/RootingAPI.h"
-#include "js/TypeDecls.h"
-#include "js/UniquePtr.h"
-#include "vm/ArgumentsObject.h"
-#include "vm/JSFunction.h"
-#include "vm/JSScript.h"
-#include "vm/SavedFrame.h"
-#include "wasm/WasmFrameIter.h"
+#include "jit/JSJitFrameIter.h"  // js::jit::{InlineFrameIterator,JSJitFrameIter}
+#include "js/RootingAPI.h"  // JS::Handle, JS::Rooted
+#include "js/TypeDecls.h"  // jsbytecode
+#include "js/UniquePtr.h"  // js::UniquePtr
+#include "js/Value.h"  // JS::Value
+#include "vm/Activation.h"  // js::InterpreterActivation
+#include "vm/Stack.h"  // js::{AbstractFramePtr,MaybeCheckAliasing}
+#include "wasm/WasmConstants.h"  // js::wasm::Trap
+#include "wasm/WasmFrameIter.h"  // js::wasm::{ExitReason,RegisterState,WasmFrameIter}
+#include "wasm/WasmTypes.h"  // js::wasm::{Frame,TrapData}
+
+struct JS_PUBLIC_API JSContext;
+
+class JSAtom;
+class JSFunction;
+class JSObject;
+struct JSPrincipals;
+class JSScript;
 
 namespace JS {
-namespace dbg {
-class JS_PUBLIC_API AutoEntryMonitor;
-}  // namespace dbg
+
+class JS_PUBLIC_API Compartment;
+class JS_PUBLIC_API Realm;
+
 }  // namespace JS
 
 namespace js {
 
-class InterpreterRegs;
+class ArgumentsObject;
 class CallObject;
-class FrameIter;
-class EnvironmentObject;
-class ScriptFrameIter;
-class GeckoProfilerRuntime;
 class InterpreterFrame;
-class LexicalEnvironmentObject;
-class EnvironmentIter;
-class EnvironmentCoordinate;
-
-class SavedFrame;
 
 namespace jit {
 class CommonFrameLayout;
-}
-namespace wasm {
-class DebugFrame;
-class Instance;
-}  // namespace wasm
-
-// [SMDOC] VM stack layout
-//
-// A JSRuntime's stack consists of a linked list of activations. Every
-// activation contains a number of scripted frames that are either running in
-// the interpreter (InterpreterActivation) or JIT code (JitActivation). The
-// frames inside a single activation are contiguous: whenever C++ calls back
-// into JS, a new activation is pushed.
-//
-// Every activation is tied to a single JSContext and JS::Compartment. This
-// means we can reconstruct a given context's stack by skipping activations
-// belonging to other contexts. This happens whenever an embedding enters the JS
-// engine on cx1 and then, from a native called by the JS engine, reenters the
-// VM on cx2.
-
-// Interpreter frames (InterpreterFrame)
-//
-// Each interpreter script activation (global or function code) is given a
-// fixed-size header (js::InterpreterFrame). The frame contains bookkeeping
-// information about the activation and links to the previous frame.
-//
-// The values after an InterpreterFrame in memory are its locals followed by its
-// expression stack. InterpreterFrame::argv_ points to the frame's arguments.
-// Missing formal arguments are padded with |undefined|, so the number of
-// arguments is always >= the number of formals.
-//
-// The top of an activation's current frame's expression stack is pointed to by
-// the activation's "current regs", which contains the stack pointer 'sp'. In
-// the interpreter, sp is adjusted as individual values are pushed and popped
-// from the stack and the InterpreterRegs struct (pointed to by the
-// InterpreterActivation) is a local var of js::Interpret.
-
-enum MaybeCheckAliasing { CHECK_ALIASING = true, DONT_CHECK_ALIASING = false };
-enum MaybeCheckTDZ { CheckTDZ = true, DontCheckTDZ = false };
-
-}  // namespace js
-
-namespace mozilla {
-template <>
-struct IsPod<js::MaybeCheckTDZ> : TrueType {};
-}  // namespace mozilla
-
-/*****************************************************************************/
-
-namespace js {
-
-namespace jit {
-class BaselineFrame;
-class RematerializedFrame;
-}  // namespace jit
-
-/**
- * Pointer to a live JS or WASM stack frame.
- */
-class AbstractFramePtr {
-  friend class FrameIter;
-
-  uintptr_t ptr_;
-
-  enum {
-    Tag_InterpreterFrame = 0x1,
-    Tag_BaselineFrame = 0x2,
-    Tag_RematerializedFrame = 0x3,
-    Tag_WasmDebugFrame = 0x4,
-    TagMask = 0x7
-  };
-
- public:
-  AbstractFramePtr() : ptr_(0) {}
-
-  MOZ_IMPLICIT AbstractFramePtr(InterpreterFrame* fp)
-      : ptr_(fp ? uintptr_t(fp) | Tag_InterpreterFrame : 0) {
-    MOZ_ASSERT_IF(fp, asInterpreterFrame() == fp);
-  }
-
-  MOZ_IMPLICIT AbstractFramePtr(jit::BaselineFrame* fp)
-      : ptr_(fp ? uintptr_t(fp) | Tag_BaselineFrame : 0) {
-    MOZ_ASSERT_IF(fp, asBaselineFrame() == fp);
-  }
-
-  MOZ_IMPLICIT AbstractFramePtr(jit::RematerializedFrame* fp)
-      : ptr_(fp ? uintptr_t(fp) | Tag_RematerializedFrame : 0) {
-    MOZ_ASSERT_IF(fp, asRematerializedFrame() == fp);
-  }
-
-  MOZ_IMPLICIT AbstractFramePtr(wasm::DebugFrame* fp)
-      : ptr_(fp ? uintptr_t(fp) | Tag_WasmDebugFrame : 0) {
-    static_assert(wasm::DebugFrame::Alignment >= TagMask, "aligned");
-    MOZ_ASSERT_IF(fp, asWasmDebugFrame() == fp);
-  }
-
-  static AbstractFramePtr FromRaw(void* raw) {
-    AbstractFramePtr frame;
-    frame.ptr_ = uintptr_t(raw);
-    return frame;
-  }
-
-  bool isInterpreterFrame() const {
-    return (ptr_ & TagMask) == Tag_InterpreterFrame;
-  }
-  InterpreterFrame* asInterpreterFrame() const {
-    MOZ_ASSERT(isInterpreterFrame());
-    InterpreterFrame* res = (InterpreterFrame*)(ptr_ & ~TagMask);
-    MOZ_ASSERT(res);
-    return res;
-  }
-  bool isBaselineFrame() const { return (ptr_ & TagMask) == Tag_BaselineFrame; }
-  jit::BaselineFrame* asBaselineFrame() const {
-    MOZ_ASSERT(isBaselineFrame());
-    jit::BaselineFrame* res = (jit::BaselineFrame*)(ptr_ & ~TagMask);
-    MOZ_ASSERT(res);
-    return res;
-  }
-  bool isRematerializedFrame() const {
-    return (ptr_ & TagMask) == Tag_RematerializedFrame;
-  }
-  jit::RematerializedFrame* asRematerializedFrame() const {
-    MOZ_ASSERT(isRematerializedFrame());
-    jit::RematerializedFrame* res =
-        (jit::RematerializedFrame*)(ptr_ & ~TagMask);
-    MOZ_ASSERT(res);
-    return res;
-  }
-  bool isWasmDebugFrame() const {
-    return (ptr_ & TagMask) == Tag_WasmDebugFrame;
-  }
-  wasm::DebugFrame* asWasmDebugFrame() const {
-    MOZ_ASSERT(isWasmDebugFrame());
-    wasm::DebugFrame* res = (wasm::DebugFrame*)(ptr_ & ~TagMask);
-    MOZ_ASSERT(res);
-    return res;
-  }
-
-  void* raw() const { return reinterpret_cast<void*>(ptr_); }
-
-  bool operator==(const AbstractFramePtr& other) const {
-    return ptr_ == other.ptr_;
-  }
-  bool operator!=(const AbstractFramePtr& other) const {
-    return ptr_ != other.ptr_;
-  }
-
-  explicit operator bool() const { return !!ptr_; }
-
-  inline JSObject* environmentChain() const;
-  inline CallObject& callObj() const;
-  inline bool initFunctionEnvironmentObjects(JSContext* cx);
-  inline bool pushVarEnvironment(JSContext* cx, HandleScope scope);
-  template <typename SpecificEnvironment>
-  inline void pushOnEnvironmentChain(SpecificEnvironment& env);
-  template <typename SpecificEnvironment>
-  inline void popOffEnvironmentChain();
-
-  inline JS::Realm* realm() const;
-
-  inline bool hasInitialEnvironment() const;
-  inline bool isGlobalFrame() const;
-  inline bool isModuleFrame() const;
-  inline bool isEvalFrame() const;
-  inline bool isDebuggerEvalFrame() const;
-
-  inline bool hasScript() const;
-  inline JSScript* script() const;
-  inline wasm::Instance* wasmInstance() const;
-  inline GlobalObject* global() const;
-  inline bool hasGlobal(const GlobalObject* global) const;
-  inline JSFunction* callee() const;
-  inline Value calleev() const;
-  inline Value& thisArgument() const;
-
-  inline bool isConstructing() const;
-  inline Value newTarget() const;
-
-  inline bool debuggerNeedsCheckPrimitiveReturn() const;
-
-  inline bool isFunctionFrame() const;
-  inline bool isGeneratorFrame() const;
-  inline bool isNonStrictDirectEvalFrame() const;
-  inline bool isStrictEvalFrame() const;
-
-  inline unsigned numActualArgs() const;
-  inline unsigned numFormalArgs() const;
-
-  inline Value* argv() const;
-
-  inline bool hasArgs() const;
-  inline bool hasArgsObj() const;
-  inline ArgumentsObject& argsObj() const;
-  inline void initArgsObj(ArgumentsObject& argsobj) const;
-
-  inline Value& unaliasedLocal(uint32_t i);
-  inline Value& unaliasedFormal(
-      unsigned i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING);
-  inline Value& unaliasedActual(
-      unsigned i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING);
-  template <class Op>
-  inline void unaliasedForEachActual(JSContext* cx, Op op);
-
-  inline bool prevUpToDate() const;
-  inline void setPrevUpToDate() const;
-  inline void unsetPrevUpToDate() const;
-
-  inline bool isDebuggee() const;
-  inline void setIsDebuggee();
-  inline void unsetIsDebuggee();
-
-  inline HandleValue returnValue() const;
-  inline void setReturnValue(const Value& rval) const;
-
-  friend void GDBTestInitAbstractFramePtr(AbstractFramePtr&, InterpreterFrame*);
-  friend void GDBTestInitAbstractFramePtr(AbstractFramePtr&,
-                                          jit::BaselineFrame*);
-  friend void GDBTestInitAbstractFramePtr(AbstractFramePtr&,
-                                          jit::RematerializedFrame*);
-  friend void GDBTestInitAbstractFramePtr(AbstractFramePtr& frame,
-                                          wasm::DebugFrame* ptr);
-};
-
-class NullFramePtr : public AbstractFramePtr {
- public:
-  NullFramePtr() : AbstractFramePtr() {}
-};
-
-enum MaybeConstruct { NO_CONSTRUCT = false, CONSTRUCT = true };
-
-/*****************************************************************************/
-
-class InterpreterFrame {
-  enum Flags : uint32_t {
-    CONSTRUCTING = 0x1, /* frame is for a constructor invocation */
-
-    RESUMED_GENERATOR = 0x2, /* frame is for a resumed generator invocation */
-
-    /* Function prologue state */
-    HAS_INITIAL_ENV =
-        0x4,            /* callobj created for function or var env for eval */
-    HAS_ARGS_OBJ = 0x8, /* ArgumentsObject created for needsArgsObj script */
-
-    /* Lazy frame initialization */
-    HAS_RVAL = 0x10, /* frame has rval_ set */
-
-    /* Debugger state */
-    PREV_UP_TO_DATE = 0x20, /* see DebugScopes::updateLiveScopes */
-
-    /*
-     * See comment above 'isDebuggee' in Realm.h for explanation of
-     * invariants of debuggee compartments, scripts, and frames.
-     */
-    DEBUGGEE = 0x40, /* Execution is being observed by Debugger */
-
-    /* Used in tracking calls and profiling (see vm/GeckoProfiler.cpp) */
-    HAS_PUSHED_PROF_FRAME = 0x80, /* Gecko Profiler was notified of entry */
-
-    /*
-     * If set, we entered one of the JITs and ScriptFrameIter should skip
-     * this frame.
-     */
-    RUNNING_IN_JIT = 0x100,
-
-    /*
-     * If set, this frame has been on the stack when
-     * |js::SavedStacks::saveCurrentStack| was called, and so there is a
-     * |js::SavedFrame| object cached for this frame.
-     */
-    HAS_CACHED_SAVED_FRAME = 0x200,
-  };
-
-  mutable uint32_t flags_; /* bits described by Flags */
-  uint32_t nactual_;       /* number of actual arguments, for function frames */
-  JSScript* script_;       /* the script we're executing */
-  JSObject* envChain_;     /* current environment chain */
-  Value rval_;             /* if HAS_RVAL, return value of the frame */
-  ArgumentsObject* argsObj_; /* if HAS_ARGS_OBJ, the call's arguments object */
-
-  /*
-   * Previous frame and its pc and sp. Always nullptr for
-   * InterpreterActivation's entry frame, always non-nullptr for inline
-   * frames.
-   */
-  InterpreterFrame* prev_;
-  jsbytecode* prevpc_;
-  Value* prevsp_;
-
-  void* unused;
-
-  /*
-   * For an eval-in-frame DEBUGGER_EVAL frame, the frame in whose scope
-   * we're evaluating code. Iteration treats this as our previous frame.
-   */
-  AbstractFramePtr evalInFramePrev_;
-
-  Value* argv_;          /* If hasArgs(), points to frame's arguments. */
-  LifoAlloc::Mark mark_; /* Used to release memory for this frame. */
-
-  static void staticAsserts() {
-    JS_STATIC_ASSERT(offsetof(InterpreterFrame, rval_) % sizeof(Value) == 0);
-    JS_STATIC_ASSERT(sizeof(InterpreterFrame) % sizeof(Value) == 0);
-  }
-
-  /*
-   * The utilities are private since they are not able to assert that only
-   * unaliased vars/formals are accessed. Normal code should prefer the
-   * InterpreterFrame::unaliased* members (or InterpreterRegs::stackDepth for
-   * the usual "depth is at least" assertions).
-   */
-  Value* slots() const { return (Value*)(this + 1); }
-  Value* base() const { return slots() + script()->nfixed(); }
-
-  friend class FrameIter;
-  friend class InterpreterRegs;
-  friend class InterpreterStack;
-  friend class jit::BaselineFrame;
-
-  /*
-   * Frame initialization, called by InterpreterStack operations after acquiring
-   * the raw memory for the frame:
-   */
-
-  /* Used for Invoke and Interpret. */
-  void initCallFrame(InterpreterFrame* prev, jsbytecode* prevpc, Value* prevsp,
-                     JSFunction& callee, JSScript* script, Value* argv,
-                     uint32_t nactual, MaybeConstruct constructing);
-
-  /* Used for global and eval frames. */
-  void initExecuteFrame(JSContext* cx, HandleScript script,
-                        AbstractFramePtr prev, const Value& newTargetValue,
-                        HandleObject envChain);
-
- public:
-  /*
-   * Frame prologue/epilogue
-   *
-   * Every stack frame must have 'prologue' called before executing the
-   * first op and 'epilogue' called after executing the last op and before
-   * popping the frame (whether the exit is exceptional or not).
-   *
-   * For inline JS calls/returns, it is easy to call the prologue/epilogue
-   * exactly once. When calling JS from C++, Invoke/Execute push the stack
-   * frame but do *not* call the prologue/epilogue. That means Interpret
-   * must call the prologue/epilogue for the entry frame. This scheme
-   * simplifies jit compilation.
-   *
-   * An important corner case is what happens when an error occurs (OOM,
-   * over-recursed) after pushing the stack frame but before 'prologue' is
-   * called or completes fully. To simplify usage, 'epilogue' does not assume
-   * 'prologue' has completed and handles all the intermediate state details.
-   */
-
-  bool prologue(JSContext* cx);
-  void epilogue(JSContext* cx, jsbytecode* pc);
-
-  bool checkReturn(JSContext* cx, HandleValue thisv);
-
-  bool initFunctionEnvironmentObjects(JSContext* cx);
-
-  /*
-   * Initialize locals of newly-pushed frame to undefined.
-   */
-  void initLocals();
-
-  /*
-   * Stack frame type
-   *
-   * A stack frame may have one of four types, which determines which
-   * members of the frame may be accessed and other invariants:
-   *
-   *  global frame:   execution of global code
-   *  function frame: execution of function code
-   *  module frame:   execution of a module
-   *  eval frame:     execution of eval code
-   */
-
-  bool isGlobalFrame() const { return script_->isGlobalCode(); }
-
-  bool isModuleFrame() const { return script_->isModule(); }
-
-  bool isEvalFrame() const { return script_->isForEval(); }
-
-  bool isFunctionFrame() const { return script_->isFunction(); }
-
-  inline bool isStrictEvalFrame() const {
-    return isEvalFrame() && script()->strict();
-  }
-
-  bool isNonStrictEvalFrame() const {
-    return isEvalFrame() && !script()->strict();
-  }
-
-  bool isNonGlobalEvalFrame() const;
-
-  bool isNonStrictDirectEvalFrame() const {
-    return isNonStrictEvalFrame() && isNonGlobalEvalFrame();
-  }
-
-  /*
-   * Previous frame
-   *
-   * A frame's 'prev' frame is either null or the previous frame pointed to
-   * by cx->regs->fp when this frame was pushed. Often, given two prev-linked
-   * frames, the next-frame is a function or eval that was called by the
-   * prev-frame, but not always: the prev-frame may have called a native that
-   * reentered the VM through JS_CallFunctionValue on the same context
-   * (without calling JS_SaveFrameChain) which pushed the next-frame. Thus,
-   * 'prev' has little semantic meaning and basically just tells the VM what
-   * to set cx->regs->fp to when this frame is popped.
-   */
-
-  InterpreterFrame* prev() const { return prev_; }
-
-  AbstractFramePtr evalInFramePrev() const {
-    MOZ_ASSERT(isEvalFrame());
-    return evalInFramePrev_;
-  }
-
-  /*
-   * (Unaliased) locals and arguments
-   *
-   * Only non-eval function frames have arguments. The arguments pushed by
-   * the caller are the 'actual' arguments. The declared arguments of the
-   * callee are the 'formal' arguments. When the caller passes less actual
-   * arguments, missing formal arguments are padded with |undefined|.
-   *
-   * When a local/formal variable is aliased (accessed by nested closures,
-   * environment operations, or 'arguments'), the canonical location for
-   * that value is the slot of an environment object.  Aliased locals don't
-   * have stack slots assigned to them.  These functions assert that
-   * accesses to stack values are unaliased.
-   */
-
-  inline Value& unaliasedLocal(uint32_t i);
-
-  bool hasArgs() const { return isFunctionFrame(); }
-  inline Value& unaliasedFormal(unsigned i,
-                                MaybeCheckAliasing = CHECK_ALIASING);
-  inline Value& unaliasedActual(unsigned i,
-                                MaybeCheckAliasing = CHECK_ALIASING);
-  template <class Op>
-  inline void unaliasedForEachActual(Op op);
-
-  unsigned numFormalArgs() const {
-    MOZ_ASSERT(hasArgs());
-    return callee().nargs();
-  }
-  unsigned numActualArgs() const {
-    MOZ_ASSERT(hasArgs());
-    return nactual_;
-  }
-
-  /* Watch out, this exposes a pointer to the unaliased formal arg array. */
-  Value* argv() const {
-    MOZ_ASSERT(hasArgs());
-    return argv_;
-  }
-
-  /*
-   * Arguments object
-   *
-   * If a non-eval function has script->needsArgsObj, an arguments object is
-   * created in the prologue and stored in the local variable for the
-   * 'arguments' binding (script->argumentsLocal). Since this local is
-   * mutable, the arguments object can be overwritten and we can "lose" the
-   * arguments object. Thus, InterpreterFrame keeps an explicit argsObj_ field
-   * so that the original arguments object is always available.
-   */
-
-  ArgumentsObject& argsObj() const;
-  void initArgsObj(ArgumentsObject& argsobj);
-
-  ArrayObject* createRestParameter(JSContext* cx);
-
-  /*
-   * Environment chain
-   *
-   * In theory, the environment chain would contain an object for every
-   * lexical scope. However, only objects that are required for dynamic
-   * lookup are actually created.
-   *
-   * Given that an InterpreterFrame corresponds roughly to a ES Execution
-   * Context (ES 10.3), InterpreterFrame::varObj corresponds to the
-   * VariableEnvironment component of a Exection Context. Intuitively, the
-   * variables object is where new bindings (variables and functions) are
-   * stored. One might expect that this is either the Call object or
-   * envChain.globalObj for function or global code, respectively, however
-   * the JSAPI allows calls of Execute to specify a variables object on the
-   * environment chain other than the call/global object. This allows
-   * embeddings to run multiple scripts under the same global, each time
-   * using a new variables object to collect and discard the script's global
-   * variables.
-   */
-
-  inline HandleObject environmentChain() const;
-
-  inline EnvironmentObject& aliasedEnvironment(EnvironmentCoordinate ec) const;
-  inline GlobalObject& global() const;
-  inline CallObject& callObj() const;
-  inline JSObject& varObj() const;
-  inline LexicalEnvironmentObject& extensibleLexicalEnvironment() const;
-
-  template <typename SpecificEnvironment>
-  inline void pushOnEnvironmentChain(SpecificEnvironment& env);
-  template <typename SpecificEnvironment>
-  inline void popOffEnvironmentChain();
-  inline void replaceInnermostEnvironment(EnvironmentObject& env);
-
-  // Push a VarEnvironmentObject for function frames of functions that have
-  // parameter expressions with closed over var bindings.
-  bool pushVarEnvironment(JSContext* cx, HandleScope scope);
-
-  /*
-   * For lexical envs with aliased locals, these interfaces push and pop
-   * entries on the environment chain.  The "freshen" operation replaces the
-   * current lexical env with a fresh copy of it, to implement semantics
-   * providing distinct bindings per iteration of a for(;;) loop whose head
-   * has a lexical declaration.  The "recreate" operation replaces the
-   * current lexical env with a copy of it containing uninitialized
-   * bindings, to implement semantics providing distinct bindings per
-   * iteration of a for-in/of loop.
-   */
-
-  bool pushLexicalEnvironment(JSContext* cx, Handle<LexicalScope*> scope);
-  bool freshenLexicalEnvironment(JSContext* cx);
-  bool recreateLexicalEnvironment(JSContext* cx);
-
-  /*
-   * Script
-   *
-   * All frames have an associated JSScript which holds the bytecode being
-   * executed for the frame.
-   */
-
-  JSScript* script() const { return script_; }
-
-  /* Return the previous frame's pc. */
-  jsbytecode* prevpc() {
-    MOZ_ASSERT(prev_);
-    return prevpc_;
-  }
-
-  /* Return the previous frame's sp. */
-  Value* prevsp() {
-    MOZ_ASSERT(prev_);
-    return prevsp_;
-  }
-
-  /*
-   * Return the 'this' argument passed to a non-eval function frame. This is
-   * not necessarily the frame's this-binding, for instance non-strict
-   * functions will box primitive 'this' values and thisArgument() will
-   * return the original, unboxed Value.
-   */
-  Value& thisArgument() const {
-    MOZ_ASSERT(isFunctionFrame());
-    return argv()[-1];
-  }
-
-  /*
-   * Callee
-   *
-   * Only function frames have a callee. An eval frame in a function has the
-   * same callee as its containing function frame.
-   */
-
-  JSFunction& callee() const {
-    MOZ_ASSERT(isFunctionFrame());
-    return calleev().toObject().as<JSFunction>();
-  }
-
-  const Value& calleev() const {
-    MOZ_ASSERT(isFunctionFrame());
-    return argv()[-2];
-  }
-
-  /*
-   * New Target
-   *
-   * Only function frames have a meaningful newTarget. An eval frame in a
-   * function will have a copy of the newTarget of the enclosing function
-   * frame.
-   */
-  Value newTarget() const {
-    if (isEvalFrame()) {
-      return ((Value*)this)[-1];
-    }
-
-    MOZ_ASSERT(isFunctionFrame());
-
-    if (callee().isArrow()) {
-      return callee().getExtendedSlot(FunctionExtended::ARROW_NEWTARGET_SLOT);
-    }
-
-    if (isConstructing()) {
-      unsigned pushedArgs = std::max(numFormalArgs(), numActualArgs());
-      return argv()[pushedArgs];
-    }
-    return UndefinedValue();
-  }
-
-  /* Profiler flags */
-
-  bool hasPushedGeckoProfilerFrame() {
-    return !!(flags_ & HAS_PUSHED_PROF_FRAME);
-  }
-
-  void setPushedGeckoProfilerFrame() { flags_ |= HAS_PUSHED_PROF_FRAME; }
-
-  void unsetPushedGeckoProfilerFrame() { flags_ &= ~HAS_PUSHED_PROF_FRAME; }
-
-  /* Return value */
-
-  bool hasReturnValue() const { return flags_ & HAS_RVAL; }
-
-  MutableHandleValue returnValue() {
-    if (!hasReturnValue()) {
-      rval_.setUndefined();
-    }
-    return MutableHandleValue::fromMarkedLocation(&rval_);
-  }
-
-  void markReturnValue() { flags_ |= HAS_RVAL; }
-
-  void setReturnValue(const Value& v) {
-    rval_ = v;
-    markReturnValue();
-  }
-
-  void clearReturnValue() {
-    rval_.setUndefined();
-    markReturnValue();
-  }
-
-  void resumeGeneratorFrame(JSObject* envChain) {
-    MOZ_ASSERT(script()->isGenerator() || script()->isAsync());
-    MOZ_ASSERT(isFunctionFrame());
-    flags_ |= HAS_INITIAL_ENV;
-    envChain_ = envChain;
-  }
-
-  /*
-   * Other flags
-   */
-
-  bool isConstructing() const { return !!(flags_ & CONSTRUCTING); }
-
-  void setResumedGenerator() { flags_ |= RESUMED_GENERATOR; }
-  bool isResumedGenerator() const { return !!(flags_ & RESUMED_GENERATOR); }
-
-  /*
-   * These two queries should not be used in general: the presence/absence of
-   * the call/args object is determined by the static(ish) properties of the
-   * JSFunction/JSScript. These queries should only be performed when probing
-   * a stack frame that may be in the middle of the prologue (during which
-   * time the call/args object are created).
-   */
-
-  inline bool hasInitialEnvironment() const;
-
-  bool hasInitialEnvironmentUnchecked() const {
-    return flags_ & HAS_INITIAL_ENV;
-  }
-
-  bool hasArgsObj() const {
-    MOZ_ASSERT(script()->needsArgsObj());
-    return flags_ & HAS_ARGS_OBJ;
-  }
-
-  /*
-   * Debugger eval frames.
-   *
-   * - If evalInFramePrev_ is non-null, frame was created for an "eval in
-   *   frame" call, which can push a successor to any live frame; so its
-   *   logical "prev" frame is not necessarily the previous frame in memory.
-   *   Iteration should treat evalInFramePrev_ as this frame's previous frame.
-   *
-   * - Don't bother to JIT it, because it's probably short-lived.
-   *
-   * - It is required to have a environment chain object outside the
-   *   js::EnvironmentObject hierarchy: either a global object, or a
-   *   DebugEnvironmentProxy.
-   */
-  bool isDebuggerEvalFrame() const {
-    return isEvalFrame() && !!evalInFramePrev_;
-  }
-
-  bool prevUpToDate() const { return !!(flags_ & PREV_UP_TO_DATE); }
-
-  void setPrevUpToDate() { flags_ |= PREV_UP_TO_DATE; }
-
-  void unsetPrevUpToDate() { flags_ &= ~PREV_UP_TO_DATE; }
-
-  bool isDebuggee() const { return !!(flags_ & DEBUGGEE); }
-
-  void setIsDebuggee() { flags_ |= DEBUGGEE; }
-
-  inline void unsetIsDebuggee();
-
-  bool hasCachedSavedFrame() const { return flags_ & HAS_CACHED_SAVED_FRAME; }
-  void setHasCachedSavedFrame() { flags_ |= HAS_CACHED_SAVED_FRAME; }
-  void clearHasCachedSavedFrame() { flags_ &= ~HAS_CACHED_SAVED_FRAME; }
-
- public:
-  void trace(JSTracer* trc, Value* sp, jsbytecode* pc);
-  void traceValues(JSTracer* trc, unsigned start, unsigned end);
-
-  // Entered Baseline/Ion from the interpreter.
-  bool runningInJit() const { return !!(flags_ & RUNNING_IN_JIT); }
-  void setRunningInJit() { flags_ |= RUNNING_IN_JIT; }
-  void clearRunningInJit() { flags_ &= ~RUNNING_IN_JIT; }
-};
-
-/*****************************************************************************/
-
-class InterpreterRegs {
- public:
-  Value* sp;
-  jsbytecode* pc;
-
- private:
-  InterpreterFrame* fp_;
-
- public:
-  InterpreterFrame* fp() const { return fp_; }
-
-  unsigned stackDepth() const {
-    MOZ_ASSERT(sp >= fp_->base());
-    return sp - fp_->base();
-  }
-
-  Value* spForStackDepth(unsigned depth) const {
-    MOZ_ASSERT(fp_->script()->nfixed() + depth <= fp_->script()->nslots());
-    return fp_->base() + depth;
-  }
-
-  /* For generators. */
-  void rebaseFromTo(const InterpreterRegs& from, InterpreterFrame& to) {
-    fp_ = &to;
-    sp = to.slots() + (from.sp - from.fp_->slots());
-    pc = from.pc;
-    MOZ_ASSERT(fp_);
-  }
-
-  void popInlineFrame() {
-    pc = fp_->prevpc();
-    unsigned spForNewTarget =
-        fp_->isResumedGenerator() ? 0 : fp_->isConstructing();
-    sp = fp_->prevsp() - fp_->numActualArgs() - 1 - spForNewTarget;
-    fp_ = fp_->prev();
-    MOZ_ASSERT(fp_);
-  }
-  void prepareToRun(InterpreterFrame& fp, JSScript* script) {
-    pc = script->code();
-    sp = fp.slots() + script->nfixed();
-    fp_ = &fp;
-  }
-
-  void setToEndOfScript();
-
-  MutableHandleValue stackHandleAt(int i) {
-    return MutableHandleValue::fromMarkedLocation(&sp[i]);
-  }
-
-  HandleValue stackHandleAt(int i) const {
-    return HandleValue::fromMarkedLocation(&sp[i]);
-  }
-
-  friend void GDBTestInitInterpreterRegs(InterpreterRegs&,
-                                         js::InterpreterFrame*, JS::Value*,
-                                         uint8_t*);
-};
-
-/*****************************************************************************/
-
-class InterpreterStack {
-  friend class InterpreterActivation;
-
-  static const size_t DEFAULT_CHUNK_SIZE = 4 * 1024;
-  LifoAlloc allocator_;
-
-  // Number of interpreter frames on the stack, for over-recursion checks.
-  static const size_t MAX_FRAMES = 50 * 1000;
-  static const size_t MAX_FRAMES_TRUSTED = MAX_FRAMES + 1000;
-  size_t frameCount_;
-
-  inline uint8_t* allocateFrame(JSContext* cx, size_t size);
-
-  inline InterpreterFrame* getCallFrame(JSContext* cx, const CallArgs& args,
-                                        HandleScript script,
-                                        MaybeConstruct constructing,
-                                        Value** pargv);
-
-  void releaseFrame(InterpreterFrame* fp) {
-    frameCount_--;
-    allocator_.release(fp->mark_);
-  }
-
- public:
-  InterpreterStack() : allocator_(DEFAULT_CHUNK_SIZE), frameCount_(0) {}
-
-  ~InterpreterStack() { MOZ_ASSERT(frameCount_ == 0); }
-
-  // For execution of eval or global code.
-  InterpreterFrame* pushExecuteFrame(JSContext* cx, HandleScript script,
-                                     const Value& newTargetValue,
-                                     HandleObject envChain,
-                                     AbstractFramePtr evalInFrame);
-
-  // Called to invoke a function.
-  InterpreterFrame* pushInvokeFrame(JSContext* cx, const CallArgs& args,
-                                    MaybeConstruct constructing);
-
-  // The interpreter can push light-weight, "inline" frames without entering a
-  // new InterpreterActivation or recursively calling Interpret.
-  bool pushInlineFrame(JSContext* cx, InterpreterRegs& regs,
-                       const CallArgs& args, HandleScript script,
-                       MaybeConstruct constructing);
-
-  void popInlineFrame(InterpreterRegs& regs);
-
-  bool resumeGeneratorCallFrame(JSContext* cx, InterpreterRegs& regs,
-                                HandleFunction callee, HandleObject envChain);
-
-  inline void purge(JSRuntime* rt);
-
-  size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
-    return allocator_.sizeOfExcludingThis(mallocSizeOf);
-  }
-};
-
-void TraceInterpreterActivations(JSContext* cx, JSTracer* trc);
-
-/*****************************************************************************/
-
-/** Base class for all function call args. */
-class AnyInvokeArgs : public JS::CallArgs {};
-
-/** Base class for all function construction args. */
-class AnyConstructArgs : public JS::CallArgs {
-  // Only js::Construct (or internal methods that call the qualified CallArgs
-  // versions) should do these things!
-  void setCallee(const Value& v) = delete;
-  void setThis(const Value& v) = delete;
-  MutableHandleValue newTarget() const = delete;
-  MutableHandleValue rval() const = delete;
-};
-
-namespace detail {
-
-/** Function call/construct args of statically-unknown count. */
-template <MaybeConstruct Construct>
-class GenericArgsBase : public mozilla::Conditional<Construct, AnyConstructArgs,
-                                                    AnyInvokeArgs>::Type {
- protected:
-  RootedValueVector v_;
-
-  explicit GenericArgsBase(JSContext* cx) : v_(cx) {}
-
- public:
-  bool init(JSContext* cx, unsigned argc) {
-    if (argc > ARGS_LENGTH_MAX) {
-      JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
-                                JSMSG_TOO_MANY_ARGUMENTS);
-      return false;
-    }
-
-    // callee, this, arguments[, new.target iff constructing]
-    size_t len = 2 + argc + uint32_t(Construct);
-    MOZ_ASSERT(len > argc);  // no overflow
-    if (!v_.resize(len)) {
-      return false;
-    }
-
-    *static_cast<JS::CallArgs*>(this) = CallArgsFromVp(argc, v_.begin());
-    this->constructing_ = Construct;
-    if (Construct) {
-      this->CallArgs::setThis(MagicValue(JS_IS_CONSTRUCTING));
-    }
-    return true;
-  }
-};
-
-/** Function call/construct args of statically-known count. */
-template <MaybeConstruct Construct, size_t N>
-class FixedArgsBase : public mozilla::Conditional<Construct, AnyConstructArgs,
-                                                  AnyInvokeArgs>::Type {
-  static_assert(N <= ARGS_LENGTH_MAX, "o/~ too many args o/~");
-
- protected:
-  JS::AutoValueArray<2 + N + uint32_t(Construct)> v_;
-
-  explicit FixedArgsBase(JSContext* cx) : v_(cx) {
-    *static_cast<JS::CallArgs*>(this) = CallArgsFromVp(N, v_.begin());
-    this->constructing_ = Construct;
-    if (Construct) {
-      this->CallArgs::setThis(MagicValue(JS_IS_CONSTRUCTING));
-    }
-  }
-};
-
-}  // namespace detail
-
-/** Function call args of statically-unknown count. */
-class InvokeArgs : public detail::GenericArgsBase<NO_CONSTRUCT> {
-  using Base = detail::GenericArgsBase<NO_CONSTRUCT>;
-
- public:
-  explicit InvokeArgs(JSContext* cx) : Base(cx) {}
-};
-
-/** Function call args of statically-unknown count. */
-class InvokeArgsMaybeIgnoresReturnValue
-    : public detail::GenericArgsBase<NO_CONSTRUCT> {
-  using Base = detail::GenericArgsBase<NO_CONSTRUCT>;
-
- public:
-  explicit InvokeArgsMaybeIgnoresReturnValue(JSContext* cx,
-                                             bool ignoresReturnValue)
-      : Base(cx) {
-    this->ignoresReturnValue_ = ignoresReturnValue;
-  }
-};
-
-/** Function call args of statically-known count. */
-template <size_t N>
-class FixedInvokeArgs : public detail::FixedArgsBase<NO_CONSTRUCT, N> {
-  using Base = detail::FixedArgsBase<NO_CONSTRUCT, N>;
-
- public:
-  explicit FixedInvokeArgs(JSContext* cx) : Base(cx) {}
-};
-
-/** Function construct args of statically-unknown count. */
-class ConstructArgs : public detail::GenericArgsBase<CONSTRUCT> {
-  using Base = detail::GenericArgsBase<CONSTRUCT>;
-
- public:
-  explicit ConstructArgs(JSContext* cx) : Base(cx) {}
-};
-
-/** Function call args of statically-known count. */
-template <size_t N>
-class FixedConstructArgs : public detail::FixedArgsBase<CONSTRUCT, N> {
-  using Base = detail::FixedArgsBase<CONSTRUCT, N>;
-
- public:
-  explicit FixedConstructArgs(JSContext* cx) : Base(cx) {}
-};
-
-template <class Args, class Arraylike>
-inline bool FillArgumentsFromArraylike(JSContext* cx, Args& args,
-                                       const Arraylike& arraylike) {
-  uint32_t len = arraylike.length();
-  if (!args.init(cx, len)) {
-    return false;
-  }
-
-  for (uint32_t i = 0; i < len; i++) {
-    args[i].set(arraylike[i]);
-  }
-
-  return true;
-}
-
-}  // namespace js
-
-namespace mozilla {
-
-template <>
-struct DefaultHasher<js::AbstractFramePtr> {
-  typedef js::AbstractFramePtr Lookup;
-
-  static js::HashNumber hash(const Lookup& key) {
-    return mozilla::HashGeneric(key.raw());
-  }
-
-  static bool match(const js::AbstractFramePtr& k, const Lookup& l) {
-    return k == l;
-  }
-};
-
-}  // namespace mozilla
-
-namespace js {
-
-/*****************************************************************************/
-
-// [SMDOC] LiveSavedFrameCache: SavedFrame caching to minimize stack walking
-//
-// Since each SavedFrame object includes a 'parent' pointer to the SavedFrame
-// for its caller, if we could easily find the right SavedFrame for a given
-// stack frame, we wouldn't need to walk the rest of the stack. Traversing deep
-// stacks can be expensive, and when we're profiling or instrumenting code, we
-// may want to capture JavaScript stacks frequently, so such cases would benefit
-// if we could avoid walking the entire stack.
-//
-// We could have a cache mapping frame addresses to their SavedFrame objects,
-// but invalidating its entries would be a challenge. Popping a stack frame is
-// extremely performance-sensitive, and SpiderMonkey stack frames can be OSR'd,
-// thrown, rematerialized, and perhaps meet other fates; we would rather our
-// cache not depend on handling so many tricky cases.
-//
-// It turns out that we can keep the cache accurate by reserving a single bit in
-// the stack frame, which must be clear on any newly pushed frame. When we
-// insert an entry into the cache mapping a given frame address to its
-// SavedFrame, we set the bit in the frame. Then, we take care to probe the
-// cache only for frames whose bit is set; the bit tells us that the frame has
-// never left the stack, so its cache entry must be accurate, at least about
-// which function the frame is executing (the line may have changed; more about
-// that below). The code refers to this bit as the 'hasCachedSavedFrame' flag.
-//
-// We could manage such a cache replacing least-recently used entries, but we
-// can do better than that: the cache can be a stack, of which we need examine
-// only entries from the top.
-//
-// First, observe that stacks are walked from the youngest frame to the oldest,
-// but SavedFrame chains are built from oldest to youngest, to ensure common
-// tails are shared. This means that capturing a stack is necessarily a
-// two-phase process: walk the stack, and then build the SavedFrames.
-//
-// Naturally, the first time we capture the stack, the cache is empty, and we
-// must traverse the entire stack. As we build each SavedFrame, we push an entry
-// associating the frame's address to its SavedFrame on the cache, and set the
-// frame's bit. At the end, every frame has its bit set and an entry in the
-// cache.
-//
-// Then the program runs some more. Some, none, or all of the frames are popped.
-// Any new frames are pushed with their bit clear. Any frame with its bit set
-// has never left the stack. The cache is left untouched.
-//
-// For the next capture, we walk the stack up to the first frame with its bit
-// set, if there is one. Call it F; it must have a cache entry. We pop entries
-// from the cache - all invalid, because they are above F's entry, and hence
-// younger - until we find the entry matching F's address. Since F's bit is set,
-// we know it never left the stack, and hence that no younger frame could have
-// had a colliding address. And since the frame's bit was set when we pushed the
-// cache entry, we know the entry is still valid.
-//
-// F's cache entry's SavedFrame covers the rest of the stack, so we don't need
-// to walk the stack any further. Now we begin building SavedFrame objects for
-// the new frames, pushing cache entries, and setting bits on the frames. By the
-// end, the cache again covers the full stack, and every frame's bit is set.
-//
-// If we walk the stack to the end, and find no frame with its bit set, then the
-// entire cache is invalid. At this point, it must be emptied, so that the new
-// entries we are about to push are the only frames in the cache.
-//
-// For example, suppose we have the following stack (let 'A > B' mean "A called
-// B", so the frames are listed oldest first):
-//
-//     P  > Q  > R  > S          Initial stack, bits not set.
-//     P* > Q* > R* > S*         Capture a SavedFrame stack, set bits.
-//                               The cache now holds: P > Q > R > S.
-//     P* > Q* > R*              Return from S.
-//     P* > Q*                   Return from R.
-//     P* > Q* > T  > U          Call T and U. New frames have clear bits.
-//
-// If we capture the stack now, the cache still holds:
-//
-//     P  > Q  > R  > S
-//
-// As we traverse the stack, we'll cross U and T, and then find Q with its bit
-// set. We pop entries from the cache until we find the entry for Q; this
-// removes entries R and S, which were indeed invalid. In Q's cache entry, we
-// find the SavedFrame representing the stack P > Q. Now we build SavedFrames
-// for the new portion of the stack, pushing an entry for T and setting the bit
-// on the frame, and then doing the same for U. In the end, the call stack again
-// has bits set on all its frames:
-//
-//     P* > Q* > T* > U*         All frames are now in the cache.
-//
-// And the cache again holds entries for the entire stack:
-//
-//     P  > Q  > T  > U
-//
-// Details:
-//
-// - When we find a cache entry whose frame address matches our frame F, we know
-//   that F has never left the stack, but it may certainly be the case that
-//   execution took place in that frame, and that the current source position
-//   within F's function has changed. This means that the entry's SavedFrame,
-//   which records the source line and column as well as the function, is not
-//   correct. To detect this case, when we push a cache entry, we record the
-//   frame's pc. When consulting the cache, if a frame's address matches but its
-//   pc does not, then we pop the cache entry, clear the frame's bit, and
-//   continue walking the stack. The next stack frame will definitely hit: since
-//   its callee frame never left the stack, the calling frame never got the
-//   chance to execute.
-//
-// - Generators, at least conceptually, have long-lived stack frames that
-//   disappear from the stack when the generator yields, and reappear on the
-//   stack when the generator's 'next' method is called. When a generator's
-//   frame is placed again atop the stack, its bit must be cleared - for the
-//   purposes of the cache, treating the frame as a new frame - to respect the
-//   invariants we used to justify the algorithm above. Async function
-//   activations usually appear atop empty stacks, since they are invoked as a
-//   promise callback, but the same rule applies.
-//
-// - SpiderMonkey has many types of stack frames, and not all have a place to
-//   store a bit indicating a cached SavedFrame. But as long as we don't create
-//   cache entries for frames we can't mark, simply omitting them from the cache
-//   is harmless. Uncacheable frame types include inlined Ion frames and
-//   non-Debug wasm frames. The LiveSavedFrameCache::FramePtr type represents
-//   only pointers to frames that can be cached, so if you have a FramePtr, you
-//   don't need to further check the frame for cachability. FramePtr provides
-//   access to the hasCachedSavedFrame bit.
-//
-// - We actually break up the cache into one cache per Activation. Popping an
-//   activation invalidates all its cache entries, simply by freeing the cache
-//   altogether.
-//
-// - The entire chain of SavedFrames for a given stack capture is created in the
-//   compartment of the code that requested the capture, *not* in that of the
-//   frames it represents, so in general, different compartments may have
-//   different SavedFrame objects representing the same actual stack frame. The
-//   LiveSavedFrameCache simply records whichever SavedFrames were used in the
-//   most recent captures. When we find a cache hit, we check the entry's
-//   SavedFrame's compartment against the current compartment; if they do not
-//   match, we clear the entire cache.
-//
-//   This means that it is not always true that, if a frame's
-//   hasCachedSavedFrame bit is set, it must have an entry in the cache. The
-//   actual invariant is: either the cache is completely empty, or the frames'
-//   bits are trustworthy. This invariant holds even though capture can be
-//   interrupted at many places by OOM failures. Clearing the cache is a single,
-//   uninterruptible step. When we try to look up a frame whose bit is set and
-//   find an empty cache, we clear the frame's bit. And we only add the first
-//   frame to an empty cache once we've walked the stack all the way, so we know
-//   that all frames' bits are cleared by that point.
-//
-// - When the Debugger API evaluates an expression in some frame (the 'target
-//   frame'), it's SpiderMonkey's convention that the target frame be treated as
-//   the parent of the eval frame. In reality, of course, the eval frame is
-//   pushed on the top of the stack like any other frame, but stack captures
-//   simply jump straight over the intervening frames, so that the '.parent'
-//   property of a SavedFrame for the eval is the SavedFrame for the target.
-//   This is arranged by giving the eval frame an 'evalInFramePrev` link
-//   pointing to the target, which an ordinary FrameIter will notice and
-//   respect.
-//
-//   If the LiveSavedFrameCache were presented with stack traversals that
-//   skipped frames in this way, it would cause havoc. First, with no debugger
-//   eval frames present, capture the stack, populating the cache. Then push a
-//   debugger eval frame and capture again; the skipped frames to appear to be
-//   absent from the stack. Now pop the debugger eval frame, and capture a third
-//   time: the no-longer-skipped frames seem to reappear on the stack, with
-//   their cached bits still set.
-//
-//   The LiveSavedFrameCache assumes that the stack it sees is used in a
-//   stack-like fashion: if a frame has its bit set, it has never left the
-//   stack. To support this assumption, when the cache is in use, we do not skip
-//   the frames between a debugger eval frame an its target; we always traverse
-//   the entire stack, invalidating and populating the cache in the usual way.
-//   Instead, when we construct a SavedFrame for a debugger eval frame, we
-//   select the appropriate parent at that point: rather than the next-older
-//   frame, we find the SavedFrame for the eval's target frame. The skip appears
-//   in the SavedFrame chains, even as the traversal covers all the frames.
-//
-// - Rematerialized frames (see ../jit/RematerializedFrame.h) are always created
-//   with their hasCachedSavedFrame bits clear: although there may be extant
-//   SavedFrames built from the original IonMonkey frame, the Rematerialized
-//   frames will not have cache entries for them until they are traversed in a
-//   capture themselves.
-//
-//   This means that, oddly, it is not always true that, once we reach a frame
-//   with its hasCachedSavedFrame bit set, all its parents will have the bit set
-//   as well. However, clear bits under younger set bits will only occur on
-//   Rematerialized frames.
-class LiveSavedFrameCache {
- public:
-  // The address of a live frame for which we can cache SavedFrames: it has a
-  // 'hasCachedSavedFrame' bit we can examine and set, and can be converted to
-  // a Key to index the cache.
-  class FramePtr {
-    // We use jit::CommonFrameLayout for both Baseline frames and Ion
-    // physical frames.
-    using Ptr = mozilla::Variant<InterpreterFrame*, jit::CommonFrameLayout*,
-                                 jit::RematerializedFrame*, wasm::DebugFrame*>;
-
-    Ptr ptr;
-
-    template <typename Frame>
-    explicit FramePtr(Frame ptr) : ptr(ptr) {}
-
-    struct HasCachedMatcher;
-    struct SetHasCachedMatcher;
-    struct ClearHasCachedMatcher;
-
-   public:
-    // If iter's frame is of a type that can be cached, construct a FramePtr
-    // for its frame. Otherwise, return Nothing.
-    static inline mozilla::Maybe<FramePtr> create(const FrameIter& iter);
-
-    // Construct a FramePtr from an AbstractFramePtr. This always succeeds.
-    static inline FramePtr create(AbstractFramePtr abstractFramePtr);
-
-    inline bool hasCachedSavedFrame() const;
-    inline void setHasCachedSavedFrame();
-    inline void clearHasCachedSavedFrame();
-
-    // Return true if this FramePtr refers to an interpreter frame.
-    inline bool isInterpreterFrame() const {
-      return ptr.is<InterpreterFrame*>();
-    }
-
-    // If this FramePtr is an interpreter frame, return a pointer to it.
-    inline InterpreterFrame& asInterpreterFrame() const {
-      return *ptr.as<InterpreterFrame*>();
-    }
-
-    // Return true if this FramePtr refers to a rematerialized frame.
-    inline bool isRematerializedFrame() const {
-      return ptr.is<jit::RematerializedFrame*>();
-    }
-
-    bool operator==(const FramePtr& rhs) const { return rhs.ptr == this->ptr; }
-    bool operator!=(const FramePtr& rhs) const { return !(rhs == *this); }
-  };
-
- private:
-  // A key in the cache: the address of a frame, live or dead, for which we
-  // can cache SavedFrames. Since the pointer may not be live, the only
-  // operation this type permits is comparison.
-  class Key {
-    FramePtr framePtr;
-
-   public:
-    MOZ_IMPLICIT Key(const FramePtr& framePtr) : framePtr(framePtr) {}
-
-    bool operator==(const Key& rhs) const {
-      return rhs.framePtr == this->framePtr;
-    }
-    bool operator!=(const Key& rhs) const { return !(rhs == *this); }
-  };
-
-  struct Entry {
-    const Key key;
-    const jsbytecode* pc;
-    HeapPtr<SavedFrame*> savedFrame;
-
-    Entry(const Key& key, const jsbytecode* pc, SavedFrame* savedFrame)
-        : key(key), pc(pc), savedFrame(savedFrame) {}
-  };
-
-  using EntryVector = Vector<Entry, 0, SystemAllocPolicy>;
-  EntryVector* frames;
-
-  LiveSavedFrameCache(const LiveSavedFrameCache&) = delete;
-  LiveSavedFrameCache& operator=(const LiveSavedFrameCache&) = delete;
-
- public:
-  explicit LiveSavedFrameCache() : frames(nullptr) {}
-
-  LiveSavedFrameCache(LiveSavedFrameCache&& rhs) : frames(rhs.frames) {
-    MOZ_ASSERT(this != &rhs, "self-move disallowed");
-    rhs.frames = nullptr;
-  }
-
-  ~LiveSavedFrameCache() {
-    if (frames) {
-      js_delete(frames);
-      frames = nullptr;
-    }
-  }
-
-  bool initialized() const { return !!frames; }
-  bool init(JSContext* cx) {
-    frames = js_new<EntryVector>();
-    if (!frames) {
-      JS_ReportOutOfMemory(cx);
-      return false;
-    }
-    return true;
-  }
-
-  void trace(JSTracer* trc);
-
-  // Set |frame| to the cached SavedFrame corresponding to |framePtr| at |pc|.
-  // |framePtr|'s hasCachedSavedFrame bit must be set. Remove all cache
-  // entries for frames younger than that one.
-  //
-  // This may set |frame| to nullptr if |pc| is different from the pc supplied
-  // when the cache entry was inserted. In this case, the cached SavedFrame
-  // (probably) has the wrong source position. Entries for younger frames are
-  // still removed. The next frame, if any, will be a cache hit.
-  //
-  // This may also set |frame| to nullptr if the cache was populated with
-  // SavedFrame objects for a different compartment than cx's current
-  // compartment. In this case, the entire cache is flushed.
-  void find(JSContext* cx, FramePtr& framePtr, const jsbytecode* pc,
-            MutableHandleSavedFrame frame) const;
-
-  // Search the cache for a frame matching |framePtr|, without removing any
-  // entries. Return the matching saved frame, or nullptr if none is found.
-  // This is used for resolving |evalInFramePrev| links.
-  void findWithoutInvalidation(const FramePtr& framePtr,
-                               MutableHandleSavedFrame frame) const;
-
-  // Push a cache entry mapping |framePtr| and |pc| to |savedFrame| on the top
-  // of the cache's stack. You must insert entries for frames from oldest to
-  // youngest. They must all be younger than the frame that the |find| method
-  // found a hit for; or you must have cleared the entire cache with the
-  // |clear| method.
-  bool insert(JSContext* cx, FramePtr& framePtr, const jsbytecode* pc,
-              HandleSavedFrame savedFrame);
-
-  // Remove all entries from the cache.
-  void clear() {
-    if (frames) frames->clear();
-  }
-};
-
-static_assert(
-    sizeof(LiveSavedFrameCache) == sizeof(uintptr_t),
-    "Every js::Activation has a LiveSavedFrameCache, so we need to be pretty "
-    "careful "
-    "about avoiding bloat. If you're adding members to LiveSavedFrameCache, "
-    "maybe you "
-    "should consider figuring out a way to make js::Activation have a "
-    "LiveSavedFrameCache* instead of a Rooted<LiveSavedFrameCache>.");
-
-/*****************************************************************************/
-
-class InterpreterActivation;
-
-namespace jit {
 class JitActivation;
 }  // namespace jit
 
-// This class is separate from Activation, because it calls Compartment::wrap()
-// which can GC and walk the stack. It's not safe to do that within the
-// JitActivation constructor.
-class MOZ_RAII ActivationEntryMonitor {
-  JSContext* cx_;
-
-  // The entry point monitor that was set on cx_->runtime() when this
-  // ActivationEntryMonitor was created.
-  JS::dbg::AutoEntryMonitor* entryMonitor_;
-
-  explicit inline ActivationEntryMonitor(JSContext* cx);
-
-  ActivationEntryMonitor(const ActivationEntryMonitor& other) = delete;
-  void operator=(const ActivationEntryMonitor& other) = delete;
-
-  void init(JSContext* cx, jit::CalleeToken entryToken);
-  void init(JSContext* cx, InterpreterFrame* entryFrame);
-
-  Value asyncStack(JSContext* cx);
-
- public:
-  inline ActivationEntryMonitor(JSContext* cx, InterpreterFrame* entryFrame);
-  inline ActivationEntryMonitor(JSContext* cx, jit::CalleeToken entryToken);
-  inline ~ActivationEntryMonitor();
-};
-
-class Activation {
- protected:
-  JSContext* cx_;
-  JS::Compartment* compartment_;
-  Activation* prev_;
-  Activation* prevProfiling_;
-
-  // Counter incremented by JS::HideScriptedCaller and decremented by
-  // JS::UnhideScriptedCaller. If > 0 for the top activation,
-  // DescribeScriptedCaller will return null instead of querying that
-  // activation, which should prompt the caller to consult embedding-specific
-  // data structures instead.
-  size_t hideScriptedCallerCount_;
-
-  // The cache of SavedFrame objects we have already captured when walking
-  // this activation's stack.
-  Rooted<LiveSavedFrameCache> frameCache_;
-
-  // Youngest saved frame of an async stack that will be iterated during stack
-  // capture in place of the actual stack of previous activations. Note that
-  // the stack of this activation is captured entirely before this is used.
-  //
-  // Usually this is nullptr, meaning that normal stack capture will occur.
-  // When this is set, the stack of any previous activation is ignored.
-  Rooted<SavedFrame*> asyncStack_;
-
-  // Value of asyncCause to be attached to asyncStack_.
-  const char* asyncCause_;
-
-  // True if the async call was explicitly requested, e.g. via
-  // callFunctionWithAsyncStack.
-  bool asyncCallIsExplicit_;
-
-  enum Kind { Interpreter, Jit };
-  Kind kind_;
-
-  inline Activation(JSContext* cx, Kind kind);
-  inline ~Activation();
-
- public:
-  JSContext* cx() const { return cx_; }
-  JS::Compartment* compartment() const { return compartment_; }
-  Activation* prev() const { return prev_; }
-  Activation* prevProfiling() const { return prevProfiling_; }
-  inline Activation* mostRecentProfiling();
-
-  bool isInterpreter() const { return kind_ == Interpreter; }
-  bool isJit() const { return kind_ == Jit; }
-  inline bool hasWasmExitFP() const;
-
-  inline bool isProfiling() const;
-  void registerProfiling();
-  void unregisterProfiling();
-
-  InterpreterActivation* asInterpreter() const {
-    MOZ_ASSERT(isInterpreter());
-    return (InterpreterActivation*)this;
-  }
-  jit::JitActivation* asJit() const {
-    MOZ_ASSERT(isJit());
-    return (jit::JitActivation*)this;
-  }
-
-  void hideScriptedCaller() { hideScriptedCallerCount_++; }
-  void unhideScriptedCaller() {
-    MOZ_ASSERT(hideScriptedCallerCount_ > 0);
-    hideScriptedCallerCount_--;
-  }
-  bool scriptedCallerIsHidden() const { return hideScriptedCallerCount_ > 0; }
-
-  static size_t offsetOfPrev() { return offsetof(Activation, prev_); }
-  static size_t offsetOfPrevProfiling() {
-    return offsetof(Activation, prevProfiling_);
-  }
-
-  SavedFrame* asyncStack() { return asyncStack_; }
-
-  const char* asyncCause() const { return asyncCause_; }
-
-  bool asyncCallIsExplicit() const { return asyncCallIsExplicit_; }
-
-  inline LiveSavedFrameCache* getLiveSavedFrameCache(JSContext* cx);
-  void clearLiveSavedFrameCache() { frameCache_.get().clear(); }
-
- private:
-  Activation(const Activation& other) = delete;
-  void operator=(const Activation& other) = delete;
-};
-
-// This variable holds a special opcode value which is greater than all normal
-// opcodes, and is chosen such that the bitwise or of this value with any
-// opcode is this value.
-static const jsbytecode EnableInterruptsPseudoOpcode = -1;
-
-static_assert(EnableInterruptsPseudoOpcode >= JSOP_LIMIT,
-              "EnableInterruptsPseudoOpcode must be greater than any opcode");
-static_assert(
-    EnableInterruptsPseudoOpcode == jsbytecode(-1),
-    "EnableInterruptsPseudoOpcode must be the maximum jsbytecode value");
-
-class InterpreterFrameIterator;
-class RunState;
-
-class InterpreterActivation : public Activation {
-  friend class js::InterpreterFrameIterator;
-
-  InterpreterRegs regs_;
-  InterpreterFrame* entryFrame_;
-  size_t opMask_;  // For debugger interrupts, see js::Interpret.
-
-#ifdef DEBUG
-  size_t oldFrameCount_;
-#endif
-
- public:
-  inline InterpreterActivation(RunState& state, JSContext* cx,
-                               InterpreterFrame* entryFrame);
-  inline ~InterpreterActivation();
-
-  inline bool pushInlineFrame(const CallArgs& args, HandleScript script,
-                              MaybeConstruct constructing);
-  inline void popInlineFrame(InterpreterFrame* frame);
-
-  inline bool resumeGeneratorFrame(HandleFunction callee,
-                                   HandleObject envChain);
-
-  InterpreterFrame* current() const { return regs_.fp(); }
-  InterpreterRegs& regs() { return regs_; }
-  InterpreterFrame* entryFrame() const { return entryFrame_; }
-  size_t opMask() const { return opMask_; }
-
-  bool isProfiling() const { return false; }
-
-  // If this js::Interpret frame is running |script|, enable interrupts.
-  void enableInterruptsIfRunning(JSScript* script) {
-    if (regs_.fp()->script() == script) {
-      enableInterruptsUnconditionally();
-    }
-  }
-  void enableInterruptsUnconditionally() {
-    opMask_ = EnableInterruptsPseudoOpcode;
-  }
-  void clearInterruptsMask() { opMask_ = 0; }
-};
-
-// Iterates over a thread's activation list.
-class ActivationIterator {
- protected:
-  Activation* activation_;
-
- public:
-  explicit ActivationIterator(JSContext* cx);
-
-  ActivationIterator& operator++();
-
-  Activation* operator->() const { return activation_; }
-  Activation* activation() const { return activation_; }
-  bool done() const { return activation_ == nullptr; }
-};
-
-namespace jit {
-
-class BailoutFrameInfo;
-
-// A JitActivation is used for frames running in Baseline or Ion.
-class JitActivation : public Activation {
-  // If Baseline, Ion or Wasm code is on the stack, and has called into C++,
-  // this will be aligned to an ExitFrame. The last bit indicates if it's a
-  // wasm frame (bit set to wasm::ExitOrJitEntryFPTag) or not
-  // (bit set to ~wasm::ExitOrJitEntryFPTag).
-  uint8_t* packedExitFP_;
-
-  // When hasWasmExitFP(), encodedWasmExitReason_ holds ExitReason.
-  uint32_t encodedWasmExitReason_;
-
-  JitActivation* prevJitActivation_;
-
-  // Rematerialized Ion frames which has info copied out of snapshots. Maps
-  // frame pointers (i.e. packedExitFP_) to a vector of rematerializations of
-  // all inline frames associated with that frame.
-  //
-  // This table is lazily initialized by calling getRematerializedFrame.
-  typedef GCVector<UniquePtr<RematerializedFrame>> RematerializedFrameVector;
-  typedef HashMap<uint8_t*, RematerializedFrameVector> RematerializedFrameTable;
-  js::UniquePtr<RematerializedFrameTable> rematerializedFrames_;
-
-  // This vector is used to remember the outcome of the evaluation of recover
-  // instructions.
-  //
-  // RInstructionResults are appended into this vector when Snapshot values
-  // have to be read, or when the evaluation has to run before some mutating
-  // code.  Each RInstructionResults belongs to one frame which has to bailout
-  // as soon as we get back to it.
-  typedef Vector<RInstructionResults, 1> IonRecoveryMap;
-  IonRecoveryMap ionRecovery_;
-
-  // If we are bailing out from Ion, then this field should be a non-null
-  // pointer which references the BailoutFrameInfo used to walk the inner
-  // frames. This field is used for all newly constructed JSJitFrameIters to
-  // read the innermost frame information from this bailout data instead of
-  // reading it from the stack.
-  BailoutFrameInfo* bailoutData_;
-
-  // When profiling is enabled, these fields will be updated to reflect the
-  // last pushed frame for this activation, and if that frame has been
-  // left for a call, the native code site of the call.
-  mozilla::Atomic<void*, mozilla::Relaxed> lastProfilingFrame_;
-  mozilla::Atomic<void*, mozilla::Relaxed> lastProfilingCallSite_;
-  static_assert(sizeof(mozilla::Atomic<void*, mozilla::Relaxed>) ==
-                    sizeof(void*),
-                "Atomic should have same memory format as underlying type.");
-
-  // When wasm traps, the signal handler records some data for unwinding
-  // purposes. Wasm code can't trap reentrantly.
-  mozilla::Maybe<wasm::TrapData> wasmTrapData_;
-
-  void clearRematerializedFrames();
-
-#ifdef CHECK_OSIPOINT_REGISTERS
- protected:
-  // Used to verify that live registers don't change between a VM call and
-  // the OsiPoint that follows it. Protected to silence Clang warning.
-  uint32_t checkRegs_ = 0;
-  RegisterDump regs_;
-#endif
-
- public:
-  explicit JitActivation(JSContext* cx);
-  ~JitActivation();
-
-  bool isProfiling() const {
-    // All JitActivations can be profiled.
-    return true;
-  }
-
-  JitActivation* prevJitActivation() const { return prevJitActivation_; }
-  static size_t offsetOfPrevJitActivation() {
-    return offsetof(JitActivation, prevJitActivation_);
-  }
-
-  bool hasExitFP() const { return !!packedExitFP_; }
-  uint8_t* jsOrWasmExitFP() const {
-    return (uint8_t*)(uintptr_t(packedExitFP_) & ~wasm::ExitOrJitEntryFPTag);
-  }
-  static size_t offsetOfPackedExitFP() {
-    return offsetof(JitActivation, packedExitFP_);
-  }
-
-  bool hasJSExitFP() const {
-    return !(uintptr_t(packedExitFP_) & wasm::ExitOrJitEntryFPTag);
-  }
-  uint8_t* jsExitFP() const {
-    MOZ_ASSERT(hasJSExitFP());
-    return packedExitFP_;
-  }
-  void setJSExitFP(uint8_t* fp) { packedExitFP_ = fp; }
-
-#ifdef CHECK_OSIPOINT_REGISTERS
-  void setCheckRegs(bool check) { checkRegs_ = check; }
-  static size_t offsetOfCheckRegs() {
-    return offsetof(JitActivation, checkRegs_);
-  }
-  static size_t offsetOfRegs() { return offsetof(JitActivation, regs_); }
-#endif
-
-  // Look up a rematerialized frame keyed by the fp, rematerializing the
-  // frame if one doesn't already exist. A frame can only be rematerialized
-  // if an IonFrameIterator pointing to the nearest uninlined frame can be
-  // provided, as values need to be read out of snapshots.
-  //
-  // The inlineDepth must be within bounds of the frame pointed to by iter.
-  RematerializedFrame* getRematerializedFrame(JSContext* cx,
-                                              const JSJitFrameIter& iter,
-                                              size_t inlineDepth = 0);
-
-  // Look up a rematerialized frame by the fp. If inlineDepth is out of
-  // bounds of what has been rematerialized, nullptr is returned.
-  RematerializedFrame* lookupRematerializedFrame(uint8_t* top,
-                                                 size_t inlineDepth = 0);
-
-  // Remove all rematerialized frames associated with the fp top from the
-  // Debugger.
-  void removeRematerializedFramesFromDebugger(JSContext* cx, uint8_t* top);
-
-  bool hasRematerializedFrame(uint8_t* top, size_t inlineDepth = 0) {
-    return !!lookupRematerializedFrame(top, inlineDepth);
-  }
-
-  // Remove a previous rematerialization by fp.
-  void removeRematerializedFrame(uint8_t* top);
-
-  void traceRematerializedFrames(JSTracer* trc);
-
-  // Register the results of on Ion frame recovery.
-  bool registerIonFrameRecovery(RInstructionResults&& results);
-
-  // Return the pointer to the Ion frame recovery, if it is already registered.
-  RInstructionResults* maybeIonFrameRecovery(JitFrameLayout* fp);
-
-  // If an Ion frame recovery exists for the |fp| frame exists, then remove it
-  // from the activation.
-  void removeIonFrameRecovery(JitFrameLayout* fp);
-
-  void traceIonRecovery(JSTracer* trc);
-
-  // Return the bailout information if it is registered.
-  const BailoutFrameInfo* bailoutData() const { return bailoutData_; }
-
-  // Register the bailout data when it is constructed.
-  void setBailoutData(BailoutFrameInfo* bailoutData);
-
-  // Unregister the bailout data when the frame is reconstructed.
-  void cleanBailoutData();
-
-  static size_t offsetOfLastProfilingFrame() {
-    return offsetof(JitActivation, lastProfilingFrame_);
-  }
-  void* lastProfilingFrame() { return lastProfilingFrame_; }
-  void setLastProfilingFrame(void* ptr) { lastProfilingFrame_ = ptr; }
-
-  static size_t offsetOfLastProfilingCallSite() {
-    return offsetof(JitActivation, lastProfilingCallSite_);
-  }
-  void* lastProfilingCallSite() { return lastProfilingCallSite_; }
-  void setLastProfilingCallSite(void* ptr) { lastProfilingCallSite_ = ptr; }
-
-  // WebAssembly specific attributes.
-  bool hasWasmExitFP() const {
-    return uintptr_t(packedExitFP_) & wasm::ExitOrJitEntryFPTag;
-  }
-  wasm::Frame* wasmExitFP() const {
-    MOZ_ASSERT(hasWasmExitFP());
-    return (wasm::Frame*)(uintptr_t(packedExitFP_) &
-                          ~wasm::ExitOrJitEntryFPTag);
-  }
-  void setWasmExitFP(const wasm::Frame* fp) {
-    if (fp) {
-      MOZ_ASSERT(!(uintptr_t(fp) & wasm::ExitOrJitEntryFPTag));
-      packedExitFP_ = (uint8_t*)(uintptr_t(fp) | wasm::ExitOrJitEntryFPTag);
-      MOZ_ASSERT(hasWasmExitFP());
-    } else {
-      packedExitFP_ = nullptr;
-    }
-  }
-  wasm::ExitReason wasmExitReason() const {
-    MOZ_ASSERT(hasWasmExitFP());
-    return wasm::ExitReason::Decode(encodedWasmExitReason_);
-  }
-  static size_t offsetOfEncodedWasmExitReason() {