Bug 1284719 part 2 - Fold EmitSection into BytecodeEmitter, remove prologue/main split. r=arai
authorJan de Mooij <jdemooij@mozilla.com>
Fri, 18 Jan 2019 13:15:27 +0000
changeset 514423 83d6478d261167ec129ffc5286a60bfbb39d0c31
parent 514422 1d260750a87e00de63750365d7c0c6fb34241c58
child 514424 529a105310435244ef67c078a810ad92b22d9327
push id1953
push userffxbld-merge
push dateMon, 11 Mar 2019 12:10:20 +0000
treeherdermozilla-release@9c35dcbaa899 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersarai
bugs1284719
milestone66.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 1284719 part 2 - Fold EmitSection into BytecodeEmitter, remove prologue/main split. r=arai Differential Revision: https://phabricator.services.mozilla.com/D16948
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/BytecodeEmitter.h
js/src/frontend/CForEmitter.cpp
js/src/frontend/EmitterScope.cpp
js/src/vm/JSScript.cpp
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -91,19 +91,23 @@ BytecodeEmitter::BytecodeEmitter(Bytecod
                                  HandleScript script,
                                  Handle<LazyScript*> lazyScript,
                                  uint32_t lineNum, EmitterMode emitterMode)
     : sc(sc),
       cx(sc->context),
       parent(parent),
       script(cx, script),
       lazyScript(cx, lazyScript),
-      prologue(cx, lineNum),
-      main(cx, lineNum),
-      current(&prologue),
+      code_(cx),
+      notes_(cx),
+      lastNoteOffset_(0),
+      currentLine_(lineNum),
+      lastColumn_(0),
+      mainOffset_(),
+      lastTarget{-1 - ptrdiff_t(JSOP_JUMPTARGET_LENGTH)},
       parser(nullptr),
       atomIndices(cx->frontendCollectionPool()),
       firstLine(lineNum),
       maxFixedSlots(0),
       maxStackDepth(0),
       stackDepth(0),
       emitLevel(0),
       bodyScopeIndex(UINT32_MAX),
@@ -296,23 +300,23 @@ bool BytecodeEmitter::emitN(JSOp op, siz
   }
   return true;
 }
 
 bool BytecodeEmitter::emitJumpTarget(JumpTarget* target) {
   ptrdiff_t off = offset();
 
   // Alias consecutive jump targets.
-  if (off == current->lastTarget.offset + ptrdiff_t(JSOP_JUMPTARGET_LENGTH)) {
-    target->offset = current->lastTarget.offset;
+  if (off == lastTarget.offset + ptrdiff_t(JSOP_JUMPTARGET_LENGTH)) {
+    target->offset = lastTarget.offset;
     return true;
   }
 
   target->offset = off;
-  current->lastTarget.offset = off;
+  lastTarget.offset = off;
   if (!emit1(JSOP_JUMPTARGET)) {
     return false;
   }
   return true;
 }
 
 bool BytecodeEmitter::emitJumpNoFallthrough(JSOp op, JumpList* jump) {
   ptrdiff_t offset;
@@ -464,18 +468,17 @@ bool BytecodeEmitter::updateLineNumberNo
      * whichever consumes less space.
      *
      * NB: We handle backward line number deltas (possible with for
      * loops where the update part is emitted after the body, but its
      * line number is <= any line number in the body) here by letting
      * unsigned delta_ wrap to a very large number, which triggers a
      * SRC_SETLINE.
      */
-    current->currentLine = line;
-    current->lastColumn = 0;
+    setCurrentLine(line);
     if (delta >= LengthOfSetLine(line)) {
       if (!newSrcNote2(SRC_SETLINE, ptrdiff_t(line))) {
         return false;
       }
     } else {
       do {
         if (!newSrcNote(SRC_NEWLINE)) {
           return false;
@@ -493,30 +496,30 @@ bool BytecodeEmitter::updateSourceCoordN
   }
 
   // Don't emit line/column number notes in the prologue.
   if (inPrologue()) {
     return true;
   }
 
   uint32_t columnIndex = parser->errorReporter().columnAt(offset);
-  ptrdiff_t colspan = ptrdiff_t(columnIndex) - ptrdiff_t(current->lastColumn);
+  ptrdiff_t colspan = ptrdiff_t(columnIndex) - ptrdiff_t(lastColumn_);
   if (colspan != 0) {
     // If the column span is so large that we can't store it, then just
     // discard this information. This can happen with minimized or otherwise
     // machine-generated code. Even gigantic column numbers are still
     // valuable if you have a source map to relate them to something real;
     // but it's better to fail soft here.
     if (!SN_REPRESENTABLE_COLSPAN(colspan)) {
       return true;
     }
     if (!newSrcNote2(SRC_COLSPAN, SN_COLSPAN_TO_OFFSET(colspan))) {
       return false;
     }
-    current->lastColumn = columnIndex;
+    lastColumn_ = columnIndex;
   }
   return true;
 }
 
 Maybe<uint32_t> BytecodeEmitter::getOffsetForLoop(ParseNode* nextpn) {
   if (!nextpn) {
     return Nothing();
   }
@@ -599,17 +602,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_->inPrologue());
+      bce_->scopeNoteList.recordEnd(n, bce_->offset());
     }
     bce_->stackDepth = savedDepth_;
   }
 
   MOZ_MUST_USE bool prepareForNonLocalJump(NestableControl* target);
 
   MOZ_MUST_USE bool prepareForNonLocalJumpToOutermost() {
     return prepareForNonLocalJump(nullptr);
@@ -624,17 +627,17 @@ 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(),
-                                  bce_->inPrologue(), openScopeNoteIndex_)) {
+                                  openScopeNoteIndex_)) {
     return false;
   }
   openScopeNoteIndex_ = bce_->scopeNoteList.length() - 1;
 
   return true;
 }
 
 /*
@@ -9142,19 +9145,16 @@ static bool AllocSrcNote(JSContext* cx, 
   }
 
   *index = notes.length() - 1;
   return true;
 }
 
 bool BytecodeEmitter::addTryNote(JSTryNoteKind kind, uint32_t stackDepth,
                                  size_t start, size_t end) {
-  // The tryNoteList stores offsets relative to current section should must
-  // be main section. During tryNoteList.finish(), the prologueLength will be
-  // added to correct offset.
   MOZ_ASSERT(!inPrologue());
   return tryNoteList.append(kind, stackDepth, start, end);
 }
 
 bool BytecodeEmitter::newSrcNote(SrcNoteType type, unsigned* indexp) {
   SrcNotesVector& notes = this->notes();
   unsigned index;
   if (!AllocSrcNote(cx, notes, &index)) {
@@ -9162,17 +9162,17 @@ bool BytecodeEmitter::newSrcNote(SrcNote
   }
 
   /*
    * 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 delta = offset - lastNoteOffset();
-  current->lastNoteOffset = offset;
+  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)) {
         return false;
       }
@@ -9269,62 +9269,22 @@ bool BytecodeEmitter::setSrcNoteOffset(u
     *sn++ = (jssrcnote)(SN_4BYTE_OFFSET_FLAG | (offset >> 24));
     *sn++ = (jssrcnote)(offset >> 16);
     *sn++ = (jssrcnote)(offset >> 8);
   }
   *sn = (jssrcnote)offset;
   return true;
 }
 
-bool BytecodeEmitter::finishTakingSrcNotes(uint32_t* out) {
-  MOZ_ASSERT(current == &main);
-
-  MOZ_ASSERT(prologue.notes.length() == 0);
-  MOZ_ASSERT(prologue.lastNoteOffset == 0);
-
-  // We may need to adjust the offset of the first main note to account for
-  // prologue bytecodes. If it can be done by adjusting the delta of the first
-  // main note, we do so. Otherwise, we insert xdeltas into the prologue.
-  ptrdiff_t offset = prologueOffset();
-  MOZ_ASSERT(offset >= 0);
-  if (offset > 0 && main.notes.length() != 0) {
-    // Use the first main note's delta if we can.
-    jssrcnote* sn = main.notes.begin();
-    ptrdiff_t newDelta = SN_DELTA(sn) + offset;
-    ptrdiff_t deltaLimit = SN_IS_XDELTA(sn) ? SN_XDELTA_LIMIT : SN_DELTA_LIMIT;
-    if (newDelta < deltaLimit) {
-      SN_SET_DELTA(sn, newDelta);
-    } else {
-      // Otherwise, add xdeltas to the prologue.
-      while (offset > 0) {
-        jssrcnote xdelta;
-        ptrdiff_t xdelta_size = Min(offset, SN_XDELTA_MASK);
-        SN_MAKE_XDELTA(&xdelta, xdelta_size);
-        if (!prologue.notes.append(xdelta)) {
-          return false;
-        }
-        offset -= xdelta_size;
-      }
-    }
-  }
-
-  // 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.
-  *out = prologue.notes.length() + main.notes.length() + 1;
-  return true;
-}
-
 void BytecodeEmitter::copySrcNotes(jssrcnote* destination, uint32_t nsrcnotes) {
-  unsigned prologueCount = prologue.notes.length();
-  unsigned mainCount = main.notes.length();
+  unsigned count = notes_.length();
   // nsrcnotes includes SN_MAKE_TERMINATOR in addition to the srcnotes.
-  MOZ_ASSERT(nsrcnotes == prologueCount + mainCount + 1);
-  PodCopy(destination, prologue.notes.begin(), prologueCount);
-  PodCopy(destination + prologueCount, main.notes.begin(), mainCount);
-  SN_MAKE_TERMINATOR(&destination[prologueCount + mainCount]);
+  MOZ_ASSERT(nsrcnotes == count + 1);
+  PodCopy(destination, notes_.begin(), count);
+  SN_MAKE_TERMINATOR(&destination[count]);
 }
 
 void CGNumberList::finish(mozilla::Span<GCPtrValue> array) {
   MOZ_ASSERT(length() == array.size());
 
   for (unsigned i = 0; i < length(); i++) {
     array[i].init(vector[i]);
   }
@@ -9384,73 +9344,60 @@ bool CGTryNoteList::append(JSTryNoteKind
   note.kind = kind;
   note.stackDepth = stackDepth;
   note.start = uint32_t(start);
   note.length = uint32_t(end - start);
 
   return list.append(note);
 }
 
-void CGTryNoteList::finish(mozilla::Span<JSTryNote> array,
-                           uint32_t prologueLength) {
+void CGTryNoteList::finish(mozilla::Span<JSTryNote> array) {
   MOZ_ASSERT(length() == array.size());
 
   for (unsigned i = 0; i < length(); i++) {
-    list[i].start += prologueLength;
     array[i] = list[i];
   }
 }
 
 bool CGScopeNoteList::append(uint32_t scopeIndex, uint32_t offset,
-                             bool inPrologue, uint32_t parent) {
+                             uint32_t parent) {
   CGScopeNote note;
   mozilla::PodZero(&note);
 
   // Offsets are given relative to sections. In finish() we will fixup base
   // offset if needed.
 
   note.index = scopeIndex;
   note.start = offset;
   note.parent = parent;
-  note.startInPrologue = inPrologue;
 
   return list.append(note);
 }
 
-void CGScopeNoteList::recordEnd(uint32_t index, uint32_t offset,
-                                bool inPrologue) {
+void CGScopeNoteList::recordEnd(uint32_t index, uint32_t offset) {
   MOZ_ASSERT(index < length());
   MOZ_ASSERT(list[index].length == 0);
   list[index].end = offset;
-  list[index].endInPrologue = inPrologue;
-}
-
-void CGScopeNoteList::finish(mozilla::Span<ScopeNote> array,
-                             uint32_t prologueLength) {
+}
+
+void CGScopeNoteList::finish(mozilla::Span<ScopeNote> array) {
   MOZ_ASSERT(length() == array.size());
 
   for (unsigned i = 0; i < length(); i++) {
-    if (!list[i].startInPrologue) {
-      list[i].start += prologueLength;
-    }
-    if (!list[i].endInPrologue && list[i].end != UINT32_MAX) {
-      list[i].end += prologueLength;
-    }
     MOZ_ASSERT(list[i].end >= list[i].start);
     list[i].length = list[i].end - list[i].start;
     array[i] = list[i];
   }
 }
 
-void CGResumeOffsetList::finish(mozilla::Span<uint32_t> array,
-                                uint32_t prologueLength) {
+void CGResumeOffsetList::finish(mozilla::Span<uint32_t> array) {
   MOZ_ASSERT(length() == array.size());
 
   for (unsigned i = 0; i < length(); i++) {
-    array[i] = prologueLength + list[i];
+    array[i] = list[i];
   }
 }
 
 const JSSrcNoteSpec js_SrcNoteSpec[] = {
 #define DEFINE_SRC_NOTE_SPEC(sym, name, arity) {name, arity},
     FOR_EACH_SRC_NOTE_TYPE(DEFINE_SRC_NOTE_SPEC)
 #undef DEFINE_SRC_NOTE_SPEC
 };
--- a/js/src/frontend/BytecodeEmitter.h
+++ b/js/src/frontend/BytecodeEmitter.h
@@ -57,55 +57,45 @@ struct MOZ_STACK_CLASS CGScopeList {
   uint32_t length() const { return vector.length(); }
   void finish(mozilla::Span<GCPtrScope> array);
 };
 
 struct CGTryNoteList {
   Vector<JSTryNote> list;
   explicit CGTryNoteList(JSContext* cx) : list(cx) {}
 
-  // Start/end offset are relative to main section and will be patch in
-  // finish().
-
   MOZ_MUST_USE bool append(JSTryNoteKind kind, uint32_t stackDepth,
                            size_t start, size_t end);
   size_t length() const { return list.length(); }
-  void finish(mozilla::Span<JSTryNote> array, uint32_t prologueLength);
+  void finish(mozilla::Span<JSTryNote> array);
 };
 
 struct CGScopeNote : public ScopeNote {
-  // The end offset. Used to compute the length; may need adjusting first if
-  // in the prologue.
+  // The end offset. Used to compute the length.
   uint32_t end;
-
-  // Is the start offset in the prologue?
-  bool startInPrologue;
-
-  // Is the end offset in the prologue?
-  bool endInPrologue;
 };
 
 struct CGScopeNoteList {
   Vector<CGScopeNote> list;
   explicit CGScopeNoteList(JSContext* cx) : list(cx) {}
 
   MOZ_MUST_USE bool append(uint32_t scopeIndex, uint32_t offset,
-                           bool inPrologue, uint32_t parent);
-  void recordEnd(uint32_t index, uint32_t offset, bool inPrologue);
+                           uint32_t parent);
+  void recordEnd(uint32_t index, uint32_t offse);
   size_t length() const { return list.length(); }
-  void finish(mozilla::Span<ScopeNote> array, uint32_t prologueLength);
+  void finish(mozilla::Span<ScopeNote> array);
 };
 
 struct CGResumeOffsetList {
   Vector<uint32_t> list;
   explicit CGResumeOffsetList(JSContext* cx) : list(cx) {}
 
   MOZ_MUST_USE bool append(uint32_t offset) { return list.append(offset); }
   size_t length() const { return list.length(); }
-  void finish(mozilla::Span<uint32_t> array, uint32_t prologueLength);
+  void finish(mozilla::Span<uint32_t> array);
 };
 
 // Have a few inline elements, so as to avoid heap allocation for tiny
 // sequences.  See bug 1390526.
 typedef Vector<jsbytecode, 64> BytecodeVector;
 typedef Vector<jssrcnote, 64> SrcNotesVector;
 
 class CallOrNewEmitter;
@@ -123,45 +113,40 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
 
   BytecodeEmitter* const parent; /* enclosing function or global context */
 
   Rooted<JSScript*> script; /* the JSScript we're ultimately producing */
 
   Rooted<LazyScript*> lazyScript; /* the lazy script if mode is LazyFunction,
                                       nullptr otherwise. */
 
-  struct EmitSection {
-    BytecodeVector code;      /* bytecode */
-    SrcNotesVector notes;     /* source notes, see below */
-    ptrdiff_t lastNoteOffset; /* code offset for last source note */
+ private:
+  BytecodeVector code_;  /* bytecode */
+  SrcNotesVector notes_; /* source notes, see below */
+
+  ptrdiff_t lastNoteOffset_; /* code offset for last source note */
 
-    // Line number for srcnotes.
-    //
-    // WARNING: If this becomes out of sync with already-emitted srcnotes,
-    // we can get undefined behavior.
-    uint32_t currentLine;
+  // Line number for srcnotes.
+  //
+  // WARNING: If this becomes out of sync with already-emitted srcnotes,
+  // we can get undefined behavior.
+  uint32_t currentLine_;
 
-    // Zero-based column index on currentLine of last SRC_COLSPAN-annotated
-    // opcode.
-    //
-    // WARNING: If this becomes out of sync with already-emitted srcnotes,
-    // we can get undefined behavior.
-    uint32_t lastColumn;
-
-    JumpTarget lastTarget;  // Last jump target emitted.
+  // Zero-based column index on currentLine of last SRC_COLSPAN-annotated
+  // opcode.
+  //
+  // WARNING: If this becomes out of sync with already-emitted srcnotes,
+  // we can get undefined behavior.
+  uint32_t lastColumn_;
 
-    EmitSection(JSContext* cx, uint32_t lineNum)
-        : code(cx),
-          notes(cx),
-          lastNoteOffset(0),
-          currentLine(lineNum),
-          lastColumn(0),
-          lastTarget{-1 - ptrdiff_t(JSOP_JUMPTARGET_LENGTH)} {}
-  };
-  EmitSection prologue, main, *current;
+  // switchToMain sets this to the bytecode offset of the main section.
+  mozilla::Maybe<uint32_t> mainOffset_;
+
+ public:
+  JumpTarget lastTarget;  // Last jump target emitted.
 
   // Private storage for parser wrapper. DO NOT REFERENCE INTERNALLY. May not be
   // initialized. Use |parser| instead.
   mozilla::Maybe<EitherParser> ep_;
   BCEParserHandle* parser;
 
   PooledMapPtr<AtomIndexMap> atomIndices; /* literals indexed for mapping */
   unsigned firstLine; /* first line, for JSScript::initFromEmitter */
@@ -385,52 +370,55 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
 
   bool needsImplicitThis();
 
   MOZ_MUST_USE bool emitThisEnvironmentCallee();
   MOZ_MUST_USE bool emitSuperBase();
 
   void tellDebuggerAboutCompiledScript(JSContext* cx);
 
-  BytecodeVector& code() const { return current->code; }
-  jsbytecode* code(ptrdiff_t offset) const {
-    return current->code.begin() + offset;
-  }
-  ptrdiff_t offset() const {
-    return current->code.end() - current->code.begin();
-  }
-  ptrdiff_t prologueOffset() const {
-    return prologue.code.end() - prologue.code.begin();
-  }
+  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());
-    current = &main;
+    mainOffset_.emplace(code_.length());
   }
-  bool inPrologue() const { return current == &prologue; }
 
-  SrcNotesVector& notes() const {
+  SrcNotesVector& notes() {
     // Prologue shouldn't have source notes.
     MOZ_ASSERT(!inPrologue());
-    return current->notes;
+    return notes_;
   }
-  ptrdiff_t lastNoteOffset() const { return current->lastNoteOffset; }
-  unsigned currentLine() const { return current->currentLine; }
+  ptrdiff_t lastNoteOffset() const { return lastNoteOffset_; }
+  unsigned currentLine() const { return currentLine_; }
+
+  void setCurrentLine(uint32_t line) {
+    currentLine_ = line;
+    lastColumn_ = 0;
+  }
 
   // Check if the last emitted opcode is a jump target.
   bool lastOpcodeIsJumpTarget() const {
-    return offset() - current->lastTarget.offset ==
-           ptrdiff_t(JSOP_JUMPTARGET_LENGTH);
+    return 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() ? current->lastTarget.offset : offset();
+    return lastOpcodeIsJumpTarget() ? lastTarget.offset : offset();
   }
 
   void setFunctionBodyEndPos(TokenPos pos) {
     functionBodyEndPos = pos.end;
     functionBodyEndPosSet = true;
   }
 
   void setScriptStartOffsetIfUnset(TokenPos pos) {
@@ -476,20 +464,16 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
                                 unsigned* indexp = nullptr);
   MOZ_MUST_USE bool newSrcNote3(SrcNoteType type, ptrdiff_t offset1,
                                 ptrdiff_t offset2, unsigned* indexp = nullptr);
 
   void copySrcNotes(jssrcnote* destination, uint32_t nsrcnotes);
   MOZ_MUST_USE bool setSrcNoteOffset(unsigned index, unsigned which,
                                      ptrdiff_t offset);
 
-  // Finish taking source notes in cx's notePool. If successful, the final
-  // source note count is stored in the out outparam.
-  MOZ_MUST_USE bool finishTakingSrcNotes(uint32_t* out);
-
   // Control whether emitTree emits a line number note.
   enum EmitLineNumberNote { EMIT_LINENOTE, SUPPRESS_LINENOTE };
 
   // Emit code for the tree rooted at pn.
   MOZ_MUST_USE bool emitTree(ParseNode* pn,
                              ValueUsage valueUsage = ValueUsage::WantValue,
                              EmitLineNumberNote emitLineNote = EMIT_LINENOTE);
 
--- a/js/src/frontend/CForEmitter.cpp
+++ b/js/src/frontend/CForEmitter.cpp
@@ -162,18 +162,17 @@ bool CForEmitter::emitCond(const Maybe<u
 
     // Restore the absolute line number for source note readers.
     if (endPos) {
       uint32_t lineNum = bce_->parser->errorReporter().lineAt(*endPos);
       if (bce_->currentLine() != lineNum) {
         if (!bce_->newSrcNote2(SRC_SETLINE, ptrdiff_t(lineNum))) {
           return false;
         }
-        bce_->current->currentLine = lineNum;
-        bce_->current->lastColumn = 0;
+        bce_->setCurrentLine(lineNum);
       }
     }
   }
 
   if (update_ == Update::Present) {
     tdzCache_.reset();
   }
 
--- 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(), bce->inPrologue(),
+  return bce->scopeNoteList.append(index(), bce->offset(),
                                    enclosingInFrame()
                                        ? enclosingInFrame()->noteIndex()
                                        : ScopeNote::NoScopeNoteIndex);
 }
 
 bool EmitterScope::deadZoneFrameSlotRange(BytecodeEmitter* bce,
                                           uint32_t slotStart,
                                           uint32_t slotEnd) const {
@@ -1054,17 +1054,17 @@ bool EmitterScope::leave(BytecodeEmitter
   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();
-      bce->scopeNoteList.recordEnd(noteIndex_, offset, bce->inPrologue());
+      bce->scopeNoteList.recordEnd(noteIndex_, offset);
     }
   }
 
   return true;
 }
 
 Scope* EmitterScope::scope(const BytecodeEmitter* bce) const {
   return bce->scopeList.vector[index()];
--- a/js/src/vm/JSScript.cpp
+++ b/js/src/vm/JSScript.cpp
@@ -3374,49 +3374,44 @@ static void InitAtomMap(frontend::AtomIn
 
   uint64_t nslots =
       bce->maxFixedSlots + static_cast<uint64_t>(bce->maxStackDepth);
   if (nslots > UINT32_MAX) {
     bce->reportError(nullptr, JSMSG_NEED_DIET, js_script_str);
     return false;
   }
 
-  uint32_t mainLength = bce->offset();
-  uint32_t prologueLength = bce->prologueOffset();
-  uint32_t nsrcnotes;
-  if (!bce->finishTakingSrcNotes(&nsrcnotes)) {
-    return false;
-  }
   uint32_t natoms = bce->atomIndices->count();
   if (!createPrivateScriptData(
           cx, script, bce->scopeList.length(), bce->numberList.length(),
           bce->objectList.length, bce->tryNoteList.length(),
           bce->scopeNoteList.length(), bce->resumeOffsetList.length())) {
     return false;
   }
 
   MOZ_ASSERT(script->mainOffset() == 0);
-  script->mainOffset_ = prologueLength;
+  script->mainOffset_ = bce->mainOffset();
   script->nTypeSets_ = bce->typesetCount;
   script->lineno_ = bce->firstLine;
 
-  if (!script->createSharedScriptData(cx, prologueLength + mainLength,
-                                      nsrcnotes, natoms)) {
+  // 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 nsrcnotes = bce->notes().length() + 1;
+  uint32_t codeLength = bce->code().length();
+  if (!script->createSharedScriptData(cx, codeLength, nsrcnotes, natoms)) {
     return false;
   }
 
   // Any fallible operation after JSScript::createSharedScriptData should
   // reset JSScript.scriptData_, in order to treat this script as
   // uncompleted, in JSScript::isUncompleted.  JSScript::shareScriptData
   // resets it before returning false.
 
   jsbytecode* code = script->code();
-  PodCopy<jsbytecode>(code, bce->prologue.code.begin(), prologueLength);
-  PodCopy<jsbytecode>(code + prologueLength, bce->main.code.begin(),
-                      mainLength);
+  PodCopy<jsbytecode>(code, bce->code().begin(), codeLength);
   bce->copySrcNotes((jssrcnote*)(code + script->length()), nsrcnotes);
   InitAtomMap(*bce->atomIndices, script->atoms());
 
   if (!script->shareScriptData(cx)) {
     return false;
   }
 
   js::PrivateScriptData* data = script->data_;
@@ -3425,23 +3420,23 @@ static void InitAtomMap(frontend::AtomIn
   }
   if (bce->objectList.length != 0) {
     bce->objectList.finish(data->objects());
   }
   if (bce->scopeList.length() != 0) {
     bce->scopeList.finish(data->scopes());
   }
   if (bce->tryNoteList.length() != 0) {
-    bce->tryNoteList.finish(data->tryNotes(), prologueLength);
+    bce->tryNoteList.finish(data->tryNotes());
   }
   if (bce->scopeNoteList.length() != 0) {
-    bce->scopeNoteList.finish(data->scopeNotes(), prologueLength);
+    bce->scopeNoteList.finish(data->scopeNotes());
   }
   if (bce->resumeOffsetList.length() != 0) {
-    bce->resumeOffsetList.finish(data->resumeOffsets(), prologueLength);
+    bce->resumeOffsetList.finish(data->resumeOffsets());
   }
 
   script->setFlag(ImmutableFlags::Strict, bce->sc->strict());
   script->setFlag(ImmutableFlags::ExplicitUseStrict,
                   bce->sc->hasExplicitUseStrict());
   script->setFlag(ImmutableFlags::BindingsAccessedDynamically,
                   bce->sc->bindingsAccessedDynamically());
   script->setFlag(ImmutableFlags::HasSingletons, bce->hasSingletons);