Bug 1535994 - Part 4: Move stackDepth to BytecodeSection class. r=jorendorff
authorTooru Fujisawa <arai_a@mac.com>
Tue, 02 Apr 2019 18:17:02 +0900
changeset 468815 66a27a2dece1aae22680d4f4b835640cd0c5df82
parent 468814 eb9c786879f40e3d9758f49abe205940d9c5dbae
child 468816 5781fc07513fd056b8a6f9a45018968d1e698059
push id35851
push userdvarga@mozilla.com
push dateWed, 10 Apr 2019 21:56:12 +0000
treeherdermozilla-central@30ca3c3abfe6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs1535994
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1535994 - Part 4: Move stackDepth to BytecodeSection class. r=jorendorff Differential Revision: https://phabricator.services.mozilla.com/D25734
js/src/frontend/BytecodeControlStructures.cpp
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/BytecodeEmitter.h
js/src/frontend/CForEmitter.cpp
js/src/frontend/DoWhileEmitter.cpp
js/src/frontend/ExpressionStatementEmitter.cpp
js/src/frontend/ForInEmitter.cpp
js/src/frontend/ForOfEmitter.cpp
js/src/frontend/ForOfLoopControl.cpp
js/src/frontend/IfEmitter.cpp
js/src/frontend/TryEmitter.cpp
js/src/frontend/WhileEmitter.cpp
js/src/vm/JSScript.cpp
--- a/js/src/frontend/BytecodeControlStructures.cpp
+++ b/js/src/frontend/BytecodeControlStructures.cpp
@@ -36,17 +36,17 @@ LabelControl::LabelControl(BytecodeEmitt
       startOffset_(startOffset) {}
 
 LoopControl::LoopControl(BytecodeEmitter* bce, StatementKind loopKind)
     : BreakableControl(bce, loopKind), tdzCache_(bce) {
   MOZ_ASSERT(is<LoopControl>());
 
   LoopControl* enclosingLoop = findNearest<LoopControl>(enclosing());
 
-  stackDepth_ = bce->stackDepth;
+  stackDepth_ = bce->bytecodeSection().stackDepth();
   loopDepth_ = enclosingLoop ? enclosingLoop->loopDepth_ + 1 : 1;
 
   int loopSlots;
   if (loopKind == StatementKind::Spread) {
     // The iterator next method, the iterator, the result array, and
     // the current array index are on the stack.
     loopSlots = 4;
   } else if (loopKind == StatementKind::ForOfLoop) {
@@ -76,17 +76,17 @@ bool LoopControl::emitContinueTarget(Byt
     return false;
   }
   return true;
 }
 
 bool LoopControl::emitSpecialBreakForDone(BytecodeEmitter* bce) {
   // This doesn't pop stack values, nor handle any other controls.
   // Should be called on the toplevel of the loop.
-  MOZ_ASSERT(bce->stackDepth == stackDepth_);
+  MOZ_ASSERT(bce->bytecodeSection().stackDepth() == stackDepth_);
   MOZ_ASSERT(bce->innermostNestableControl == this);
 
   if (!bce->newSrcNote(SRC_BREAK)) {
     return false;
   }
   if (!bce->emitJump(JSOP_GOTO, &breaks)) {
     return false;
   }
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -242,28 +242,28 @@ bool BytecodeEmitter::emitCheck(JSOp op,
 
   if (BytecodeOpHasIC(op)) {
     numICEntries++;
   }
 
   return true;
 }
 
-void BytecodeEmitter::updateDepth(ptrdiff_t target) {
-  jsbytecode* pc = bytecodeSection().code(target);
+void BytecodeEmitter::BytecodeSection::updateDepth(ptrdiff_t target) {
+  jsbytecode* pc = code(target);
 
   int nuses = StackUses(pc);
   int ndefs = StackDefs(pc);
 
-  stackDepth -= nuses;
-  MOZ_ASSERT(stackDepth >= 0);
-  stackDepth += ndefs;
-
-  if ((uint32_t)stackDepth > maxStackDepth) {
-    maxStackDepth = stackDepth;
+  stackDepth_ -= nuses;
+  MOZ_ASSERT(stackDepth_ >= 0);
+  stackDepth_ += ndefs;
+
+  if ((uint32_t)stackDepth_ > maxStackDepth_) {
+    maxStackDepth_ = stackDepth_;
   }
 }
 
 #ifdef DEBUG
 bool BytecodeEmitter::checkStrictOrSloppy(JSOp op) {
   if (IsCheckStrictOp(op) && !sc->strict()) {
     return false;
   }
@@ -279,32 +279,32 @@ bool BytecodeEmitter::emit1(JSOp op) {
 
   ptrdiff_t offset;
   if (!emitCheck(op, 1, &offset)) {
     return false;
   }
 
   jsbytecode* code = bytecodeSection().code(offset);
   code[0] = jsbytecode(op);
-  updateDepth(offset);
+  bytecodeSection().updateDepth(offset);
   return true;
 }
 
 bool BytecodeEmitter::emit2(JSOp op, uint8_t op1) {
   MOZ_ASSERT(checkStrictOrSloppy(op));
 
   ptrdiff_t offset;
   if (!emitCheck(op, 2, &offset)) {
     return false;
   }
 
   jsbytecode* code = bytecodeSection().code(offset);
   code[0] = jsbytecode(op);
   code[1] = jsbytecode(op1);
-  updateDepth(offset);
+  bytecodeSection().updateDepth(offset);
   return true;
 }
 
 bool BytecodeEmitter::emit3(JSOp op, jsbytecode op1, jsbytecode op2) {
   MOZ_ASSERT(checkStrictOrSloppy(op));
 
   /* These should filter through emitVarOp. */
   MOZ_ASSERT(!IsArgOp(op));
@@ -314,17 +314,17 @@ bool BytecodeEmitter::emit3(JSOp op, jsb
   if (!emitCheck(op, 3, &offset)) {
     return false;
   }
 
   jsbytecode* code = bytecodeSection().code(offset);
   code[0] = jsbytecode(op);
   code[1] = op1;
   code[2] = op2;
-  updateDepth(offset);
+  bytecodeSection().updateDepth(offset);
   return true;
 }
 
 bool BytecodeEmitter::emitN(JSOp op, size_t extra, ptrdiff_t* offset) {
   MOZ_ASSERT(checkStrictOrSloppy(op));
   ptrdiff_t length = 1 + ptrdiff_t(extra);
 
   ptrdiff_t off;
@@ -336,17 +336,17 @@ bool BytecodeEmitter::emitN(JSOp op, siz
   code[0] = jsbytecode(op);
   /* The remaining |extra| bytes are set by the caller */
 
   /*
    * Don't updateDepth if op's use-count comes from the immediate
    * operand yet to be stored in the extra bytes after op.
    */
   if (CodeSpec[op].nuses >= 0) {
-    updateDepth(off);
+    bytecodeSection().updateDepth(off);
   }
 
   if (offset) {
     *offset = off;
   }
   return true;
 }
 
@@ -389,17 +389,17 @@ bool BytecodeEmitter::emitJumpNoFallthro
   if (!emitCheck(op, 5, &offset)) {
     return false;
   }
 
   jsbytecode* code = bytecodeSection().code(offset);
   code[0] = jsbytecode(op);
   MOZ_ASSERT(-1 <= jump->offset && jump->offset < offset);
   jump->push(bytecodeSection().code(0), offset);
-  updateDepth(offset);
+  bytecodeSection().updateDepth(offset);
   return true;
 }
 
 bool BytecodeEmitter::emitJump(JSOp op, JumpList* jump) {
   if (!emitJumpNoFallthrough(op, jump)) {
     return false;
   }
   if (BytecodeFallsThrough(op)) {
@@ -458,17 +458,17 @@ bool BytecodeEmitter::emitCall(JSOp op, 
   return emit3(op, ARGC_LO(argc), ARGC_HI(argc));
 }
 
 bool BytecodeEmitter::emitCall(JSOp op, uint16_t argc, ParseNode* pn) {
   return emitCall(op, argc, pn ? Some(pn->pn_pos.begin) : Nothing());
 }
 
 bool BytecodeEmitter::emitDupAt(unsigned slotFromTop) {
-  MOZ_ASSERT(slotFromTop < unsigned(stackDepth));
+  MOZ_ASSERT(slotFromTop < unsigned(bytecodeSection().stackDepth()));
 
   if (slotFromTop == 0) {
     return emit1(JSOP_DUP);
   }
 
   if (slotFromTop >= JS_BIT(24)) {
     reportError(nullptr, JSMSG_TOO_MANY_LOCALS);
     return false;
@@ -664,26 +664,26 @@ class NonLocalExitControl {
   NonLocalExitControl(const NonLocalExitControl&) = delete;
 
   MOZ_MUST_USE bool leaveScope(EmitterScope* scope);
 
  public:
   NonLocalExitControl(BytecodeEmitter* bce, Kind kind)
       : bce_(bce),
         savedScopeNoteIndex_(bce->scopeNoteList.length()),
-        savedDepth_(bce->stackDepth),
+        savedDepth_(bce->bytecodeSection().stackDepth()),
         openScopeNoteIndex_(bce->innermostEmitterScope()->noteIndex()),
         kind_(kind) {}
 
   ~NonLocalExitControl() {
     for (uint32_t n = savedScopeNoteIndex_; n < bce_->scopeNoteList.length();
          n++) {
       bce_->scopeNoteList.recordEnd(n, bce_->bytecodeSection().offset());
     }
-    bce_->stackDepth = savedDepth_;
+    bce_->bytecodeSection().setStackDepth(savedDepth_);
   }
 
   MOZ_MUST_USE bool prepareForNonLocalJump(NestableControl* target);
 
   MOZ_MUST_USE bool prepareForNonLocalJumpToOutermost() {
     return prepareForNonLocalJump(nullptr);
   }
 };
@@ -888,17 +888,17 @@ bool BytecodeEmitter::emitIndex32(JSOp o
   ptrdiff_t offset;
   if (!emitCheck(op, len, &offset)) {
     return false;
   }
 
   jsbytecode* code = bytecodeSection().code(offset);
   code[0] = jsbytecode(op);
   SET_UINT32_INDEX(code, index);
-  updateDepth(offset);
+  bytecodeSection().updateDepth(offset);
   return true;
 }
 
 bool BytecodeEmitter::emitIndexOp(JSOp op, uint32_t index) {
   MOZ_ASSERT(checkStrictOrSloppy(op));
 
   const size_t len = CodeSpec[op].length;
   MOZ_ASSERT(len >= 1 + UINT32_INDEX_LEN);
@@ -906,17 +906,17 @@ bool BytecodeEmitter::emitIndexOp(JSOp o
   ptrdiff_t offset;
   if (!emitCheck(op, len, &offset)) {
     return false;
   }
 
   jsbytecode* code = bytecodeSection().code(offset);
   code[0] = jsbytecode(op);
   SET_UINT32_INDEX(code, index);
-  updateDepth(offset);
+  bytecodeSection().updateDepth(offset);
   return true;
 }
 
 bool BytecodeEmitter::emitAtomOp(JSAtom* atom, JSOp op) {
   MOZ_ASSERT(atom);
 
   // .generator lookups should be emitted as JSOP_GETALIASEDVAR instead of
   // JSOP_GETNAME etc, to bypass |with| objects on the scope chain.
@@ -1687,17 +1687,17 @@ bool BytecodeEmitter::emitNewInit() {
   }
 
   jsbytecode* code = bytecodeSection().code(offset);
   code[0] = JSOP_NEWINIT;
   code[1] = 0;
   code[2] = 0;
   code[3] = 0;
   code[4] = 0;
-  updateDepth(offset);
+  bytecodeSection().updateDepth(offset);
   return true;
 }
 
 bool BytecodeEmitter::iteratorResultShape(unsigned* shape) {
   // No need to do any guessing for the object kind, since we know exactly how
   // many properties we plan to have.
   gc::AllocKind kind = gc::GetGCObjectKind(2);
   RootedPlainObject obj(
@@ -2021,17 +2021,17 @@ bool BytecodeEmitter::emitDouble(double 
   ptrdiff_t offset;
   if (!emitCheck(JSOP_DOUBLE, 9, &offset)) {
     return false;
   }
 
   jsbytecode* code = bytecodeSection().code(offset);
   code[0] = jsbytecode(JSOP_DOUBLE);
   SET_INLINE_VALUE(code, DoubleValue(d));
-  updateDepth(offset);
+  bytecodeSection().updateDepth(offset);
   return true;
 }
 
 bool BytecodeEmitter::emitNumberOp(double dval) {
   int32_t ival;
   if (NumberIsInt32(dval, &ival)) {
     if (ival == 0) {
       return emit1(JSOP_ZERO);
@@ -2570,17 +2570,17 @@ bool BytecodeEmitter::emitDestructuringL
   // setting or initializing value.  Getting reference doesn't recur.
   if (target->isKind(ParseNodeKind::Name) ||
       target->isKind(ParseNodeKind::ArrayExpr) ||
       target->isKind(ParseNodeKind::ObjectExpr)) {
     return true;
   }
 
 #ifdef DEBUG
-  int depth = stackDepth;
+  int depth = bytecodeSection().stackDepth();
 #endif
 
   switch (target->getKind()) {
     case ParseNodeKind::DotExpr: {
       PropertyAccess* prop = &target->as<PropertyAccess>();
       bool isSuper = prop->isSuper();
       PropOpEmitter poe(this, PropOpEmitter::Kind::SimpleAssignment,
                         isSuper ? PropOpEmitter::ObjKind::Super
@@ -2648,17 +2648,17 @@ bool BytecodeEmitter::emitDestructuringL
           "rejects function calls as assignment "
           "targets in destructuring assignments");
       break;
 
     default:
       MOZ_CRASH("emitDestructuringLHSRef: bad lhs kind");
   }
 
-  MOZ_ASSERT(stackDepth == depth + int(*emitted));
+  MOZ_ASSERT(bytecodeSection().stackDepth() == depth + int(*emitted));
 
   return true;
 }
 
 bool BytecodeEmitter::emitSetOrInitializeDestructuring(
     ParseNode* target, DestructuringFlavor flav) {
   // Now emit the lvalue opcode sequence. If the lvalue is a nested
   // destructuring initialiser-form, call ourselves to handle it, then pop
@@ -2811,17 +2811,17 @@ bool BytecodeEmitter::emitIteratorNext(
     const Maybe<uint32_t>& callSourceCoordOffset,
     IteratorKind iterKind /* = IteratorKind::Sync */,
     bool allowSelfHosted /* = false */) {
   MOZ_ASSERT(allowSelfHosted || emitterMode != BytecodeEmitter::SelfHosting,
              ".next() iteration is prohibited in self-hosted code because it "
              "can run user-modifiable iteration code");
 
   //                [stack] ... NEXT ITER
-  MOZ_ASSERT(this->stackDepth >= 2);
+  MOZ_ASSERT(bytecodeSection().stackDepth() >= 2);
 
   if (!emitCall(JSOP_CALL, 0, callSourceCoordOffset)) {
     //              [stack] ... RESULT
     return false;
   }
 
   if (iterKind == IteratorKind::Async) {
     if (!emitAwaitInInnermostScope()) {
@@ -2834,17 +2834,17 @@ bool BytecodeEmitter::emitIteratorNext(
     //              [stack] ... RESULT
     return false;
   }
   return true;
 }
 
 bool BytecodeEmitter::emitPushNotUndefinedOrNull() {
   //                [stack] V
-  MOZ_ASSERT(this->stackDepth > 0);
+  MOZ_ASSERT(bytecodeSection().stackDepth() > 0);
 
   if (!emit1(JSOP_DUP)) {
     //              [stack] V V
     return false;
   }
   if (!emit1(JSOP_UNDEFINED)) {
     //              [stack] V V UNDEFINED
     return false;
@@ -3082,17 +3082,17 @@ bool BytecodeEmitter::emitIteratorCloseI
 
   return emit1(JSOP_POP);
   //                [stack] ...
 }
 
 template <typename InnerEmitter>
 bool BytecodeEmitter::wrapWithDestructuringTryNote(int32_t iterDepth,
                                                    InnerEmitter emitter) {
-  MOZ_ASSERT(this->stackDepth >= iterDepth);
+  MOZ_ASSERT(bytecodeSection().stackDepth() >= iterDepth);
 
   // Pad a nop at the beginning of the bytecode covered by the trynote so
   // that when unwinding environments, we may unwind to the scope
   // corresponding to the pc *before* the start, in case the first bytecode
   // emitted by |emitter| is the start of an inner scope. See comment above
   // UnwindEnvironmentToTryPc.
   if (!emit1(JSOP_TRY_DESTRUCTURING)) {
     return false;
@@ -3203,17 +3203,17 @@ bool BytecodeEmitter::emitInitializer(Pa
   }
 
   return true;
 }
 
 bool BytecodeEmitter::emitDestructuringOpsArray(ListNode* pattern,
                                                 DestructuringFlavor flav) {
   MOZ_ASSERT(pattern->isKind(ParseNodeKind::ArrayExpr));
-  MOZ_ASSERT(this->stackDepth != 0);
+  MOZ_ASSERT(bytecodeSection().stackDepth() != 0);
 
   // Here's pseudo code for |let [a, b, , c=y, ...d] = x;|
   //
   // Lines that are annotated "covered by trynote" mean that upon throwing
   // an exception, IteratorClose is called on iter only if done is false.
   //
   //   let x, y;
   //   let a, b, c, d;
@@ -3327,17 +3327,17 @@ bool BytecodeEmitter::emitDestructuringO
   if (!emit1(JSOP_FALSE)) {
     //              [stack] ... OBJ NEXT ITER FALSE
     return false;
   }
 
   // JSTRY_DESTRUCTURING expects the iterator and the done value
   // to be the second to top and the top of the stack, respectively.
   // IteratorClose is called upon exception only if done is false.
-  int32_t tryNoteDepth = stackDepth;
+  int32_t tryNoteDepth = bytecodeSection().stackDepth();
 
   for (ParseNode* member : pattern->contents()) {
     bool isFirst = member == pattern->head();
     DebugOnly<bool> hasNext = !!member->pn_next;
 
     size_t emitted = 0;
 
     // Spec requires LHS reference to be evaluated first.
@@ -3636,17 +3636,17 @@ bool BytecodeEmitter::emitComputedProper
   return emitTree(computedPropName->kid()) && emit1(JSOP_TOID);
 }
 
 bool BytecodeEmitter::emitDestructuringOpsObject(ListNode* pattern,
                                                  DestructuringFlavor flav) {
   MOZ_ASSERT(pattern->isKind(ParseNodeKind::ObjectExpr));
 
   //                [stack] ... RHS
-  MOZ_ASSERT(this->stackDepth > 0);
+  MOZ_ASSERT(bytecodeSection().stackDepth() > 0);
 
   if (!emit1(JSOP_CHECKOBJCOERCIBLE)) {
     //              [stack] ... RHS
     return false;
   }
 
   bool needsRestPropertyExcludedSet =
       pattern->count() > 1 && pattern->last()->isKind(ParseNodeKind::Spread);
@@ -4900,17 +4900,17 @@ bool BytecodeEmitter::emitWith(BinaryNod
   if (!emitTree(withNode->right())) {
     return false;
   }
 
   return emitterScope.leave(this);
 }
 
 bool BytecodeEmitter::emitCopyDataProperties(CopyOption option) {
-  DebugOnly<int32_t> depth = this->stackDepth;
+  DebugOnly<int32_t> depth = bytecodeSection().stackDepth();
 
   uint32_t argc;
   if (option == CopyOption::Filtered) {
     MOZ_ASSERT(depth > 2);
     //              [stack] TARGET SOURCE SET
     argc = 3;
 
     if (!emitAtomOp(cx->names().CopyDataProperties, JSOP_GETINTRINSIC)) {
@@ -4955,17 +4955,17 @@ bool BytecodeEmitter::emitCopyDataProper
     return false;
   }
 
   if (!emit1(JSOP_POP)) {
     //              [stack]
     return false;
   }
 
-  MOZ_ASSERT(depth - int(argc) == this->stackDepth);
+  MOZ_ASSERT(depth - int(argc) == bytecodeSection().stackDepth());
   return true;
 }
 
 bool BytecodeEmitter::emitBigIntOp(BigInt* bigint) {
   if (!numberList.append(BigIntValue(bigint))) {
     return false;
   }
   return emitIndex32(JSOP_BIGINT, numberList.length() - 1);
@@ -5146,34 +5146,34 @@ bool BytecodeEmitter::emitSpread(bool al
     //              [stack] NEXT ITER ARR I
     return false;
   }
 
   // When we enter the goto above, we have NEXT ITER ARR I on the stack. But
   // when we reach this point on the loop backedge (if spreading produces at
   // least one value), we've additionally pushed a RESULT iteration value.
   // Increment manually to reflect this.
-  this->stackDepth++;
+  bytecodeSection().setStackDepth(bytecodeSection().stackDepth() + 1);
 
   {
 #ifdef DEBUG
-    auto loopDepth = this->stackDepth;
+    auto loopDepth = bytecodeSection().stackDepth();
 #endif
 
     // Emit code to assign result.value to the iteration variable.
     if (!emitAtomOp(cx->names().value, JSOP_GETPROP)) {
       //            [stack] NEXT ITER ARR I VALUE
       return false;
     }
     if (!emit1(JSOP_INITELEM_INC)) {
       //            [stack] NEXT ITER ARR (I+1)
       return false;
     }
 
-    MOZ_ASSERT(this->stackDepth == loopDepth - 1);
+    MOZ_ASSERT(bytecodeSection().stackDepth() == loopDepth - 1);
 
     // Spread operations can't contain |continue|, so don't bother setting loop
     // and enclosing "update" offsets, as we do with for-loops.
 
     // COME FROM the beginning of the loop to here.
     if (!loopInfo.emitLoopEntry(this, Nothing())) {
       //            [stack] NEXT ITER ARR I
       return false;
@@ -5200,31 +5200,31 @@ bool BytecodeEmitter::emitSpread(bool al
       return false;
     }
 
     if (!loopInfo.emitLoopEnd(this, JSOP_IFEQ)) {
       //            [stack] NEXT ITER ARR I RESULT
       return false;
     }
 
-    MOZ_ASSERT(this->stackDepth == loopDepth);
+    MOZ_ASSERT(bytecodeSection().stackDepth() == loopDepth);
   }
 
   // Let Ion know where the closing jump of this loop is.
   if (!setSrcNoteOffset(noteIndex, SrcNote::ForOf::BackJumpOffset,
                         loopInfo.loopEndOffsetFromEntryJump())) {
     return false;
   }
 
   // No breaks or continues should occur in spreads.
   MOZ_ASSERT(loopInfo.breaks.offset == -1);
   MOZ_ASSERT(loopInfo.continues.offset == -1);
 
-  if (!addTryNote(JSTRY_FOR_OF, stackDepth, loopInfo.headOffset(),
-                  loopInfo.breakTargetOffset())) {
+  if (!addTryNote(JSTRY_FOR_OF, bytecodeSection().stackDepth(),
+                  loopInfo.headOffset(), loopInfo.breakTargetOffset())) {
     return false;
   }
 
   if (!emit2(JSOP_PICK, 4)) {
     //              [stack] ITER ARR FINAL_INDEX RESULT NEXT
     return false;
   }
   if (!emit2(JSOP_PICK, 4)) {
@@ -5235,17 +5235,17 @@ bool BytecodeEmitter::emitSpread(bool al
   return emitPopN(3);
   //                [stack] ARR FINAL_INDEX
 }
 
 bool BytecodeEmitter::emitInitializeForInOrOfTarget(TernaryNode* forHead) {
   MOZ_ASSERT(forHead->isKind(ParseNodeKind::ForIn) ||
              forHead->isKind(ParseNodeKind::ForOf));
 
-  MOZ_ASSERT(this->stackDepth >= 1,
+  MOZ_ASSERT(bytecodeSection().stackDepth() >= 1,
              "must have a per-iteration value for initializing");
 
   ParseNode* target = forHead->kid1();
   MOZ_ASSERT(!forHead->kid2());
 
   // If the for-in/of loop didn't have a variable declaration, per-loop
   // initialization is just assigning the iteration value to a target
   // expression.
@@ -5283,24 +5283,24 @@ bool BytecodeEmitter::emitInitializeForI
     if (!noe.prepareForRhs()) {
       return false;
     }
     if (noe.emittedBindOp()) {
       // Per-iteration initialization in for-in/of loops computes the
       // iteration value *before* initializing.  Thus the initializing
       // value may be buried under a bind-specific value on the stack.
       // Swap it to the top of the stack.
-      MOZ_ASSERT(stackDepth >= 2);
+      MOZ_ASSERT(bytecodeSection().stackDepth() >= 2);
       if (!emit1(JSOP_SWAP)) {
         return false;
       }
     } else {
       // In cases of emitting a frame slot or environment slot,
       // nothing needs be done.
-      MOZ_ASSERT(stackDepth >= 1);
+      MOZ_ASSERT(bytecodeSection().stackDepth() >= 1);
     }
     if (!noe.emitAssignment()) {
       return false;
     }
 
     // The caller handles removing the iteration value from the stack.
     return true;
   }
@@ -6215,17 +6215,17 @@ bool BytecodeEmitter::emitYieldStar(Pars
   // Step 6.
   // Initial send value is undefined.
   if (!emit1(JSOP_UNDEFINED)) {
     //              [stack] NEXT ITER RECEIVED
     return false;
   }
 
   int32_t savedDepthTemp;
-  int32_t startDepth = stackDepth;
+  int32_t startDepth = bytecodeSection().stackDepth();
   MOZ_ASSERT(startDepth >= 3);
 
   TryEmitter tryCatch(this, TryEmitter::Kind::TryCatchFinally,
                       TryEmitter::ControlKind::NonSyntactic);
   if (!tryCatch.emitJumpOverCatchAndFinally()) {
     //              [stack] NEXT ITER RESULT
     return false;
   }
@@ -6247,17 +6247,17 @@ bool BytecodeEmitter::emitYieldStar(Pars
     }
   }
 
   if (!tryCatch.emitTry()) {
     //              [stack] NEXT ITER RESULT
     return false;
   }
 
-  MOZ_ASSERT(this->stackDepth == startDepth);
+  MOZ_ASSERT(bytecodeSection().stackDepth() == startDepth);
 
   // Step 7.a.vi.
   // Step 7.b.ii.7.
   // Step 7.c.ix.
   //   25.5.3.7 AsyncGeneratorYield, step 5.
   if (iterKind == IteratorKind::Async) {
     if (!emitAwaitInInnermostScope()) {
       //            [stack] NEXT ITER RESULT
@@ -6280,17 +6280,17 @@ bool BytecodeEmitter::emitYieldStar(Pars
     return false;
   }
 
   if (!tryCatch.emitCatch()) {
     //              [stack] NEXT ITER RESULT
     return false;
   }
 
-  MOZ_ASSERT(stackDepth == startDepth);
+  MOZ_ASSERT(bytecodeSection().stackDepth() == startDepth);
 
   if (!emit1(JSOP_EXCEPTION)) {
     //              [stack] NEXT ITER RESULT EXCEPTION
     return false;
   }
   if (!emitDupAt(2)) {
     //              [stack] NEXT ITER RESULT EXCEPTION ITER
     return false;
@@ -6299,17 +6299,17 @@ bool BytecodeEmitter::emitYieldStar(Pars
     //              [stack] NEXT ITER RESULT EXCEPTION ITER ITER
     return false;
   }
   if (!emitAtomOp(cx->names().throw_, JSOP_CALLPROP)) {
     //              [stack] NEXT ITER RESULT EXCEPTION ITER THROW
     return false;
   }
 
-  savedDepthTemp = stackDepth;
+  savedDepthTemp = bytecodeSection().stackDepth();
   InternalIfEmitter ifThrowMethodIsNotDefined(this);
   if (!emitPushNotUndefinedOrNull()) {
     //              [stack] NEXT ITER RESULT EXCEPTION ITER THROW
     //                    NOT-UNDEF-OR-NULL
     return false;
   }
 
   if (!ifThrowMethodIsNotDefined.emitThenElse()) {
@@ -6350,28 +6350,28 @@ bool BytecodeEmitter::emitYieldStar(Pars
   if (!emit1(JSOP_SWAP)) {
     //              [stack] NEXT ITER RESULT OLDRESULT
     return false;
   }
   if (!emit1(JSOP_POP)) {
     //              [stack] NEXT ITER RESULT
     return false;
   }
-  MOZ_ASSERT(this->stackDepth == startDepth);
+  MOZ_ASSERT(bytecodeSection().stackDepth() == startDepth);
 
   JumpList checkResult;
   // Note that there is no GOSUB to the finally block here. If the iterator has
   // a "throw" method, it does not perform IteratorClose.
   if (!emitJump(JSOP_GOTO, &checkResult)) {
     //              [stack] NEXT ITER RESULT
     //              [stack] # goto checkResult
     return false;
   }
 
-  stackDepth = savedDepthTemp;
+  bytecodeSection().setStackDepth(savedDepthTemp);
   if (!ifThrowMethodIsNotDefined.emitElse()) {
     //              [stack] NEXT ITER RESULT EXCEPTION ITER THROW
     return false;
   }
 
   if (!emit1(JSOP_POP)) {
     //              [stack] NEXT ITER RESULT EXCEPTION ITER
     return false;
@@ -6386,22 +6386,22 @@ bool BytecodeEmitter::emitYieldStar(Pars
   }
   // Steps 7.b.iii.5-6.
   if (!emitUint16Operand(JSOP_THROWMSG, JSMSG_ITERATOR_NO_THROW)) {
     //              [stack] NEXT ITER RESULT EXCEPTION
     //              [stack] # throw
     return false;
   }
 
-  stackDepth = savedDepthTemp;
+  bytecodeSection().setStackDepth(savedDepthTemp);
   if (!ifThrowMethodIsNotDefined.emitEnd()) {
     return false;
   }
 
-  stackDepth = startDepth;
+  bytecodeSection().setStackDepth(startDepth);
   if (!tryCatch.emitFinally()) {
     return false;
   }
 
   // Step 7.c.i.
   //
   // Call iterator.return() for receiving a "forced return" completion from
   // the generator.
@@ -6518,17 +6518,17 @@ bool BytecodeEmitter::emitYieldStar(Pars
       //            [stack] NEXT ITER OLDRESULT FTYPE FVALUE RESULT
       return false;
     }
   }
   if (!emit1(JSOP_SETRVAL)) {
     //              [stack] NEXT ITER OLDRESULT FTYPE FVALUE
     return false;
   }
-  savedDepthTemp = this->stackDepth;
+  savedDepthTemp = bytecodeSection().stackDepth();
   if (!ifReturnDone.emitElse()) {
     //              [stack] NEXT ITER OLDRESULT FTYPE FVALUE RESULT
     return false;
   }
   if (!emit2(JSOP_UNPICK, 3)) {
     //              [stack] NEXT ITER RESULT OLDRESULT FTYPE FVALUE
     return false;
   }
@@ -6540,17 +6540,17 @@ bool BytecodeEmitter::emitYieldStar(Pars
     // goto tryStart;
     JumpList beq;
     JumpTarget breakTarget{-1};
     if (!emitBackwardJump(JSOP_GOTO, tryStart, &beq, &breakTarget)) {
       //            [stack] NEXT ITER RESULT
       return false;
     }
   }
-  this->stackDepth = savedDepthTemp;
+  bytecodeSection().setStackDepth(savedDepthTemp);
   if (!ifReturnDone.emitEnd()) {
     return false;
   }
 
   if (!ifReturnMethodIsDefined.emitElse()) {
     //              [stack] NEXT ITER RESULT FTYPE FVALUE ITER RET
     return false;
   }
@@ -6615,17 +6615,17 @@ bool BytecodeEmitter::emitYieldStar(Pars
     }
   }
 
   // Step 7.a.iii.
   if (!emitCheckIsObj(CheckIsObjectKind::IteratorNext)) {
     //              [stack] NEXT ITER RESULT
     return false;
   }
-  MOZ_ASSERT(this->stackDepth == startDepth);
+  MOZ_ASSERT(bytecodeSection().stackDepth() == startDepth);
 
   // Steps 7.a.iv-v.
   // Steps 7.b.ii.5-6.
   if (!emitJumpTargetAndPatch(checkResult)) {
     //              [stack] NEXT ITER RESULT
     //              [stack] # checkResult:
     return false;
   }
@@ -6660,17 +6660,17 @@ bool BytecodeEmitter::emitYieldStar(Pars
     //              [stack] RESULT
     return false;
   }
   if (!emitAtomOp(cx->names().value, JSOP_GETPROP)) {
     //              [stack] VALUE
     return false;
   }
 
-  MOZ_ASSERT(this->stackDepth == startDepth - 2);
+  MOZ_ASSERT(bytecodeSection().stackDepth() == startDepth - 2);
 
   return true;
 }
 
 bool BytecodeEmitter::emitStatementList(ListNode* stmtList) {
   for (ParseNode* stmt : stmtList->contents()) {
     if (!emitTree(stmt)) {
       return false;
--- a/js/src/frontend/BytecodeEmitter.h
+++ b/js/src/frontend/BytecodeEmitter.h
@@ -159,16 +159,25 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
     // JumpTarget should not be part of the emitted statement, as they can be
     // aliased by multiple statements. If we included the jump target as part of
     // the statement we might have issues where the enclosing statement might
     // not contain all the opcodes of the enclosed statements.
     ptrdiff_t lastNonJumpTargetOffset() const {
       return lastOpcodeIsJumpTarget() ? lastTarget_.offset : offset();
     }
 
+    // ---- Stack ----
+
+    int32_t stackDepth() const { return stackDepth_; }
+    void setStackDepth(int32_t depth) { stackDepth_ = depth; }
+
+    uint32_t maxStackDepth() const { return maxStackDepth_; }
+
+    void updateDepth(ptrdiff_t target);
+
    private:
     // ---- Bytecode ----
 
     // Bytecode.
     BytecodeVector code_;
 
     // ---- Source notes ----
 
@@ -177,16 +186,24 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
 
     // Code offset for last source note
     ptrdiff_t lastNoteOffset_ = 0;
 
     // ---- Jump ----
 
     // Last jump target emitted.
     JumpTarget lastTarget_ = {-1 - ptrdiff_t(JSOP_JUMPTARGET_LENGTH)};
+
+    // ---- Stack ----
+
+    // Maximum number of expression stack slots so far.
+    uint32_t maxStackDepth_ = 0;
+
+    // Current stack depth in script frame.
+    int32_t stackDepth_ = 0;
   };
 
   BytecodeSection bytecodeSection_;
 
  public:
   BytecodeSection& bytecodeSection() { return bytecodeSection_; }
   const BytecodeSection& bytecodeSection() const { return bytecodeSection_; }
 
@@ -219,20 +236,16 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
   // initialized. Use |parser| instead.
   mozilla::Maybe<EitherParser> ep_ = {};
   BCEParserHandle* parser = nullptr;
 
   PooledMapPtr<AtomIndexMap> atomIndices; /* literals indexed for mapping */
   unsigned firstLine = 0; /* first line, for JSScript::initFromEmitter */
 
   uint32_t maxFixedSlots = 0; /* maximum number of fixed frame slots so far */
-  uint32_t maxStackDepth =
-      0; /* maximum number of expression stack slots so far */
-
-  int32_t stackDepth = 0; /* current stack depth in script frame */
 
   uint32_t bodyScopeIndex =
       UINT32_MAX; /* index into scopeList of the body scope */
 
   EmitterScope* varEmitterScope = nullptr;
   NestableControl* innermostNestableControl = nullptr;
   EmitterScope* innermostEmitterScope_ = nullptr;
   TDZCheckCache* innermostTDZCheckCache = nullptr;
@@ -537,17 +550,16 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
   // encompasses the entire source.
   MOZ_MUST_USE bool emitScript(ParseNode* body);
 
   // Emit function code for the tree rooted at body.
   enum class TopLevelFunction { No, Yes };
   MOZ_MUST_USE bool emitFunctionScript(FunctionNode* funNode,
                                        TopLevelFunction isTopLevel);
 
-  void updateDepth(ptrdiff_t target);
   MOZ_MUST_USE bool markStepBreakpoint();
   MOZ_MUST_USE bool markSimpleBreakpoint();
   MOZ_MUST_USE bool updateLineNumberNotes(uint32_t offset);
   MOZ_MUST_USE bool updateSourceCoordNotes(uint32_t offset);
   void updateSeparatorPosition();
 
   JSOp strictifySetNameOp(JSOp op);
 
--- a/js/src/frontend/CForEmitter.cpp
+++ b/js/src/frontend/CForEmitter.cpp
@@ -223,17 +223,18 @@ bool CForEmitter::emitEnd() {
   // The third note offset helps us find the loop-closing jump.
   if (!bce_->setSrcNoteOffset(noteIndex_, SrcNote::For::BackJumpOffset,
                               loopInfo_->loopEndOffset() - biasedTop_))
 
   {
     return false;
   }
 
-  if (!bce_->addTryNote(JSTRY_LOOP, bce_->stackDepth, loopInfo_->headOffset(),
+  if (!bce_->addTryNote(JSTRY_LOOP, bce_->bytecodeSection().stackDepth(),
+                        loopInfo_->headOffset(),
                         loopInfo_->breakTargetOffset())) {
     return false;
   }
 
   if (!loopInfo_->patchBreaksAndContinues(bce_)) {
     //              [stack]
     return false;
   }
--- a/js/src/frontend/DoWhileEmitter.cpp
+++ b/js/src/frontend/DoWhileEmitter.cpp
@@ -70,17 +70,18 @@ bool DoWhileEmitter::emitCond() {
 
 bool DoWhileEmitter::emitEnd() {
   MOZ_ASSERT(state_ == State::Cond);
 
   if (!loopInfo_->emitLoopEnd(bce_, JSOP_IFNE)) {
     return false;
   }
 
-  if (!bce_->addTryNote(JSTRY_LOOP, bce_->stackDepth, loopInfo_->headOffset(),
+  if (!bce_->addTryNote(JSTRY_LOOP, bce_->bytecodeSection().stackDepth(),
+                        loopInfo_->headOffset(),
                         loopInfo_->breakTargetOffset())) {
     return false;
   }
 
   // Update the annotations with the update and back edge positions, for
   // IonBuilder.
   if (!bce_->setSrcNoteOffset(noteIndex_, SrcNote::DoWhile::CondOffset,
                               loopInfo_->continueTargetOffsetFromLoopHead())) {
--- a/js/src/frontend/ExpressionStatementEmitter.cpp
+++ b/js/src/frontend/ExpressionStatementEmitter.cpp
@@ -24,25 +24,25 @@ bool ExpressionStatementEmitter::prepare
 
   if (beginPos) {
     if (!bce_->updateSourceCoordNotes(*beginPos)) {
       return false;
     }
   }
 
 #ifdef DEBUG
-  depth_ = bce_->stackDepth;
+  depth_ = bce_->bytecodeSection().stackDepth();
   state_ = State::Expr;
 #endif
   return true;
 }
 
 bool ExpressionStatementEmitter::emitEnd() {
   MOZ_ASSERT(state_ == State::Expr);
-  MOZ_ASSERT(bce_->stackDepth == depth_ + 1);
+  MOZ_ASSERT(bce_->bytecodeSection().stackDepth() == depth_ + 1);
 
   //                [stack] VAL
 
   JSOp op = valueUsage_ == ValueUsage::WantValue ? JSOP_SETRVAL : JSOP_POP;
   if (!bce_->emit1(op)) {
     //              [stack] # if WantValue
     //              [stack] VAL
     //              [stack] # otherwise
--- a/js/src/frontend/ForInEmitter.cpp
+++ b/js/src/frontend/ForInEmitter.cpp
@@ -89,17 +89,17 @@ bool ForInEmitter::emitInitialize() {
 
     // For uncaptured bindings, put them back in TDZ.
     if (!headLexicalEmitterScope_->deadZoneFrameSlots(bce_)) {
       return false;
     }
   }
 
 #ifdef DEBUG
-  loopDepth_ = bce_->stackDepth;
+  loopDepth_ = bce_->bytecodeSection().stackDepth();
 #endif
   MOZ_ASSERT(loopDepth_ >= 2);
 
   if (!bce_->emit1(JSOP_ITERNEXT)) {
     //              [stack] ITER ITERVAL
     return false;
   }
 
@@ -107,17 +107,17 @@ bool ForInEmitter::emitInitialize() {
   state_ = State::Initialize;
 #endif
   return true;
 }
 
 bool ForInEmitter::emitBody() {
   MOZ_ASSERT(state_ == State::Initialize);
 
-  MOZ_ASSERT(bce_->stackDepth == loopDepth_,
+  MOZ_ASSERT(bce_->bytecodeSection().stackDepth() == loopDepth_,
              "iterator and iterval must be left on the stack");
 
 #ifdef DEBUG
   state_ = State::Body;
 #endif
   return true;
 }
 
@@ -166,17 +166,18 @@ bool ForInEmitter::emitEnd(const Maybe<u
   }
 
   // Pop the enumeration value.
   if (!bce_->emit1(JSOP_POP)) {
     //              [stack] ITER
     return false;
   }
 
-  if (!bce_->addTryNote(JSTRY_FOR_IN, bce_->stackDepth, loopInfo_->headOffset(),
+  if (!bce_->addTryNote(JSTRY_FOR_IN, bce_->bytecodeSection().stackDepth(),
+                        loopInfo_->headOffset(),
                         bce_->bytecodeSection().offset())) {
     return false;
   }
 
   if (!bce_->emit1(JSOP_ENDITER)) {
     //              [stack]
     return false;
   }
--- a/js/src/frontend/ForOfEmitter.cpp
+++ b/js/src/frontend/ForOfEmitter.cpp
@@ -53,17 +53,17 @@ bool ForOfEmitter::emitInitialize(const 
     }
   } else {
     if (!bce_->emitIterator()) {
       //            [stack] NEXT ITER
       return false;
     }
   }
 
-  int32_t iterDepth = bce_->stackDepth;
+  int32_t iterDepth = bce_->bytecodeSection().stackDepth();
 
   // For-of loops have the iterator next method, the iterator itself, and
   // the result.value on the stack.
   // Push an undefined to balance the stack.
   if (!bce_->emit1(JSOP_UNDEFINED)) {
     //              [stack] NEXT ITER UNDEF
     return false;
   }
@@ -106,17 +106,17 @@ bool ForOfEmitter::emitInitialize(const 
 
     // For uncaptured bindings, put them back in TDZ.
     if (!headLexicalEmitterScope_->deadZoneFrameSlots(bce_)) {
       return false;
     }
   }
 
 #ifdef DEBUG
-  loopDepth_ = bce_->stackDepth;
+  loopDepth_ = bce_->bytecodeSection().stackDepth();
 #endif
 
   // Make sure this code is attributed to the "for".
   if (forPos) {
     if (!bce_->updateSourceCoordNotes(*forPos)) {
       return false;
     }
   }
@@ -190,17 +190,17 @@ bool ForOfEmitter::emitInitialize(const 
   state_ = State::Initialize;
 #endif
   return true;
 }
 
 bool ForOfEmitter::emitBody() {
   MOZ_ASSERT(state_ == State::Initialize);
 
-  MOZ_ASSERT(bce_->stackDepth == loopDepth_,
+  MOZ_ASSERT(bce_->bytecodeSection().stackDepth() == loopDepth_,
              "the stack must be balanced around the initializing "
              "operation");
 
   // Remove VALUE from the stack to release it.
   if (!bce_->emit1(JSOP_POP)) {
     //              [stack] NEXT ITER
     return false;
   }
@@ -213,17 +213,17 @@ bool ForOfEmitter::emitBody() {
   state_ = State::Body;
 #endif
   return true;
 }
 
 bool ForOfEmitter::emitEnd(const Maybe<uint32_t>& iteratedPos) {
   MOZ_ASSERT(state_ == State::Body);
 
-  MOZ_ASSERT(bce_->stackDepth == loopDepth_,
+  MOZ_ASSERT(bce_->bytecodeSection().stackDepth() == loopDepth_,
              "the stack must be balanced around the for-of body");
 
   if (!loopInfo_->emitEndCodeNeedingIteratorClose(bce_)) {
     return false;
   }
 
   loopInfo_->setContinueTarget(bce_->bytecodeSection().offset());
 
@@ -239,29 +239,30 @@ bool ForOfEmitter::emitEnd(const Maybe<u
     //              [stack] NEXT ITER UNDEF FALSE
     return false;
   }
   if (!loopInfo_->emitLoopEnd(bce_, JSOP_IFEQ)) {
     //              [stack] NEXT ITER UNDEF
     return false;
   }
 
-  MOZ_ASSERT(bce_->stackDepth == loopDepth_);
+  MOZ_ASSERT(bce_->bytecodeSection().stackDepth() == loopDepth_);
 
   // Let Ion know where the closing jump of this loop is.
   if (!bce_->setSrcNoteOffset(noteIndex_, SrcNote::ForOf::BackJumpOffset,
                               loopInfo_->loopEndOffsetFromEntryJump())) {
     return false;
   }
 
   if (!loopInfo_->patchBreaksAndContinues(bce_)) {
     return false;
   }
 
-  if (!bce_->addTryNote(JSTRY_FOR_OF, bce_->stackDepth, loopInfo_->headOffset(),
+  if (!bce_->addTryNote(JSTRY_FOR_OF, bce_->bytecodeSection().stackDepth(),
+                        loopInfo_->headOffset(),
                         loopInfo_->breakTargetOffset())) {
     return false;
   }
 
   if (!bce_->emitPopN(3)) {
     //              [stack]
     return false;
   }
--- a/js/src/frontend/ForOfLoopControl.cpp
+++ b/js/src/frontend/ForOfLoopControl.cpp
@@ -40,17 +40,17 @@ bool ForOfLoopControl::emitEndCodeNeedin
     //              [stack] ITER ...
     return false;
   }
 
   if (!bce->emit1(JSOP_EXCEPTION)) {
     //              [stack] ITER ... EXCEPTION
     return false;
   }
-  unsigned slotFromTop = bce->stackDepth - iterDepth_;
+  unsigned slotFromTop = bce->bytecodeSection().stackDepth() - iterDepth_;
   if (!bce->emitDupAt(slotFromTop)) {
     //              [stack] ITER ... EXCEPTION ITER
     return false;
   }
 
   // If ITER is undefined, it means the exception is thrown by
   // IteratorClose for non-local jump, and we should't perform
   // IteratorClose again here.
@@ -64,17 +64,18 @@ bool ForOfLoopControl::emitEndCodeNeedin
   }
 
   InternalIfEmitter ifIteratorIsNotClosed(bce);
   if (!ifIteratorIsNotClosed.emitThen()) {
     //              [stack] ITER ... EXCEPTION
     return false;
   }
 
-  MOZ_ASSERT(slotFromTop == unsigned(bce->stackDepth - iterDepth_));
+  MOZ_ASSERT(slotFromTop ==
+             unsigned(bce->bytecodeSection().stackDepth() - iterDepth_));
   if (!bce->emitDupAt(slotFromTop)) {
     //              [stack] ITER ... EXCEPTION ITER
     return false;
   }
   if (!emitIteratorCloseInInnermostScopeWithTryNote(bce,
                                                     CompletionKind::Throw)) {
     return false;  // ITER ... EXCEPTION
   }
--- a/js/src/frontend/IfEmitter.cpp
+++ b/js/src/frontend/IfEmitter.cpp
@@ -36,38 +36,38 @@ bool BranchEmitterBase::emitThenInternal
   }
   if (!bce_->emitJump(JSOP_IFEQ, &jumpAroundThen_)) {
     return false;
   }
 
   // To restore stack depth in else part, save depth of the then part.
 #ifdef DEBUG
   // If DEBUG, this is also necessary to calculate |pushed_|.
-  thenDepth_ = bce_->stackDepth;
+  thenDepth_ = bce_->bytecodeSection().stackDepth();
 #else
   if (type == SRC_COND || type == SRC_IF_ELSE) {
-    thenDepth_ = bce_->stackDepth;
+    thenDepth_ = bce_->bytecodeSection().stackDepth();
   }
 #endif
 
   // Enclose then-branch with TDZCheckCache.
   if (kind_ == Kind::MayContainLexicalAccessInBranch) {
     tdzCache_.emplace(bce_);
   }
 
   return true;
 }
 
 void BranchEmitterBase::calculateOrCheckPushed() {
 #ifdef DEBUG
   if (!calculatedPushed_) {
-    pushed_ = bce_->stackDepth - thenDepth_;
+    pushed_ = bce_->bytecodeSection().stackDepth() - thenDepth_;
     calculatedPushed_ = true;
   } else {
-    MOZ_ASSERT(pushed_ == bce_->stackDepth - thenDepth_);
+    MOZ_ASSERT(pushed_ == bce_->bytecodeSection().stackDepth() - thenDepth_);
   }
 #endif
 }
 
 bool BranchEmitterBase::emitElseInternal() {
   calculateOrCheckPushed();
 
   // The end of TDZCheckCache for then-clause.
@@ -87,17 +87,17 @@ bool BranchEmitterBase::emitElseInternal
   if (!bce_->emitJumpTargetAndPatch(jumpAroundThen_)) {
     return false;
   }
 
   // Clear jumpAroundThen_ offset, to tell emitEnd there was an else part.
   jumpAroundThen_ = JumpList();
 
   // Restore stack depth of the then part.
-  bce_->stackDepth = thenDepth_;
+  bce_->bytecodeSection().setStackDepth(thenDepth_);
 
   // Enclose else-branch with TDZCheckCache.
   if (kind_ == Kind::MayContainLexicalAccessInBranch) {
     tdzCache_.emplace(bce_);
   }
 
   return true;
 }
--- a/js/src/frontend/TryEmitter.cpp
+++ b/js/src/frontend/TryEmitter.cpp
@@ -48,17 +48,17 @@ bool TryEmitter::emitTry() {
 
   // Since an exception can be thrown at any place inside the try block,
   // we need to restore the stack and the scope chain before we transfer
   // the control to the exception handler.
   //
   // For that we store in a try note associated with the catch or
   // finally block the stack depth upon the try entry. The interpreter
   // uses this depth to properly unwind the stack and the scope chain.
-  depth_ = bce_->stackDepth;
+  depth_ = bce_->bytecodeSection().stackDepth();
 
   // Record the try location, then emit the try block.
   if (!bce_->newSrcNote(SRC_TRY, &noteIndex_)) {
     return false;
   }
   if (!bce_->emit1(JSOP_TRY)) {
     return false;
   }
@@ -67,17 +67,17 @@ bool TryEmitter::emitTry() {
 #ifdef DEBUG
   state_ = State::Try;
 #endif
   return true;
 }
 
 bool TryEmitter::emitTryEnd() {
   MOZ_ASSERT(state_ == State::Try);
-  MOZ_ASSERT(depth_ == bce_->stackDepth);
+  MOZ_ASSERT(depth_ == bce_->bytecodeSection().stackDepth());
 
   // GOSUB to finally, if present.
   if (hasFinally() && controlInfo_) {
     if (!bce_->emitGoSub(&controlInfo_->gosubs)) {
       return false;
     }
   }
 
@@ -101,17 +101,17 @@ bool TryEmitter::emitTryEnd() {
 }
 
 bool TryEmitter::emitCatch() {
   MOZ_ASSERT(state_ == State::Try);
   if (!emitTryEnd()) {
     return false;
   }
 
-  MOZ_ASSERT(bce_->stackDepth == depth_);
+  MOZ_ASSERT(bce_->bytecodeSection().stackDepth() == depth_);
 
   if (controlKind_ == ControlKind::Syntactic) {
     // Clear the frame's return value that might have been set by the
     // try block:
     //
     //   eval("try { 1; throw 2 } catch(e) {}"); // undefined, not 1
     if (!bce_->emit1(JSOP_UNDEFINED)) {
       return false;
@@ -134,17 +134,17 @@ bool TryEmitter::emitCatchEnd() {
     return true;
   }
 
   // gosub <finally>, if required.
   if (hasFinally()) {
     if (!bce_->emitGoSub(&controlInfo_->gosubs)) {
       return false;
     }
-    MOZ_ASSERT(bce_->stackDepth == depth_);
+    MOZ_ASSERT(bce_->bytecodeSection().stackDepth() == depth_);
 
     // Jump over the finally block.
     if (!bce_->emitJump(JSOP_GOTO, &catchAndFinallyJump_)) {
       return false;
     }
   }
 
   return true;
@@ -173,17 +173,17 @@ bool TryEmitter::emitFinally(
     }
   } else {
     MOZ_ASSERT(state_ == State::Catch);
     if (!emitCatchEnd()) {
       return false;
     }
   }
 
-  MOZ_ASSERT(bce_->stackDepth == depth_);
+  MOZ_ASSERT(bce_->bytecodeSection().stackDepth() == depth_);
 
   if (!bce_->emitJumpTarget(&finallyStart_)) {
     return false;
   }
 
   if (controlInfo_) {
     // Fix up the gosubs that might have been emitted before non-local
     // jumps to the finally code.
@@ -249,17 +249,17 @@ bool TryEmitter::emitEnd() {
     }
   } else {
     MOZ_ASSERT(state_ == State::Finally);
     if (!emitFinallyEnd()) {
       return false;
     }
   }
 
-  MOZ_ASSERT(bce_->stackDepth == depth_);
+  MOZ_ASSERT(bce_->bytecodeSection().stackDepth() == depth_);
 
   // ReconstructPCStack needs a NOP here to mark the end of the last
   // catch block.
   if (!bce_->emit1(JSOP_NOP)) {
     return false;
   }
 
   // Fix up the end-of-try/catch jumps to come here.
--- a/js/src/frontend/WhileEmitter.cpp
+++ b/js/src/frontend/WhileEmitter.cpp
@@ -95,17 +95,18 @@ bool WhileEmitter::emitCond(const Maybe<
 
 bool WhileEmitter::emitEnd() {
   MOZ_ASSERT(state_ == State::Cond);
 
   if (!loopInfo_->emitLoopEnd(bce_, JSOP_IFNE)) {
     return false;
   }
 
-  if (!bce_->addTryNote(JSTRY_LOOP, bce_->stackDepth, loopInfo_->headOffset(),
+  if (!bce_->addTryNote(JSTRY_LOOP, bce_->bytecodeSection().stackDepth(),
+                        loopInfo_->headOffset(),
                         loopInfo_->breakTargetOffset())) {
     return false;
   }
 
   if (!bce_->setSrcNoteOffset(noteIndex_, SrcNote::While::BackJumpOffset,
                               loopInfo_->loopEndOffsetFromEntryJump())) {
     return false;
   }
--- a/js/src/vm/JSScript.cpp
+++ b/js/src/vm/JSScript.cpp
@@ -3564,17 +3564,18 @@ bool JSScript::fullyInitFromEmitter(JSCo
   auto scriptDataGuard =
       mozilla::MakeScopeExit([&] { script->freeScriptData(); });
 
   /* The counts of indexed things must be checked during code generation. */
   MOZ_ASSERT(bce->atomIndices->count() <= INDEX_LIMIT);
   MOZ_ASSERT(bce->objectList.length <= INDEX_LIMIT);
 
   uint64_t nslots =
-      bce->maxFixedSlots + static_cast<uint64_t>(bce->maxStackDepth);
+      bce->maxFixedSlots +
+      static_cast<uint64_t>(bce->bytecodeSection().maxStackDepth());
   if (nslots > UINT32_MAX) {
     bce->reportError(nullptr, JSMSG_NEED_DIET, js_script_str);
     return false;
   }
 
   // Initialize POD fields
   script->lineno_ = bce->firstLine;
   script->mainOffset_ = bce->mainOffset();