Bug 1535994 - Part 1: Add BytecodeSection class with BytecodeVector. r=jorendorff
☠☠ backed out by 7fb3acf38591 ☠ ☠
authorTooru Fujisawa <arai_a@mac.com>
Wed, 10 Apr 2019 08:25:10 +0000
changeset 468758 384cdd1ee833dfa72b957072651c1bde10dacf7c
parent 468757 caff7c30502713c949800eb950d836e3f55e5a65
child 468759 b77efa8567a299f90c926f5623a6f07325fcfa32
push id112755
push userdvarga@mozilla.com
push dateWed, 10 Apr 2019 22:06:41 +0000
treeherdermozilla-inbound@606f85641d0b [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 1: Add BytecodeSection class with BytecodeVector. r=jorendorff Differential Revision: https://phabricator.services.mozilla.com/D25731
js/src/frontend/BytecodeControlStructures.cpp
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/BytecodeEmitter.h
js/src/frontend/CForEmitter.cpp
js/src/frontend/EmitterScope.cpp
js/src/frontend/ForInEmitter.cpp
js/src/frontend/ForOfEmitter.cpp
js/src/frontend/ForOfLoopControl.cpp
js/src/frontend/LabelEmitter.cpp
js/src/frontend/ObjectEmitter.cpp
js/src/frontend/SwitchEmitter.cpp
js/src/frontend/TryEmitter.cpp
js/src/vm/JSScript.cpp
--- a/js/src/frontend/BytecodeControlStructures.cpp
+++ b/js/src/frontend/BytecodeControlStructures.cpp
@@ -104,43 +104,44 @@ bool LoopControl::emitEntryJump(Bytecode
 bool LoopControl::emitLoopHead(BytecodeEmitter* bce,
                                const Maybe<uint32_t>& nextPos) {
   if (nextPos) {
     if (!bce->updateSourceCoordNotes(*nextPos)) {
       return false;
     }
   }
 
-  head_ = {bce->offset()};
+  head_ = {bce->bytecodeSection().offset()};
   ptrdiff_t off;
   if (!bce->emitJumpTargetOp(JSOP_LOOPHEAD, &off)) {
     return false;
   }
 
   return true;
 }
 
 bool LoopControl::emitLoopEntry(BytecodeEmitter* bce,
                                 const Maybe<uint32_t>& nextPos) {
   if (nextPos) {
     if (!bce->updateSourceCoordNotes(*nextPos)) {
       return false;
     }
   }
 
-  JumpTarget entry = {bce->offset()};
+  JumpTarget entry = {bce->bytecodeSection().offset()};
   bce->patchJumpsToTarget(entryJump_, entry);
 
   MOZ_ASSERT(loopDepth_ > 0);
 
   ptrdiff_t off;
   if (!bce->emitJumpTargetOp(JSOP_LOOPENTRY, &off)) {
     return false;
   }
-  SetLoopEntryDepthHintAndFlags(bce->code(off), loopDepth_, canIonOsr_);
+  SetLoopEntryDepthHintAndFlags(bce->bytecodeSection().code(off), loopDepth_,
+                                canIonOsr_);
 
   return true;
 }
 
 bool LoopControl::emitLoopEnd(BytecodeEmitter* bce, JSOp op) {
   JumpList beq;
   if (!bce->emitBackwardJump(op, head_, &beq, &breakTarget_)) {
     return false;
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -86,26 +86,28 @@ static bool ParseNodeRequiresSpecialLine
   // handling to avoid strange stepping behavior.
   // Functions usually shouldn't have location information (bug 1431202).
 
   ParseNodeKind kind = pn->getKind();
   return kind == ParseNodeKind::WhileStmt || kind == ParseNodeKind::ForStmt ||
          kind == ParseNodeKind::Function;
 }
 
+BytecodeEmitter::BytecodeSection::BytecodeSection(JSContext* cx) : code_(cx) {}
+
 BytecodeEmitter::BytecodeEmitter(
     BytecodeEmitter* parent, SharedContext* sc, HandleScript script,
     Handle<LazyScript*> lazyScript, uint32_t lineNum, EmitterMode emitterMode,
     FieldInitializers fieldInitializers /* = FieldInitializers::Invalid() */)
     : sc(sc),
       cx(sc->cx_),
       parent(parent),
       script(cx, script),
       lazyScript(cx, lazyScript),
-      code_(cx),
+      bytecodeSection_(cx),
       notes_(cx),
       currentLine_(lineNum),
       fieldInitializers_(fieldInitializers),
       atomIndices(cx->frontendCollectionPool()),
       firstLine(lineNum),
       numberList(cx),
       scopeList(cx),
       tryNoteList(cx),
@@ -189,17 +191,17 @@ bool BytecodeEmitter::markStepBreakpoint
 
   if (!newSrcNote(SRC_BREAKPOINT)) {
     return false;
   }
 
   // We track the location of the most recent separator for use in
   // markSimpleBreakpoint. Note that this means that the position must already
   // be set before markStepBreakpoint is called.
-  lastSeparatorOffet_ = code().length();
+  lastSeparatorOffet_ = bytecodeSection().code().length();
   lastSeparatorLine_ = currentLine_;
   lastSeparatorColumn_ = lastColumn_;
 
   return true;
 }
 
 bool BytecodeEmitter::markSimpleBreakpoint() {
   if (inPrologue()) {
@@ -218,19 +220,19 @@ bool BytecodeEmitter::markSimpleBreakpoi
       return false;
     }
   }
 
   return true;
 }
 
 bool BytecodeEmitter::emitCheck(JSOp op, ptrdiff_t delta, ptrdiff_t* offset) {
-  *offset = code().length();
-
-  if (!code().growByUninitialized(delta)) {
+  *offset = bytecodeSection().code().length();
+
+  if (!bytecodeSection().code().growByUninitialized(delta)) {
     ReportOutOfMemory(cx);
     return false;
   }
 
   // If op is JOF_TYPESET (see the type barriers comment in TypeInference.h),
   // reserve a type set to store its result.
   if (CodeSpec[op].format & JOF_TYPESET) {
     if (typesetCount < JSScript::MaxBytecodeTypeSets) {
@@ -241,17 +243,17 @@ bool BytecodeEmitter::emitCheck(JSOp op,
   if (BytecodeOpHasIC(op)) {
     numICEntries++;
   }
 
   return true;
 }
 
 void BytecodeEmitter::updateDepth(ptrdiff_t target) {
-  jsbytecode* pc = code(target);
+  jsbytecode* pc = bytecodeSection().code(target);
 
   int nuses = StackUses(pc);
   int ndefs = StackDefs(pc);
 
   stackDepth -= nuses;
   MOZ_ASSERT(stackDepth >= 0);
   stackDepth += ndefs;
 
@@ -275,31 +277,31 @@ bool BytecodeEmitter::checkStrictOrSlopp
 bool BytecodeEmitter::emit1(JSOp op) {
   MOZ_ASSERT(checkStrictOrSloppy(op));
 
   ptrdiff_t offset;
   if (!emitCheck(op, 1, &offset)) {
     return false;
   }
 
-  jsbytecode* code = this->code(offset);
+  jsbytecode* code = bytecodeSection().code(offset);
   code[0] = jsbytecode(op);
   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 = this->code(offset);
+  jsbytecode* code = bytecodeSection().code(offset);
   code[0] = jsbytecode(op);
   code[1] = jsbytecode(op1);
   updateDepth(offset);
   return true;
 }
 
 bool BytecodeEmitter::emit3(JSOp op, jsbytecode op1, jsbytecode op2) {
   MOZ_ASSERT(checkStrictOrSloppy(op));
@@ -308,34 +310,34 @@ bool BytecodeEmitter::emit3(JSOp op, jsb
   MOZ_ASSERT(!IsArgOp(op));
   MOZ_ASSERT(!IsLocalOp(op));
 
   ptrdiff_t offset;
   if (!emitCheck(op, 3, &offset)) {
     return false;
   }
 
-  jsbytecode* code = this->code(offset);
+  jsbytecode* code = bytecodeSection().code(offset);
   code[0] = jsbytecode(op);
   code[1] = op1;
   code[2] = op2;
   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;
   if (!emitCheck(op, length, &off)) {
     return false;
   }
 
-  jsbytecode* code = this->code(off);
+  jsbytecode* code = bytecodeSection().code(off);
   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) {
@@ -356,22 +358,22 @@ bool BytecodeEmitter::emitJumpTargetOp(J
     reportError(nullptr, JSMSG_NEED_DIET, js_script_str);
     return false;
   }
 
   if (!emitN(op, CodeSpec[op].length - 1, off)) {
     return false;
   }
 
-  SET_ICINDEX(code(*off), numEntries);
+  SET_ICINDEX(bytecodeSection().code(*off), numEntries);
   return true;
 }
 
 bool BytecodeEmitter::emitJumpTarget(JumpTarget* target) {
-  ptrdiff_t off = offset();
+  ptrdiff_t off = bytecodeSection().offset();
 
   // Alias consecutive jump targets.
   if (off == lastTarget.offset + ptrdiff_t(JSOP_JUMPTARGET_LENGTH)) {
     target->offset = lastTarget.offset;
     return true;
   }
 
   target->offset = off;
@@ -382,20 +384,20 @@ bool BytecodeEmitter::emitJumpTarget(Jum
 }
 
 bool BytecodeEmitter::emitJumpNoFallthrough(JSOp op, JumpList* jump) {
   ptrdiff_t offset;
   if (!emitCheck(op, 5, &offset)) {
     return false;
   }
 
-  jsbytecode* code = this->code(offset);
+  jsbytecode* code = bytecodeSection().code(offset);
   code[0] = jsbytecode(op);
   MOZ_ASSERT(-1 <= jump->offset && jump->offset < offset);
-  jump->push(this->code(0), offset);
+  jump->push(bytecodeSection().code(0), offset);
   updateDepth(offset);
   return true;
 }
 
 bool BytecodeEmitter::emitJump(JSOp op, JumpList* jump) {
   if (!emitJumpNoFallthrough(op, jump)) {
     return false;
   }
@@ -420,21 +422,22 @@ bool BytecodeEmitter::emitBackwardJump(J
   // target for break statements.
   if (!emitJumpTarget(fallthrough)) {
     return false;
   }
   return true;
 }
 
 void BytecodeEmitter::patchJumpsToTarget(JumpList jump, JumpTarget target) {
-  MOZ_ASSERT(-1 <= jump.offset && jump.offset <= offset());
-  MOZ_ASSERT(0 <= target.offset && target.offset <= offset());
-  MOZ_ASSERT_IF(jump.offset != -1 && target.offset + 4 <= offset(),
-                BytecodeIsJumpTarget(JSOp(*code(target.offset))));
-  jump.patchAll(code(0), target);
+  MOZ_ASSERT(-1 <= jump.offset && jump.offset <= bytecodeSection().offset());
+  MOZ_ASSERT(0 <= target.offset && target.offset <= bytecodeSection().offset());
+  MOZ_ASSERT_IF(
+      jump.offset != -1 && target.offset + 4 <= bytecodeSection().offset(),
+      BytecodeIsJumpTarget(JSOp(*bytecodeSection().code(target.offset))));
+  jump.patchAll(bytecodeSection().code(0), target);
 }
 
 bool BytecodeEmitter::emitJumpTargetAndPatch(JumpList jump) {
   if (jump.offset == -1) {
     return true;
   }
   JumpTarget target;
   if (!emitJumpTarget(&target)) {
@@ -470,17 +473,17 @@ bool BytecodeEmitter::emitDupAt(unsigned
     return false;
   }
 
   ptrdiff_t off;
   if (!emitN(JSOP_DUPAT, 3, &off)) {
     return false;
   }
 
-  jsbytecode* pc = code(off);
+  jsbytecode* pc = bytecodeSection().code(off);
   SET_UINT24(pc, slotFromTop);
   return true;
 }
 
 bool BytecodeEmitter::emitPopN(unsigned n) {
   MOZ_ASSERT(n != 0);
 
   if (n == 1) {
@@ -582,17 +585,18 @@ bool BytecodeEmitter::updateSourceCoordN
     lastColumn_ = columnIndex;
     updateSeparatorPosition();
   }
   return true;
 }
 
 /* Updates the last separator position, if present */
 void BytecodeEmitter::updateSeparatorPosition() {
-  if (!inPrologue() && lastSeparatorOffet_ == code().length()) {
+  if (!inPrologue() &&
+      lastSeparatorOffet_ == bytecodeSection().code().length()) {
     lastSeparatorLine_ = currentLine_;
     lastSeparatorColumn_ = lastColumn_;
   }
 }
 
 Maybe<uint32_t> BytecodeEmitter::getOffsetForLoop(ParseNode* nextpn) {
   if (!nextpn) {
     return Nothing();
@@ -621,17 +625,17 @@ bool BytecodeEmitter::emitUint16Operand(
   return true;
 }
 
 bool BytecodeEmitter::emitUint32Operand(JSOp op, uint32_t operand) {
   ptrdiff_t off;
   if (!emitN(op, 4, &off)) {
     return false;
   }
-  SET_UINT32(code(off), operand);
+  SET_UINT32(bytecodeSection().code(off), operand);
   return true;
 }
 
 namespace {
 
 class NonLocalExitControl {
  public:
   enum Kind {
@@ -666,17 +670,17 @@ class NonLocalExitControl {
         savedScopeNoteIndex_(bce->scopeNoteList.length()),
         savedDepth_(bce->stackDepth),
         openScopeNoteIndex_(bce->innermostEmitterScope()->noteIndex()),
         kind_(kind) {}
 
   ~NonLocalExitControl() {
     for (uint32_t n = savedScopeNoteIndex_; n < bce_->scopeNoteList.length();
          n++) {
-      bce_->scopeNoteList.recordEnd(n, bce_->offset());
+      bce_->scopeNoteList.recordEnd(n, bce_->bytecodeSection().offset());
     }
     bce_->stackDepth = savedDepth_;
   }
 
   MOZ_MUST_USE bool prepareForNonLocalJump(NestableControl* target);
 
   MOZ_MUST_USE bool prepareForNonLocalJumpToOutermost() {
     return prepareForNonLocalJump(nullptr);
@@ -690,17 +694,18 @@ bool NonLocalExitControl::leaveScope(Emi
 
   // As we pop each scope due to the non-local jump, emit notes that
   // record the extent of the enclosing scope. These notes will have
   // their ends recorded in ~NonLocalExitControl().
   uint32_t enclosingScopeIndex = ScopeNote::NoScopeIndex;
   if (es->enclosingInFrame()) {
     enclosingScopeIndex = es->enclosingInFrame()->index();
   }
-  if (!bce_->scopeNoteList.append(enclosingScopeIndex, bce_->offset(),
+  if (!bce_->scopeNoteList.append(enclosingScopeIndex,
+                                  bce_->bytecodeSection().offset(),
                                   openScopeNoteIndex_)) {
     return false;
   }
   openScopeNoteIndex_ = bce_->scopeNoteList.length() - 1;
 
   return true;
 }
 
@@ -833,17 +838,17 @@ bool NonLocalExitControl::prepareForNonL
       target ? target->emitterScope() : bce_->varEmitterScope;
   for (; es != targetEmitterScope; es = es->enclosingInFrame()) {
     if (!leaveScope(es)) {
       return false;
     }
   }
 
   // Close FOR_OF_ITERCLOSE trynotes.
-  ptrdiff_t end = bce_->offset();
+  ptrdiff_t end = bce_->bytecodeSection().offset();
   for (ptrdiff_t start : forOfIterCloseScopeStarts) {
     if (!bce_->addTryNote(JSTRY_FOR_OF_ITERCLOSE, 0, start, end)) {
       return false;
     }
   }
 
   return true;
 }
@@ -879,17 +884,17 @@ bool BytecodeEmitter::emitIndex32(JSOp o
   const size_t len = 1 + UINT32_INDEX_LEN;
   MOZ_ASSERT(len == size_t(CodeSpec[op].length));
 
   ptrdiff_t offset;
   if (!emitCheck(op, len, &offset)) {
     return false;
   }
 
-  jsbytecode* code = this->code(offset);
+  jsbytecode* code = bytecodeSection().code(offset);
   code[0] = jsbytecode(op);
   SET_UINT32_INDEX(code, index);
   updateDepth(offset);
   return true;
 }
 
 bool BytecodeEmitter::emitIndexOp(JSOp op, uint32_t index) {
   MOZ_ASSERT(checkStrictOrSloppy(op));
@@ -897,17 +902,17 @@ bool BytecodeEmitter::emitIndexOp(JSOp o
   const size_t len = CodeSpec[op].length;
   MOZ_ASSERT(len >= 1 + UINT32_INDEX_LEN);
 
   ptrdiff_t offset;
   if (!emitCheck(op, len, &offset)) {
     return false;
   }
 
-  jsbytecode* code = this->code(offset);
+  jsbytecode* code = bytecodeSection().code(offset);
   code[0] = jsbytecode(op);
   SET_UINT32_INDEX(code, index);
   updateDepth(offset);
   return true;
 }
 
 bool BytecodeEmitter::emitAtomOp(JSAtom* atom, JSOp op) {
   MOZ_ASSERT(atom);
@@ -969,43 +974,43 @@ bool BytecodeEmitter::emitLocalOp(JSOp o
   MOZ_ASSERT(JOF_OPTYPE(op) != JOF_ENVCOORD);
   MOZ_ASSERT(IsLocalOp(op));
 
   ptrdiff_t off;
   if (!emitN(op, LOCALNO_LEN, &off)) {
     return false;
   }
 
-  SET_LOCALNO(code(off), slot);
+  SET_LOCALNO(bytecodeSection().code(off), slot);
   return true;
 }
 
 bool BytecodeEmitter::emitArgOp(JSOp op, uint16_t slot) {
   MOZ_ASSERT(IsArgOp(op));
   ptrdiff_t off;
   if (!emitN(op, ARGNO_LEN, &off)) {
     return false;
   }
 
-  SET_ARGNO(code(off), slot);
+  SET_ARGNO(bytecodeSection().code(off), slot);
   return true;
 }
 
 bool BytecodeEmitter::emitEnvCoordOp(JSOp op, EnvironmentCoordinate ec) {
   MOZ_ASSERT(JOF_OPTYPE(op) == JOF_ENVCOORD);
 
   unsigned n = ENVCOORD_HOPS_LEN + ENVCOORD_SLOT_LEN;
   MOZ_ASSERT(int(n) + 1 /* op */ == CodeSpec[op].length);
 
   ptrdiff_t off;
   if (!emitN(op, n, &off)) {
     return false;
   }
 
-  jsbytecode* pc = code(off);
+  jsbytecode* pc = bytecodeSection().code(off);
   SET_ENVCOORD_HOPS(pc, ec.hops());
   pc += ENVCOORD_HOPS_LEN;
   SET_ENVCOORD_SLOT(pc, ec.slot());
   pc += ENVCOORD_SLOT_LEN;
   return true;
 }
 
 JSOp BytecodeEmitter::strictifySetNameOp(JSOp op) {
@@ -1675,17 +1680,17 @@ bool BytecodeEmitter::reportExtraWarning
 
 bool BytecodeEmitter::emitNewInit() {
   const size_t len = 1 + UINT32_INDEX_LEN;
   ptrdiff_t offset;
   if (!emitCheck(JSOP_NEWINIT, len, &offset)) {
     return false;
   }
 
-  jsbytecode* code = this->code(offset);
+  jsbytecode* code = bytecodeSection().code(offset);
   code[0] = JSOP_NEWINIT;
   code[1] = 0;
   code[2] = 0;
   code[3] = 0;
   code[4] = 0;
   updateDepth(offset);
   return true;
 }
@@ -2042,23 +2047,23 @@ bool BytecodeEmitter::emitNumberOp(doubl
       if (!emitUint16Operand(JSOP_UINT16, u)) {
         return false;
       }
     } else if (u < JS_BIT(24)) {
       ptrdiff_t off;
       if (!emitN(JSOP_UINT24, 3, &off)) {
         return false;
       }
-      SET_UINT24(code(off), u);
+      SET_UINT24(bytecodeSection().code(off), u);
     } else {
       ptrdiff_t off;
       if (!emitN(JSOP_INT32, 4, &off)) {
         return false;
       }
-      SET_INT32(code(off), ival);
+      SET_INT32(bytecodeSection().code(off), ival);
     }
     return true;
   }
 
   return emitDouble(dval);
 }
 
 /*
@@ -2292,21 +2297,21 @@ bool BytecodeEmitter::emitYieldOp(JSOp o
     return false;
   }
 
   if (op == JSOP_INITIALYIELD || op == JSOP_YIELD) {
     numYields++;
   }
 
   uint32_t resumeIndex;
-  if (!allocateResumeIndex(offset(), &resumeIndex)) {
-    return false;
-  }
-
-  SET_RESUMEINDEX(code(off), resumeIndex);
+  if (!allocateResumeIndex(bytecodeSection().offset(), &resumeIndex)) {
+    return false;
+  }
+
+  SET_RESUMEINDEX(bytecodeSection().code(off), resumeIndex);
 
   return emit1(JSOP_DEBUGAFTERYIELD);
 }
 
 bool BytecodeEmitter::emitSetThis(BinaryNode* setThisNode) {
   // ParseNodeKind::SetThis is used to update |this| after a super() call
   // in a derived class constructor.
 
@@ -3087,21 +3092,21 @@ bool BytecodeEmitter::wrapWithDestructur
   // 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;
   }
 
-  ptrdiff_t start = offset();
+  ptrdiff_t start = bytecodeSection().offset();
   if (!emitter(this)) {
     return false;
   }
-  ptrdiff_t end = offset();
+  ptrdiff_t end = bytecodeSection().offset();
   if (start != end) {
     return addTryNote(JSTRY_DESTRUCTURING, iterDepth, start, end);
   }
   return true;
 }
 
 bool BytecodeEmitter::emitDefault(ParseNode* defaultExpr, ParseNode* pattern) {
   //                [stack] VALUE
@@ -3810,17 +3815,17 @@ bool BytecodeEmitter::emitDestructuringO
 
   return true;
 }
 
 bool BytecodeEmitter::emitDestructuringObjRestExclusionSet(ListNode* pattern) {
   MOZ_ASSERT(pattern->isKind(ParseNodeKind::ObjectExpr));
   MOZ_ASSERT(pattern->last()->isKind(ParseNodeKind::Spread));
 
-  ptrdiff_t offset = this->offset();
+  ptrdiff_t offset = bytecodeSection().offset();
   if (!emitNewInit()) {
     return false;
   }
 
   // Try to construct the shape of the object as we go, so we can emit a
   // JSOP_NEWOBJECT with the final shape instead.
   // In the case of computed property names and indices, we cannot fix the
   // shape at bytecode compile time. When the shape cannot be determined,
@@ -4685,21 +4690,21 @@ MOZ_MUST_USE bool BytecodeEmitter::emitG
     return false;
   }
 
   if (!emitJump(JSOP_GOSUB, jump)) {
     return false;
   }
 
   uint32_t resumeIndex;
-  if (!allocateResumeIndex(offset(), &resumeIndex)) {
-    return false;
-  }
-
-  SET_RESUMEINDEX(code(off), resumeIndex);
+  if (!allocateResumeIndex(bytecodeSection().offset(), &resumeIndex)) {
+    return false;
+  }
+
+  SET_RESUMEINDEX(bytecodeSection().code(off), resumeIndex);
   return true;
 }
 
 bool BytecodeEmitter::emitIf(TernaryNode* ifNode) {
   IfEmitter ifThenElse(this);
 
   if (!ifThenElse.emitIf(Some(ifNode->kid1()->pn_pos.begin))) {
     return false;
@@ -5962,17 +5967,17 @@ bool BytecodeEmitter::emitReturn(UnaryNo
    * We can't simply transfer control flow to our caller in that case,
    * because we must gosub to those finally clauses from inner to outer,
    * with the correct stack pointer (i.e., after popping any with,
    * for/in, etc., slots nested inside the finally's try).
    *
    * In this case we mutate JSOP_RETURN into JSOP_SETRVAL and add an
    * extra JSOP_RETRVAL after the fixups.
    */
-  ptrdiff_t top = offset();
+  ptrdiff_t top = bytecodeSection().offset();
 
   bool needsFinalYield =
       sc->isFunctionBox() && sc->asFunctionBox()->needsFinalYield();
   bool isDerivedClassConstructor =
       sc->isFunctionBox() && sc->asFunctionBox()->isDerivedClassConstructor();
 
   if (!emit1((needsFinalYield || isDerivedClassConstructor) ? JSOP_SETRVAL
                                                             : JSOP_RETURN)) {
@@ -6023,22 +6028,23 @@ bool BytecodeEmitter::emitReturn(UnaryNo
 
     if (!emitGetNameAtLocation(cx->names().dotGenerator, loc)) {
       return false;
     }
     if (!emitYieldOp(JSOP_FINALYIELDRVAL)) {
       return false;
     }
   } else if (isDerivedClassConstructor) {
-    MOZ_ASSERT(code()[top] == JSOP_SETRVAL);
+    MOZ_ASSERT(bytecodeSection().code()[top] == JSOP_SETRVAL);
     if (!emit1(JSOP_RETRVAL)) {
       return false;
     }
-  } else if (top + static_cast<ptrdiff_t>(JSOP_RETURN_LENGTH) != offset()) {
-    code()[top] = JSOP_SETRVAL;
+  } else if (top + static_cast<ptrdiff_t>(JSOP_RETURN_LENGTH) !=
+             bytecodeSection().offset()) {
+    bytecodeSection().code()[top] = JSOP_SETRVAL;
     if (!emit1(JSOP_RETRVAL)) {
       return false;
     }
   }
 
   return true;
 }
 
@@ -6702,17 +6708,17 @@ bool BytecodeEmitter::emitExpressionStat
     /*
      * Don't eliminate apparently useless expressions if they are labeled
      * expression statements. The startOffset() test catches the case
      * where we are nesting in emitTree for a labeled compound statement.
      */
     if (innermostNestableControl &&
         innermostNestableControl->is<LabelControl>() &&
         innermostNestableControl->as<LabelControl>().startOffset() >=
-            offset()) {
+            bytecodeSection().offset()) {
       useful = true;
     }
   }
 
   if (useful) {
     ValueUsage valueUsage =
         wantval ? ValueUsage::WantValue : ValueUsage::IgnoreValue;
     ExpressionStatementEmitter ese(this, valueUsage);
@@ -8178,17 +8184,17 @@ bool BytecodeEmitter::replaceNewInitWith
     return false;
   }
 
   static_assert(
       JSOP_NEWINIT_LENGTH == JSOP_NEWOBJECT_LENGTH,
       "newinit and newobject must have equal length to edit in-place");
 
   uint32_t index = objectList.add(objbox);
-  jsbytecode* code = this->code(offset);
+  jsbytecode* code = bytecodeSection().code(offset);
 
   MOZ_ASSERT(code[0] == JSOP_NEWINIT);
   code[0] = JSOP_NEWOBJECT;
   SET_UINT32(code, index);
 
   return true;
 }
 
@@ -9343,17 +9349,17 @@ bool BytecodeEmitter::newSrcNote(SrcNote
   if (!AllocSrcNote(cx, notes, &index)) {
     return false;
   }
 
   /*
    * Compute delta from the last annotated bytecode's offset.  If it's too
    * big to fit in sn, allocate one or more xdelta notes and reset sn.
    */
-  ptrdiff_t offset = this->offset();
+  ptrdiff_t offset = bytecodeSection().offset();
   ptrdiff_t delta = offset - lastNoteOffset();
   lastNoteOffset_ = offset;
   if (delta >= SN_DELTA_LIMIT) {
     do {
       ptrdiff_t xdelta = Min(delta, SN_XDELTA_MASK);
       SN_MAKE_XDELTA(&notes[index], xdelta);
       delta -= xdelta;
       if (!AllocSrcNote(cx, notes, &index)) {
--- a/js/src/frontend/BytecodeEmitter.h
+++ b/js/src/frontend/BytecodeEmitter.h
@@ -119,17 +119,42 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
 
   // The JSScript we're ultimately producing.
   Rooted<JSScript*> script;
 
   // The lazy script if mode is LazyFunction, nullptr otherwise.
   Rooted<LazyScript*> lazyScript;
 
  private:
-  BytecodeVector code_;  /* bytecode */
+  // Bytecode and all data directly associated with specific opcode/index inside
+  // bytecode is stored in this class.
+  class BytecodeSection {
+   public:
+    explicit BytecodeSection(JSContext* cx);
+
+    BytecodeVector& code() { return code_; }
+    const BytecodeVector& code() const { return code_; }
+
+    jsbytecode* code(ptrdiff_t offset) { return code_.begin() + offset; }
+    ptrdiff_t offset() const { return code_.end() - code_.begin(); }
+
+   private:
+    // ---- Bytecode ----
+
+    // Bytecode.
+    BytecodeVector code_;
+  };
+
+  BytecodeSection bytecodeSection_;
+
+ public:
+  BytecodeSection& bytecodeSection() { return bytecodeSection_; }
+  const BytecodeSection& bytecodeSection() const { return bytecodeSection_; }
+
+ private:
   SrcNotesVector notes_; /* source notes, see below */
 
   // Code offset for last source note
   ptrdiff_t lastNoteOffset_ = 0;
 
   // Line number for srcnotes.
   //
   // WARNING: If this becomes out of sync with already-emitted srcnotes,
@@ -395,29 +420,23 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
 
   bool needsImplicitThis();
 
   MOZ_MUST_USE bool emitThisEnvironmentCallee();
   MOZ_MUST_USE bool emitSuperBase();
 
   void tellDebuggerAboutCompiledScript(JSContext* cx);
 
-  BytecodeVector& code() { return code_; }
-  const BytecodeVector& code() const { return code_; }
-
-  jsbytecode* code(ptrdiff_t offset) { return code_.begin() + offset; }
-  ptrdiff_t offset() const { return code_.end() - code_.begin(); }
-
   uint32_t mainOffset() const { return *mainOffset_; }
 
   bool inPrologue() const { return mainOffset_.isNothing(); }
 
   void switchToMain() {
     MOZ_ASSERT(inPrologue());
-    mainOffset_.emplace(code_.length());
+    mainOffset_.emplace(bytecodeSection().code().length());
   }
 
   SrcNotesVector& notes() {
     // Prologue shouldn't have source notes.
     MOZ_ASSERT(!inPrologue());
     return notes_;
   }
   ptrdiff_t lastNoteOffset() const { return lastNoteOffset_; }
@@ -425,25 +444,27 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
 
   void setCurrentLine(uint32_t line) {
     currentLine_ = line;
     lastColumn_ = 0;
   }
 
   // Check if the last emitted opcode is a jump target.
   bool lastOpcodeIsJumpTarget() const {
-    return offset() - lastTarget.offset == ptrdiff_t(JSOP_JUMPTARGET_LENGTH);
+    return bytecodeSection().offset() - lastTarget.offset ==
+           ptrdiff_t(JSOP_JUMPTARGET_LENGTH);
   }
 
   // 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();
+    return lastOpcodeIsJumpTarget() ? lastTarget.offset
+                                    : bytecodeSection().offset();
   }
 
   void setFunctionBodyEndPos(uint32_t pos) {
     functionBodyEndPos = mozilla::Some(pos);
   }
 
   void setScriptStartOffsetIfUnset(uint32_t pos) {
     if (scriptStartOffset.isNothing()) {
--- a/js/src/frontend/CForEmitter.cpp
+++ b/js/src/frontend/CForEmitter.cpp
@@ -70,17 +70,17 @@ bool CForEmitter::emitBody(Cond cond, co
   if (!bce_->newSrcNote(SRC_FOR, &noteIndex_)) {
     return false;
   }
   if (!bce_->emit1(JSOP_NOP)) {
     //              [stack]
     return false;
   }
 
-  biasedTop_ = bce_->offset();
+  biasedTop_ = bce_->bytecodeSection().offset();
 
   if (cond_ == Cond::Present) {
     // Goto the loop condition, which branches back to iterate.
     if (!loopInfo_->emitEntryJump(bce_)) {
       return false;
     }
   }
 
@@ -171,17 +171,17 @@ bool CForEmitter::emitCond(const Maybe<u
       }
     }
   }
 
   if (update_ == Update::Present) {
     tdzCache_.reset();
   }
 
-  condOffset_ = bce_->offset();
+  condOffset_ = bce_->bytecodeSection().offset();
 
   if (cond_ == Cond::Present) {
     if (!loopInfo_->emitLoopEntry(bce_, condPos)) {
       //            [stack]
       return false;
     }
   } else if (update_ == Update::Missing) {
     // If there is no condition clause and no update clause, mark
--- a/js/src/frontend/EmitterScope.cpp
+++ b/js/src/frontend/EmitterScope.cpp
@@ -354,17 +354,17 @@ bool EmitterScope::internBodyScope(Bytec
   bce->bodyScopeIndex = bce->scopeList.length();
   return internScope(bce, createScope);
 }
 
 bool EmitterScope::appendScopeNote(BytecodeEmitter* bce) {
   MOZ_ASSERT(ScopeKindIsInBody(scope(bce)->kind()) && enclosingInFrame(),
              "Scope notes are not needed for body-level scopes.");
   noteIndex_ = bce->scopeNoteList.length();
-  return bce->scopeNoteList.append(index(), bce->offset(),
+  return bce->scopeNoteList.append(index(), bce->bytecodeSection().offset(),
                                    enclosingInFrame()
                                        ? enclosingInFrame()->noteIndex()
                                        : ScopeNote::NoScopeNoteIndex);
 }
 
 bool EmitterScope::deadZoneFrameSlotRange(BytecodeEmitter* bce,
                                           uint32_t slotStart,
                                           uint32_t slotEnd) const {
@@ -1052,18 +1052,19 @@ bool EmitterScope::leave(BytecodeEmitter
 
   // Finish up the scope if we are leaving it in LIFO fashion.
   if (!nonLocal) {
     // Popping scopes due to non-local jumps generate additional scope
     // notes. See NonLocalExitControl::prepareForNonLocalJump.
     if (ScopeKindIsInBody(kind)) {
       // The extra function var scope is never popped once it's pushed,
       // so its scope note extends until the end of any possible code.
-      uint32_t offset =
-          kind == ScopeKind::FunctionBodyVar ? UINT32_MAX : bce->offset();
+      uint32_t offset = kind == ScopeKind::FunctionBodyVar
+                            ? UINT32_MAX
+                            : bce->bytecodeSection().offset();
       bce->scopeNoteList.recordEnd(noteIndex_, offset);
     }
   }
 
   return true;
 }
 
 Scope* EmitterScope::scope(const BytecodeEmitter* bce) const {
--- a/js/src/frontend/ForInEmitter.cpp
+++ b/js/src/frontend/ForInEmitter.cpp
@@ -119,17 +119,17 @@ bool ForInEmitter::emitBody() {
   state_ = State::Body;
 #endif
   return true;
 }
 
 bool ForInEmitter::emitEnd(const Maybe<uint32_t>& forPos) {
   MOZ_ASSERT(state_ == State::Body);
 
-  loopInfo_->setContinueTarget(bce_->offset());
+  loopInfo_->setContinueTarget(bce_->bytecodeSection().offset());
 
   if (forPos) {
     // Make sure this code is attributed to the "for".
     if (!bce_->updateSourceCoordNotes(*forPos)) {
       return false;
     }
   }
 
@@ -167,17 +167,17 @@ 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(),
-                        bce_->offset())) {
+                        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
@@ -220,17 +220,17 @@ bool ForOfEmitter::emitEnd(const Maybe<u
 
   MOZ_ASSERT(bce_->stackDepth == loopDepth_,
              "the stack must be balanced around the for-of body");
 
   if (!loopInfo_->emitEndCodeNeedingIteratorClose(bce_)) {
     return false;
   }
 
-  loopInfo_->setContinueTarget(bce_->offset());
+  loopInfo_->setContinueTarget(bce_->bytecodeSection().offset());
 
   // We use the iterated value's position to attribute JSOP_LOOPENTRY,
   // which corresponds to the iteration protocol.
   // This is a bit misleading for 2nd and later iterations and might need
   // some fix (bug 1482003).
   if (!loopInfo_->emitLoopEntry(bce_, iteratedPos)) {
     return false;
   }
--- a/js/src/frontend/ForOfLoopControl.cpp
+++ b/js/src/frontend/ForOfLoopControl.cpp
@@ -130,22 +130,22 @@ bool ForOfLoopControl::emitEndCodeNeedin
   numYieldsAtBeginCodeNeedingIterClose_ = UINT32_MAX;
 
   return true;
 }
 
 bool ForOfLoopControl::emitIteratorCloseInInnermostScopeWithTryNote(
     BytecodeEmitter* bce,
     CompletionKind completionKind /* = CompletionKind::Normal */) {
-  ptrdiff_t start = bce->offset();
+  ptrdiff_t start = bce->bytecodeSection().offset();
   if (!emitIteratorCloseInScope(bce, *bce->innermostEmitterScope(),
                                 completionKind)) {
     return false;
   }
-  ptrdiff_t end = bce->offset();
+  ptrdiff_t end = bce->bytecodeSection().offset();
   return bce->addTryNote(JSTRY_FOR_OF_ITERCLOSE, 0, start, end);
 }
 
 bool ForOfLoopControl::emitIteratorCloseInScope(
     BytecodeEmitter* bce, EmitterScope& currentScope,
     CompletionKind completionKind /* = CompletionKind::Normal */) {
   return bce->emitIteratorCloseInScope(currentScope, iterKind_, completionKind,
                                        allowSelfHosted_);
@@ -188,17 +188,17 @@ bool ForOfLoopControl::emitPrepareForNon
     //              [stack] ITER UNDEF
     return false;
   }
   if (!bce->emit1(JSOP_SWAP)) {
     //              [stack] UNDEF ITER
     return false;
   }
 
-  *tryNoteStart = bce->offset();
+  *tryNoteStart = bce->bytecodeSection().offset();
   if (!emitIteratorCloseInScope(bce, currentScope, CompletionKind::Normal)) {
     //              [stack] UNDEF
     return false;
   }
 
   if (isTarget) {
     // At the level of the target block, there's bytecode after the
     // loop that will pop the next method, the iterator, and the
--- a/js/src/frontend/LabelEmitter.cpp
+++ b/js/src/frontend/LabelEmitter.cpp
@@ -22,29 +22,29 @@ bool LabelEmitter::emitLabel(JSAtom* nam
   uint32_t index;
   if (!bce_->makeAtomIndex(name, &index)) {
     return false;
   }
   if (!bce_->emitN(JSOP_LABEL, 4, &top_)) {
     return false;
   }
 
-  controlInfo_.emplace(bce_, name, bce_->offset());
+  controlInfo_.emplace(bce_, name, bce_->bytecodeSection().offset());
 
 #ifdef DEBUG
   state_ = State::Label;
 #endif
   return true;
 }
 
 bool LabelEmitter::emitEnd() {
   MOZ_ASSERT(state_ == State::Label);
 
   // Patch the JSOP_LABEL offset.
-  jsbytecode* labelpc = bce_->code(top_);
+  jsbytecode* labelpc = bce_->bytecodeSection().code(top_);
   int32_t offset = bce_->lastNonJumpTargetOffset() - top_;
   MOZ_ASSERT(*labelpc == JSOP_LABEL);
   SET_CODE_OFFSET(labelpc, offset);
 
   // Patch the break/continue to this label.
   if (!controlInfo_->patchBreaks(bce_)) {
     return false;
   }
--- a/js/src/frontend/ObjectEmitter.cpp
+++ b/js/src/frontend/ObjectEmitter.cpp
@@ -407,17 +407,17 @@ bool ObjectEmitter::emitObject(size_t pr
   MOZ_ASSERT(propertyState_ == PropertyState::Start);
   MOZ_ASSERT(objectState_ == ObjectState::Start);
 
   //                [stack]
 
   // Emit code for {p:a, '%q':b, 2:c} that is equivalent to constructing
   // a new object and defining (in source order) each property on the object
   // (or mutating the object's [[Prototype]], in the case of __proto__).
-  top_ = bce_->offset();
+  top_ = bce_->bytecodeSection().offset();
   if (!bce_->emitNewInit()) {
     //              [stack] OBJ
     return false;
   }
 
   // Try to construct the shape of the object as we go, so we can emit a
   // JSOP_NEWOBJECT with the final shape instead.
   // In the case of computed property names and indices, we cannot fix the
--- a/js/src/frontend/SwitchEmitter.cpp
+++ b/js/src/frontend/SwitchEmitter.cpp
@@ -146,66 +146,66 @@ bool SwitchEmitter::validateCaseCount(ui
 
 bool SwitchEmitter::emitCond() {
   MOZ_ASSERT(state_ == State::CaseCount);
 
   kind_ = Kind::Cond;
 
   // After entering the scope if necessary, push the switch control.
   controlInfo_.emplace(bce_, StatementKind::Switch);
-  top_ = bce_->offset();
+  top_ = bce_->bytecodeSection().offset();
 
   if (!caseOffsets_.resize(caseCount_)) {
     ReportOutOfMemory(bce_->cx);
     return false;
   }
 
   // The note has two offsets: first tells total switch code length;
   // second tells offset to first JSOP_CASE.
   if (!bce_->newSrcNote3(SRC_CONDSWITCH, 0, 0, &noteIndex_)) {
     return false;
   }
 
-  MOZ_ASSERT(top_ == bce_->offset());
+  MOZ_ASSERT(top_ == bce_->bytecodeSection().offset());
   if (!bce_->emitN(JSOP_CONDSWITCH, 0)) {
     return false;
   }
 
   tdzCacheCaseAndBody_.emplace(bce_);
 
   state_ = State::Cond;
   return true;
 }
 
 bool SwitchEmitter::emitTable(const TableGenerator& tableGen) {
   MOZ_ASSERT(state_ == State::CaseCount);
   kind_ = Kind::Table;
 
   // After entering the scope if necessary, push the switch control.
   controlInfo_.emplace(bce_, StatementKind::Switch);
-  top_ = bce_->offset();
+  top_ = bce_->bytecodeSection().offset();
 
   // The note has one offset that tells total switch code length.
   if (!bce_->newSrcNote2(SRC_TABLESWITCH, 0, &noteIndex_)) {
     return false;
   }
 
   if (!caseOffsets_.resize(tableGen.tableLength())) {
     ReportOutOfMemory(bce_->cx);
     return false;
   }
 
-  MOZ_ASSERT(top_ == bce_->offset());
+  MOZ_ASSERT(top_ == bce_->bytecodeSection().offset());
   if (!bce_->emitN(JSOP_TABLESWITCH,
                    JSOP_TABLESWITCH_LENGTH - sizeof(jsbytecode))) {
     return false;
   }
 
   // Skip default offset.
-  jsbytecode* pc = bce_->code(top_ + JUMP_OFFSET_LEN);
+  jsbytecode* pc = bce_->bytecodeSection().code(top_ + JUMP_OFFSET_LEN);
 
   // Fill in switch bounds, which we know fit in 16-bit offsets.
   SET_JUMP_OFFSET(pc, tableGen.low());
   SET_JUMP_OFFSET(pc + JUMP_OFFSET_LEN, tableGen.high());
 
   state_ = State::Table;
   return true;
 }
@@ -218,19 +218,19 @@ bool SwitchEmitter::emitCaseOrDefaultJum
       return false;
     }
     return true;
   }
 
   if (caseIndex > 0) {
     // Link the last JSOP_CASE's SRC_NEXTCASE to current JSOP_CASE for the
     // benefit of IonBuilder.
-    if (!bce_->setSrcNoteOffset(caseNoteIndex_,
-                                SrcNote::NextCase::NextCaseOffset,
-                                bce_->offset() - lastCaseOffset_)) {
+    if (!bce_->setSrcNoteOffset(
+            caseNoteIndex_, SrcNote::NextCase::NextCaseOffset,
+            bce_->bytecodeSection().offset() - lastCaseOffset_)) {
       return false;
     }
   }
 
   if (!bce_->newSrcNote2(SRC_NEXTCASE, 0, &caseNoteIndex_)) {
     return false;
   }
 
@@ -393,17 +393,17 @@ bool SwitchEmitter::emitEnd() {
   // Set the default offset (to end of switch if no default).
   jsbytecode* pc;
   if (kind_ == Kind::Cond) {
     pc = nullptr;
     bce_->patchJumpsToTarget(condSwitchDefaultOffset_,
                              defaultJumpTargetOffset_);
   } else {
     // Fill in the default jump target.
-    pc = bce_->code(top_);
+    pc = bce_->bytecodeSection().code(top_);
     SET_JUMP_OFFSET(pc, defaultJumpTargetOffset_.offset - top_);
     pc += JUMP_OFFSET_LEN;
   }
 
   // Set the SRC_SWITCH note's offset operand to tell end of switch.
   // This code is shared between table switch and cond switch.
   static_assert(unsigned(SrcNote::TableSwitch::EndOffset) ==
                     unsigned(SrcNote::CondSwitch::EndOffset),
--- a/js/src/frontend/TryEmitter.cpp
+++ b/js/src/frontend/TryEmitter.cpp
@@ -57,17 +57,17 @@ bool TryEmitter::emitTry() {
 
   // Record the try location, then emit the try block.
   if (!bce_->newSrcNote(SRC_TRY, &noteIndex_)) {
     return false;
   }
   if (!bce_->emit1(JSOP_TRY)) {
     return false;
   }
-  tryStart_ = bce_->offset();
+  tryStart_ = bce_->bytecodeSection().offset();
 
 #ifdef DEBUG
   state_ = State::Try;
 #endif
   return true;
 }
 
 bool TryEmitter::emitTryEnd() {
@@ -77,18 +77,19 @@ bool TryEmitter::emitTryEnd() {
   // GOSUB to finally, if present.
   if (hasFinally() && controlInfo_) {
     if (!bce_->emitGoSub(&controlInfo_->gosubs)) {
       return false;
     }
   }
 
   // Source note points to the jump at the end of the try block.
-  if (!bce_->setSrcNoteOffset(noteIndex_, SrcNote::Try::EndOfTryJumpOffset,
-                              bce_->offset() - tryStart_ + JSOP_TRY_LENGTH)) {
+  if (!bce_->setSrcNoteOffset(
+          noteIndex_, SrcNote::Try::EndOfTryJumpOffset,
+          bce_->bytecodeSection().offset() - tryStart_ + JSOP_TRY_LENGTH)) {
     return false;
   }
 
   // Emit jump over catch and/or finally.
   if (!bce_->emitJump(JSOP_GOTO, &catchAndFinallyJump_)) {
     return false;
   }
 
--- a/js/src/vm/JSScript.cpp
+++ b/js/src/vm/JSScript.cpp
@@ -4518,31 +4518,31 @@ bool JSScript::hasBreakpointsAt(jsbyteco
   }
 
   return site->enabledCount > 0;
 }
 
 /* static */ bool SharedScriptData::InitFromEmitter(
     JSContext* cx, js::HandleScript script, frontend::BytecodeEmitter* bce) {
   uint32_t natoms = bce->atomIndices->count();
-  uint32_t codeLength = bce->code().length();
+  uint32_t codeLength = bce->bytecodeSection().code().length();
 
   // The + 1 is to account for the final SN_MAKE_TERMINATOR that is appended
   // when the notes are copied to their final destination by copySrcNotes.
   uint32_t noteLength = bce->notes().length() + 1;
 
   // Create and initialize SharedScriptData
   if (!script->createSharedScriptData(cx, codeLength, noteLength, natoms)) {
     return false;
   }
 
   js::SharedScriptData* data = script->scriptData_;
 
   // Initialize trailing arrays
-  std::copy_n(bce->code().begin(), codeLength, data->code());
+  std::copy_n(bce->bytecodeSection().code().begin(), codeLength, data->code());
   bce->copySrcNotes(data->notes(), noteLength);
   InitAtomMap(*bce->atomIndices, data->atoms());
 
   return true;
 }
 
 void SharedScriptData::traceChildren(JSTracer* trc) {
   MOZ_ASSERT(refCount() != 0);