Bug 1460126 - Part 2: Merge TryEmitter::{ShouldUseRetVal,ShouldUseControl} into TryEmitter::ControlKind. r=jwalden
authorTooru Fujisawa <arai_a@mac.com>
Thu, 31 May 2018 15:15:50 +0900
changeset 420671 e2aabb9c50162fc250cabbbfe9c6c69ecdede6b9
parent 420670 0ad0b4d1b0f34ca4a8059b2f814be317ea5865d5
child 420672 325ac4e5f005b00b3a9ec68b59cdb22180eb5725
push id34077
push usernerli@mozilla.com
push dateThu, 31 May 2018 21:51:59 +0000
treeherdermozilla-central@42880a726964 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwalden
bugs1460126
milestone62.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 1460126 - Part 2: Merge TryEmitter::{ShouldUseRetVal,ShouldUseControl} into TryEmitter::ControlKind. r=jwalden
js/src/frontend/BytecodeEmitter.cpp
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -1502,34 +1502,37 @@ BytecodeEmitter::TDZCheckCache::noteTDZC
     return true;
 }
 
 // Class for emitting bytecode for blocks like try-catch-finally.
 //
 // Usage: (check for the return value is omitted for simplicity)
 //
 //   `try { try_block } catch (ex) { catch_block }`
-//     TryEmitter tryCatch(this, TryEmitter::Kind::TryCatch);
+//     TryEmitter tryCatch(this, TryEmitter::Kind::TryCatch,
+//                         TryEmitter::ControlKind::Syntactic);
 //     tryCatch.emitTry();
 //     emit(try_block);
 //     tryCatch.emitCatch();
 //     emit(ex and catch_block); // use JSOP_EXCEPTION to get exception
 //     tryCatch.emitEnd();
 //
 //   `try { try_block } finally { finally_block }`
-//     TryEmitter tryCatch(this, TryEmitter::Kind::TryFinally);
+//     TryEmitter tryCatch(this, TryEmitter::Kind::TryFinally,
+//                         TryEmitter::ControlKind::Syntactic);
 //     tryCatch.emitTry();
 //     emit(try_block);
 //     // finally_pos: The "{" character's position in the source code text.
 //     tryCatch.emitFinally(Some(finally_pos));
 //     emit(finally_block);
 //     tryCatch.emitEnd();
 //
 //   `try { try_block } catch (ex) {catch_block} finally { finally_block }`
-//     TryEmitter tryCatch(this, TryEmitter::Kind::TryCatchFinally);
+//     TryEmitter tryCatch(this, TryEmitter::Kind::TryCatchFinally,
+//                         TryEmitter::ControlKind::Syntactic);
 //     tryCatch.emitTry();
 //     emit(try_block);
 //     tryCatch.emitCatch();
 //     emit(ex and catch_block);
 //     tryCatch.emitFinally(Some(finally_pos));
 //     emit(finally_block);
 //     tryCatch.emitEnd();
 //
@@ -1537,21 +1540,27 @@ class MOZ_STACK_CLASS TryEmitter
 {
   public:
     enum class Kind {
         TryCatch,
         TryCatchFinally,
         TryFinally
     };
 
-    // Whether the catch and finally blocks handle the frame's return value.
-    // If UseRetVal is specified, the bytecode marked with "*" are emitted
-    // to clear return value with `undefined` before the catch block and the
-    // finally block, and also to save/restore the return value before/after
-    // the finally block.
+    // Syntactic try-catch-finally and internally used non-syntactic
+    // try-catch-finally behave differently for 2 points.
+    //
+    // The first one is whether TryFinallyControl is used or not.
+    // See the comment for `controlInfo_`.
+    //
+    // The second one is whether the catch and finally blocks handle the frame's
+    // return value.  For syntactic try-catch-finally, the bytecode marked with
+    // "*" are emitted to clear return value with `undefined` before the catch
+    // block and the finally block, and also to save/restore the return value
+    // before/after the finally block.
     //
     //     JSOP_TRY
     //
     //     try_body...
     //
     //     JSOP_GOSUB finally
     //     JSOP_JUMPTARGET
     //     JSOP_GOTO end:
@@ -1576,57 +1585,45 @@ class MOZ_STACK_CLASS TryEmitter
     //     finally_body...
     //
     //   * JSOP_SETRVAL
     //     JSOP_NOP
     //
     //   end:
     //     JSOP_JUMPTARGET
     //
-    // For syntactic try-catch-finally, UseRetVal should be used.
-    // For non-syntactic try-catch-finally, DontUseRetVal should be used.
-    enum ShouldUseRetVal {
-        UseRetVal,
-        DontUseRetVal
-    };
-
-    // Whether this class should use TryFinallyControl.
-    // See the comment for `controlInfo_`.
-    //
-    // For syntactic try-catch-finally, UseControl should be used.
-    // For non-syntactic try-catch-finally, DontUseControl should be used.
-    enum ShouldUseControl {
-        UseControl,
-        DontUseControl,
+    // For syntactic try-catch-finally, Syntactic should be used.
+    // For non-syntactic try-catch-finally, NonSyntactic should be used.
+    enum class ControlKind {
+        Syntactic,
+        NonSyntactic
     };
 
   private:
     BytecodeEmitter* bce_;
     Kind kind_;
-    ShouldUseRetVal retValKind_;
+    ControlKind controlKind_;
 
     // Track jumps-over-catches and gosubs-to-finally for later fixup.
     //
     // When a finally block is active, non-local jumps (including
     // jumps-over-catches) result in a GOSUB being written into the bytecode
     // stream and fixed-up later.
     //
-    // If ShouldUseControl is DontUseControl, all that handling is skipped.
-    // DontUseControl is used by yield* and the internal try-catch around
-    // IteratorClose. These internal uses must:
+    // For non-syntactic try-catch-finally, all that handling is skipped.
+    // The non-syntactic try-catch-finally must:
     //   * have only one catch block
     //   * have JSOP_GOTO at the end of catch-block
     //   * have no non-local-jump
     //   * don't use finally block for normal completion of try-block and
     //     catch-block
     //
-    // Additionally, a finally block may be emitted when ShouldUseControl is
-    // DontUseControl, even if the kind is not TryCatchFinally or TryFinally,
-    // because GOSUBs are not emitted. This internal use shares the
-    // requirements as above.
+    // Additionally, a finally block may be emitted for non-syntactic
+    // try-catch-finally, even if the kind is TryCatch, because GOSUBs are not
+    // emitted.
     Maybe<TryFinallyControl> controlInfo_;
 
     // The stack depth before emitting JSOP_TRY.
     int depth_;
 
     // The source note index for SRC_TRY.
     unsigned noteIndex_;
 
@@ -1674,27 +1671,26 @@ class MOZ_STACK_CLASS TryEmitter
     bool hasCatch() const {
         return kind_ == Kind::TryCatch || kind_ == Kind::TryCatchFinally;
     }
     bool hasFinally() const {
         return kind_ == Kind::TryCatchFinally || kind_ == Kind::TryFinally;
     }
 
   public:
-    TryEmitter(BytecodeEmitter* bce, Kind kind, ShouldUseRetVal retValKind = UseRetVal,
-               ShouldUseControl controlKind = UseControl)
+    TryEmitter(BytecodeEmitter* bce, Kind kind, ControlKind controlKind)
       : bce_(bce),
         kind_(kind),
-        retValKind_(retValKind),
+        controlKind_(controlKind),
         depth_(0),
         noteIndex_(0),
         tryStart_(0),
         state_(State::Start)
     {
-        if (controlKind == UseControl)
+        if (controlKind_ == ControlKind::Syntactic)
             controlInfo_.emplace(bce_, hasFinally() ? StatementKind::Finally : StatementKind::Try);
         finallyStart_.offset = 0;
     }
 
     // Emits JSOP_GOTO to the end of try-catch-finally.
     // Used in `yield*`.
     bool emitJumpOverCatchAndFinally() {
         if (!bce_->emitJump(JSOP_GOTO, &catchAndFinallyJump_))
@@ -1753,17 +1749,17 @@ class MOZ_STACK_CLASS TryEmitter
   public:
     bool emitCatch() {
         MOZ_ASSERT(state_ == State::Try);
         if (!emitTryEnd())
             return false;
 
         MOZ_ASSERT(bce_->stackDepth == depth_);
 
-        if (retValKind_ == UseRetVal) {
+        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;
             if (!bce_->emit1(JSOP_SETRVAL))
                 return false;
@@ -1797,19 +1793,20 @@ class MOZ_STACK_CLASS TryEmitter
   public:
     // If `finallyPos` is specified, it's an offset of the finally block's
     // "{" character in the source code text, to improve line:column number in
     // the error reporting.
     // For non-syntactic try-catch-finally, `finallyPos` can be omitted.
     bool emitFinally(const Maybe<uint32_t>& finallyPos = Nothing()) {
         // If we are using controlInfo_ (i.e., emitting a syntactic try
         // blocks), we must have specified up front if there will be a finally
-        // close. For internal try blocks, like those emitted for yield* and
-        // IteratorClose inside for-of loops, we can emitFinally even without
-        // specifying up front, since the internal try blocks emit no GOSUBs.
+        // close. For internal non-syntactic try blocks, like those emitted for
+        // yield* and IteratorClose inside for-of loops, we can emitFinally even
+        // without specifying up front, since the internal non-syntactic try
+        // blocks emit no GOSUBs.
         if (!controlInfo_) {
             if (kind_ == Kind::TryCatch)
                 kind_ = Kind::TryCatchFinally;
         } else {
             MOZ_ASSERT(hasFinally());
         }
 
         if (state_ == State::Try) {
@@ -1836,17 +1833,17 @@ class MOZ_STACK_CLASS TryEmitter
         }
         if (finallyPos) {
             if (!bce_->updateSourceCoordNotes(finallyPos.value()))
                 return false;
         }
         if (!bce_->emit1(JSOP_FINALLY))
             return false;
 
-        if (retValKind_ == UseRetVal) {
+        if (controlKind_ == ControlKind::Syntactic) {
             if (!bce_->emit1(JSOP_GETRVAL))
                 return false;
 
             // Clear the frame's return value to make break/continue return
             // correct value even if there's no other statement before them:
             //
             //   eval("x: try { 1 } finally { break x; }"); // undefined, not 1
             if (!bce_->emit1(JSOP_UNDEFINED))
@@ -1858,17 +1855,17 @@ class MOZ_STACK_CLASS TryEmitter
         state_ = State::Finally;
         return true;
     }
 
   private:
     bool emitFinallyEnd() {
         MOZ_ASSERT(state_ == State::Finally);
 
-        if (retValKind_ == UseRetVal) {
+        if (controlKind_ == ControlKind::Syntactic) {
             if (!bce_->emit1(JSOP_SETRVAL))
                 return false;
         }
 
         if (!bce_->emit1(JSOP_RETSUB))
             return false;
 
         bce_->hasTryFinally = true;
@@ -2258,18 +2255,17 @@ class ForOfLoopControl : public LoopCont
         iterDepth_(iterDepth),
         numYieldsAtBeginCodeNeedingIterClose_(UINT32_MAX),
         allowSelfHosted_(allowSelfHosted),
         iterKind_(iterKind)
     {
     }
 
     bool emitBeginCodeNeedingIteratorClose(BytecodeEmitter* bce) {
-        tryCatch_.emplace(bce, TryEmitter::Kind::TryCatch, TryEmitter::DontUseRetVal,
-                          TryEmitter::DontUseControl);
+        tryCatch_.emplace(bce, TryEmitter::Kind::TryCatch, TryEmitter::ControlKind::NonSyntactic);
 
         if (!tryCatch_->emitTry())
             return false;
 
         MOZ_ASSERT(numYieldsAtBeginCodeNeedingIterClose_ == UINT32_MAX);
         numYieldsAtBeginCodeNeedingIterClose_ = bce->yieldAndAwaitOffsetList.numYields;
 
         return true;
@@ -5531,18 +5527,17 @@ BytecodeEmitter::emitIteratorCloseInScop
     // Call "return" if it is not undefined or null, and check that it returns
     // an Object.
     if (!emit1(JSOP_SWAP))                                // ... RET ITER
         return false;
 
     Maybe<TryEmitter> tryCatch;
 
     if (completionKind == CompletionKind::Throw) {
-        tryCatch.emplace(this, TryEmitter::Kind::TryCatch, TryEmitter::DontUseRetVal,
-                         TryEmitter::DontUseControl);
+        tryCatch.emplace(this, TryEmitter::Kind::TryCatch, TryEmitter::ControlKind::NonSyntactic);
 
         // Mutate stack to balance stack for try-catch.
         if (!emit1(JSOP_UNDEFINED))                       // ... RET ITER UNDEF
             return false;
         if (!tryCatch->emitTry())                         // ... RET ITER UNDEF
             return false;
         if (!emitDupAt(2))                                // ... RET ITER UNDEF RET
             return false;
@@ -6867,17 +6862,17 @@ BytecodeEmitter::emitTry(ParseNode* pn)
         if (finallyNode)
             kind = TryEmitter::Kind::TryCatchFinally;
         else
             kind = TryEmitter::Kind::TryCatch;
     } else {
         MOZ_ASSERT(finallyNode);
         kind = TryEmitter::Kind::TryFinally;
     }
-    TryEmitter tryCatch(this, kind);
+    TryEmitter tryCatch(this, kind, TryEmitter::ControlKind::Syntactic);
 
     if (!tryCatch.emitTry())
         return false;
 
     if (!emitTree(pn->pn_kid1))
         return false;
 
     // If this try has a catch block, emit it.
@@ -8613,18 +8608,18 @@ BytecodeEmitter::emitYieldStar(ParseNode
     // Initial send value is undefined.
     if (!emit1(JSOP_UNDEFINED))                           // NEXT ITER RECEIVED
         return false;
 
     int32_t savedDepthTemp;
     int32_t startDepth = stackDepth;
     MOZ_ASSERT(startDepth >= 3);
 
-    TryEmitter tryCatch(this, TryEmitter::Kind::TryCatchFinally, TryEmitter::DontUseRetVal,
-                        TryEmitter::DontUseControl);
+    TryEmitter tryCatch(this, TryEmitter::Kind::TryCatchFinally,
+                        TryEmitter::ControlKind::NonSyntactic);
     if (!tryCatch.emitJumpOverCatchAndFinally())          // NEXT ITER RESULT
         return false;
 
     JumpTarget tryStart{ offset() };
     if (!tryCatch.emitTry())                              // NEXT ITER RESULT
         return false;
 
     MOZ_ASSERT(this->stackDepth == startDepth);