Bug 1535994 - Part 8: Move resume/yield info to BytecodeSection class. r=jorendorff
☠☠ backed out by 7fb3acf38591 ☠ ☠
authorTooru Fujisawa <arai_a@mac.com>
Wed, 10 Apr 2019 08:27:23 +0000
changeset 468765 db520471b4073f6ca3a9f671d522987f1298fa50
parent 468764 096ab8585046007ed3a7853e4b2ce6ce37f55243
child 468766 fdd1177e499a08b4cde3e80992e288e5ee8084d5
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 8: Move resume/yield info to BytecodeSection class. r=jorendorff Differential Revision: https://phabricator.services.mozilla.com/D25738
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/BytecodeEmitter.h
js/src/frontend/ForOfLoopControl.cpp
js/src/vm/JSScript.cpp
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -87,17 +87,21 @@ static bool ParseNodeRequiresSpecialLine
   // 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), notes_(cx), tryNoteList_(cx), scopeNoteList_(cx) {}
+    : code_(cx),
+      notes_(cx),
+      tryNoteList_(cx),
+      scopeNoteList_(cx),
+      resumeOffsetList_(cx) {}
 
 BytecodeEmitter::PerScriptData::PerScriptData(JSContext* cx)
     : scopeList_(cx), numberList_(cx) {}
 
 BytecodeEmitter::BytecodeEmitter(
     BytecodeEmitter* parent, SharedContext* sc, HandleScript script,
     Handle<LazyScript*> lazyScript, uint32_t lineNum, EmitterMode emitterMode,
     FieldInitializers fieldInitializers /* = FieldInitializers::Invalid() */)
@@ -107,17 +111,16 @@ BytecodeEmitter::BytecodeEmitter(
       script(cx, script),
       lazyScript(cx, lazyScript),
       bytecodeSection_(cx),
       perScriptData_(cx),
       currentLine_(lineNum),
       fieldInitializers_(fieldInitializers),
       atomIndices(cx->frontendCollectionPool()),
       firstLine(lineNum),
-      resumeOffsetList(cx),
       emitterMode(emitterMode) {
   MOZ_ASSERT_IF(emitterMode == LazyFunction, lazyScript);
 
   if (sc->isFunctionBox()) {
     // Functions have IC entries for type monitoring |this| and arguments.
     numICEntries = sc->asFunctionBox()->function()->nargs() + 1;
   }
 }
@@ -2256,23 +2259,23 @@ bool BytecodeEmitter::allocateResumeInde
       MaxResumeIndex < uint32_t(AbstractGeneratorObject::RESUME_INDEX_CLOSING),
       "resumeIndex should not include magic AbstractGeneratorObject "
       "resumeIndex values");
   static_assert(
       MaxResumeIndex <= INT32_MAX / sizeof(uintptr_t),
       "resumeIndex * sizeof(uintptr_t) must fit in an int32. JIT code relies "
       "on this when loading resume entries from BaselineScript");
 
-  *resumeIndex = resumeOffsetList.length();
+  *resumeIndex = bytecodeSection().resumeOffsetList().length();
   if (*resumeIndex > MaxResumeIndex) {
     reportError(nullptr, JSMSG_TOO_MANY_RESUME_INDEXES);
     return false;
   }
 
-  return resumeOffsetList.append(offset);
+  return bytecodeSection().resumeOffsetList().append(offset);
 }
 
 bool BytecodeEmitter::allocateResumeIndexRange(mozilla::Span<ptrdiff_t> offsets,
                                                uint32_t* firstResumeIndex) {
   *firstResumeIndex = 0;
 
   for (size_t i = 0, len = offsets.size(); i < len; i++) {
     uint32_t resumeIndex;
@@ -2295,17 +2298,17 @@ bool BytecodeEmitter::emitYieldOp(JSOp o
   MOZ_ASSERT(op == JSOP_INITIALYIELD || op == JSOP_YIELD || op == JSOP_AWAIT);
 
   ptrdiff_t off;
   if (!emitN(op, 3, &off)) {
     return false;
   }
 
   if (op == JSOP_INITIALYIELD || op == JSOP_YIELD) {
-    numYields++;
+    bytecodeSection().addNumYields();
   }
 
   uint32_t resumeIndex;
   if (!allocateResumeIndex(bytecodeSection().offset(), &resumeIndex)) {
     return false;
   }
 
   SET_RESUMEINDEX(bytecodeSection().code(off), resumeIndex);
--- a/js/src/frontend/BytecodeEmitter.h
+++ b/js/src/frontend/BytecodeEmitter.h
@@ -178,16 +178,26 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
     CGTryNoteList& tryNoteList() { return tryNoteList_; };
     const CGTryNoteList& tryNoteList() const { return tryNoteList_; };
 
     // ---- Scope ----
 
     CGScopeNoteList& scopeNoteList() { return scopeNoteList_; };
     const CGScopeNoteList& scopeNoteList() const { return scopeNoteList_; };
 
+    // ---- Generator ----
+
+    CGResumeOffsetList& resumeOffsetList() { return resumeOffsetList_; }
+    const CGResumeOffsetList& resumeOffsetList() const {
+      return resumeOffsetList_;
+    }
+
+    uint32_t numYields() const { return numYields_; }
+    void addNumYields() { numYields_++; }
+
    private:
     // ---- Bytecode ----
 
     // Bytecode.
     BytecodeVector code_;
 
     // ---- Source notes ----
 
@@ -214,16 +224,28 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
 
     // List of emitted try notes.
     CGTryNoteList tryNoteList_;
 
     // ---- Scope ----
 
     // List of emitted block scope notes.
     CGScopeNoteList scopeNoteList_;
+
+    // ---- Generator ----
+
+    // Certain ops (yield, await, gosub) have an entry in the script's
+    // resumeOffsets list. This can be used to map from the op's resumeIndex to
+    // the bytecode offset of the next pc. This indirection makes it easy to
+    // resume in the JIT (because BaselineScript stores a resumeIndex => native
+    // code array).
+    CGResumeOffsetList resumeOffsetList_;
+
+    // Number of yield instructions emitted. Does not include JSOP_AWAIT.
+    uint32_t numYields_ = 0;
   };
 
   BytecodeSection bytecodeSection_;
 
  public:
   BytecodeSection& bytecodeSection() { return bytecodeSection_; }
   const BytecodeSection& bytecodeSection() const { return bytecodeSection_; }
 
@@ -322,29 +344,19 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
   EmitterScope* innermostEmitterScope() const {
     MOZ_ASSERT(!unstableEmitterScope);
     return innermostEmitterScopeNoCheck();
   }
   EmitterScope* innermostEmitterScopeNoCheck() const {
     return innermostEmitterScope_;
   }
 
-  // Certain ops (yield, await, gosub) have an entry in the script's
-  // resumeOffsets list. This can be used to map from the op's resumeIndex to
-  // the bytecode offset of the next pc. This indirection makes it easy to
-  // resume in the JIT (because BaselineScript stores a resumeIndex => native
-  // code array).
-  CGResumeOffsetList resumeOffsetList;
-
   // Number of JOF_IC opcodes emitted.
   size_t numICEntries = 0;
 
-  // Number of yield instructions emitted. Does not include JSOP_AWAIT.
-  uint32_t numYields = 0;
-
   // Number of JOF_TYPESET opcodes generated.
   uint16_t typesetCount = 0;
 
   // Script contains singleton initializer JSOP_OBJECT.
   bool hasSingletons = false;
 
   // Script contains finally block.
   bool hasTryFinally = false;
--- a/js/src/frontend/ForOfLoopControl.cpp
+++ b/js/src/frontend/ForOfLoopControl.cpp
@@ -25,17 +25,17 @@ bool ForOfLoopControl::emitBeginCodeNeed
   tryCatch_.emplace(bce, TryEmitter::Kind::TryCatch,
                     TryEmitter::ControlKind::NonSyntactic);
 
   if (!tryCatch_->emitTry()) {
     return false;
   }
 
   MOZ_ASSERT(numYieldsAtBeginCodeNeedingIterClose_ == UINT32_MAX);
-  numYieldsAtBeginCodeNeedingIterClose_ = bce->numYields;
+  numYieldsAtBeginCodeNeedingIterClose_ = bce->bytecodeSection().numYields();
 
   return true;
 }
 
 bool ForOfLoopControl::emitEndCodeNeedingIteratorClose(BytecodeEmitter* bce) {
   if (!tryCatch_->emitCatch()) {
     //              [stack] ITER ...
     return false;
@@ -88,17 +88,17 @@ bool ForOfLoopControl::emitEndCodeNeedin
   if (!bce->emit1(JSOP_THROW)) {
     //              [stack] ITER ...
     return false;
   }
 
   // If any yields were emitted, then this for-of loop is inside a star
   // generator and must handle the case of Generator.return. Like in
   // yield*, it is handled with a finally block.
-  uint32_t numYieldsEmitted = bce->numYields;
+  uint32_t numYieldsEmitted = bce->bytecodeSection().numYields();
   if (numYieldsEmitted > numYieldsAtBeginCodeNeedingIterClose_) {
     if (!tryCatch_->emitFinally()) {
       return false;
     }
 
     InternalIfEmitter ifGeneratorClosing(bce);
     if (!bce->emit1(JSOP_ISGENCLOSING)) {
       //            [stack] ITER ... FTYPE FVALUE CLOSING
--- a/js/src/vm/JSScript.cpp
+++ b/js/src/vm/JSScript.cpp
@@ -3238,17 +3238,17 @@ PrivateScriptData* PrivateScriptData::ne
 
 /* static */ bool PrivateScriptData::InitFromEmitter(
     JSContext* cx, js::HandleScript script, frontend::BytecodeEmitter* bce) {
   uint32_t nscopes = bce->perScriptData().scopeList().length();
   uint32_t nconsts = bce->perScriptData().numberList().length();
   uint32_t nobjects = bce->perScriptData().objectList().length;
   uint32_t ntrynotes = bce->bytecodeSection().tryNoteList().length();
   uint32_t nscopenotes = bce->bytecodeSection().scopeNoteList().length();
-  uint32_t nresumeoffsets = bce->resumeOffsetList.length();
+  uint32_t nresumeoffsets = bce->bytecodeSection().resumeOffsetList().length();
 
   // Create and initialize PrivateScriptData
   if (!JSScript::createPrivateScriptData(cx, script, nscopes, nconsts, nobjects,
                                          ntrynotes, nscopenotes,
                                          nresumeoffsets)) {
     return false;
   }
 
@@ -3264,17 +3264,17 @@ PrivateScriptData* PrivateScriptData::ne
   }
   if (ntrynotes) {
     bce->bytecodeSection().tryNoteList().finish(data->tryNotes());
   }
   if (nscopenotes) {
     bce->bytecodeSection().scopeNoteList().finish(data->scopeNotes());
   }
   if (nresumeoffsets) {
-    bce->resumeOffsetList.finish(data->resumeOffsets());
+    bce->bytecodeSection().resumeOffsetList().finish(data->resumeOffsets());
   }
 
   return true;
 }
 
 void PrivateScriptData::trace(JSTracer* trc) {
   auto scopearray = scopes();
   TraceRange(trc, scopearray.size(), scopearray.data(), "scopes");