Bug 1459845 - Part 4: Add IfThenElseEmitter::emitElseIf to clarify cascading else-if blocks. r=Yoric
authorTooru Fujisawa <arai_a@mac.com>
Thu, 31 May 2018 15:15:49 +0900
changeset 420667 31606aa882a925c60bcbef04d09910ba979d1ac4
parent 420666 1bf4b8c47cbef84ebac166046f5e61ec71cb7962
child 420668 901ab55af4f3c894f658a79ef25f1bf54654ee18
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)
reviewersYoric
bugs1459845
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 1459845 - Part 4: Add IfThenElseEmitter::emitElseIf to clarify cascading else-if blocks. r=Yoric
js/src/frontend/BytecodeEmitter.cpp
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -1942,21 +1942,21 @@ class MOZ_STACK_CLASS TryEmitter
 //     emit(else_block);
 //     ifThenElse.emitEnd();
 //
 //   `if (c1) b1 else if (c2) b2 else if (c3) b3 else b4`
 //     IfThenElseEmitter ifThenElse(this);
 //     emit(c1);
 //     ifThenElse.emitIfElse();
 //     emit(b1);
-//     ifThenElse.emitElse();
+//     ifThenElse.emitElseIf();
 //     emit(c2);
 //     ifThenElse.emitIfElse();
 //     emit(b2);
-//     ifThenElse.emitElse();
+//     ifThenElse.emitElseIf();
 //     emit(c3);
 //     ifThenElse.emitIfElse();
 //     emit(b3);
 //     ifThenElse.emitElse();
 //     emit(b4);
 //     ifThenElse.emitEnd();
 //
 //   `cond ? then_expr : else_expr`
@@ -1987,47 +1987,54 @@ class MOZ_STACK_CLASS IfThenElseEmitter
 #ifdef DEBUG
     // The number of values pushed in the then and else blocks.
     int32_t pushed_;
     bool calculatedPushed_;
 #endif
 
     // The state of this emitter.
     //
-    // +-------+   emitCond +------+ emitElse +------+      emitEnd +-----+
-    // | Start |-+--------->| Cond |--------->| Else |---->+------->| End |
-    // +-------+ |          +------+          +------+     ^        +-----+
-    //           |                                         |
-    //           v emitIf +----+                           |
-    //        +->+------->| If |-------------------------->+
-    //        ^  |        +----+                           ^
-    //        |  |                                         |
-    //        |  |                                         |
-    //        |  |                                         |
-    //        |  | emitIfElse +--------+ emitElse +------+ |
-    //        |  +----------->| IfElse |--------->| Else |-+
-    //        |               +--------+          +------+ |
-    //        |                                            |
-    //        +--------------------------------------------+
+    // +-------+   emitCond +------+ emitElse +------+        emitEnd +-----+
+    // | Start |-+--------->| Cond |--------->| Else |------>+------->| End |
+    // +-------+ |          +------+          +------+       ^        +-----+
+    //           |                                           |
+    //           v emitIf +----+                             |
+    //        +->+------->| If |---------------------------->+
+    //        ^  |        +----+                             ^
+    //        |  |                                           |
+    //        |  |                                           |
+    //        |  |                                           |
+    //        |  | emitIfElse +--------+   emitElse +------+ |
+    //        |  +----------->| IfElse |-+--------->| Else |-+
+    //        |               +--------+ |          +------+
+    //        |                          |
+    //        |                          | emitElseIf +--------+
+    //        |                          +----------->| ElseIf |-+
+    //        |                                       +--------+ |
+    //        |                                                  |
+    //        +--------------------------------------------------+
     enum class State {
         // The initial state.
         Start,
 
         // After calling emitIf.
         If,
 
         // After calling emitCond.
         Cond,
 
         // After calling emitIfElse.
         IfElse,
 
         // After calling emitElse.
         Else,
 
+        // After calling emitElseIf.
+        ElseIf,
+
         // After calling emitEnd.
         End
     };
     State state_;
 
   public:
     explicit IfThenElseEmitter(BytecodeEmitter* bce)
       : bce_(bce),
@@ -2038,39 +2045,26 @@ class MOZ_STACK_CLASS IfThenElseEmitter
 #endif
         state_(State::Start)
     {}
 
     ~IfThenElseEmitter()
     {}
 
   private:
-    MOZ_MUST_USE bool emitIf(State nextState) {
-        MOZ_ASSERT(state_ == State::Start || state_ == State::Else);
-        MOZ_ASSERT(nextState == State::If || nextState == State::IfElse ||
-                   nextState == State::Cond);
-
-        // Clear jumpAroundThen_ offset that points previous JSOP_IFEQ.
-        if (state_ == State::Else)
-            jumpAroundThen_ = JumpList();
+    MOZ_MUST_USE bool emitIfInternal(State nextState, SrcNoteType type) {
+        MOZ_ASSERT_IF(state_ == State::Start,
+                      nextState == State::If ||
+                      nextState == State::IfElse ||
+                      nextState == State::Cond);
+        MOZ_ASSERT_IF(state_ == State::ElseIf,
+                      nextState == State::If ||
+                      nextState == State::IfElse);
 
         // Emit an annotated branch-if-false around the then part.
-        SrcNoteType type;
-        switch (nextState) {
-          case State::If:
-            type = SRC_IF;
-            break;
-          case State::IfElse:
-            type = SRC_IF_ELSE;
-            break;
-          default:
-            MOZ_ASSERT(nextState == State::Cond);
-            type = SRC_COND;
-            break;
-        }
         if (!bce_->newSrcNote(type))
             return false;
         if (!bce_->emitJump(JSOP_IFEQ, &jumpAroundThen_))
             return false;
 
         // To restore stack depth in else part, save depth of the then part.
 #ifdef DEBUG
         // If DEBUG, this is also necessary to calculate |pushed_|.
@@ -2091,25 +2085,28 @@ class MOZ_STACK_CLASS IfThenElseEmitter
         } else {
             MOZ_ASSERT(pushed_ == bce_->stackDepth - thenDepth_);
         }
 #endif
     }
 
   public:
     MOZ_MUST_USE bool emitIf() {
-        return emitIf(State::If);
+        MOZ_ASSERT(state_ == State::Start || state_ == State::ElseIf);
+        return emitIfInternal(State::If, SRC_IF);
     }
 
     MOZ_MUST_USE bool emitCond() {
-        return emitIf(State::Cond);
+        MOZ_ASSERT(state_ == State::Start);
+        return emitIfInternal(State::Cond, SRC_COND);
     }
 
     MOZ_MUST_USE bool emitIfElse() {
-        return emitIf(State::IfElse);
+        MOZ_ASSERT(state_ == State::Start || state_ == State::ElseIf);
+        return emitIfInternal(State::IfElse, SRC_IF_ELSE);
     }
 
     MOZ_MUST_USE bool emitElse() {
         MOZ_ASSERT(state_ == State::IfElse || state_ == State::Cond);
 
         calculateOrCheckPushed();
 
         // Emit a jump from the end of our then part around the else part. The
@@ -2123,16 +2120,29 @@ class MOZ_STACK_CLASS IfThenElseEmitter
             return false;
 
         // Restore stack depth of the then part.
         bce_->stackDepth = thenDepth_;
         state_ = State::Else;
         return true;
     }
 
+    MOZ_MUST_USE bool emitElseIf() {
+        MOZ_ASSERT(state_ == State::IfElse);
+
+        if (!emitElse())
+            return false;
+
+        // Clear jumpAroundThen_ offset that points previous JSOP_IFEQ.
+        jumpAroundThen_ = JumpList();
+        state_ = State::ElseIf;
+
+        return true;
+    }
+
     MOZ_MUST_USE bool emitEnd() {
         MOZ_ASSERT(state_ == State::If || state_ == State::Else);
 
         calculateOrCheckPushed();
 
         if (state_ == State::If) {
             // No else part, fixup the branch-if-false to come here.
             if (!bce_->emitJumpTargetAndPatch(jumpAroundThen_))
@@ -6896,24 +6906,28 @@ BytecodeEmitter::emitIf(ParseNode* pn)
             return false;
     }
 
     /* Emit code for the then part. */
     if (!emitTreeInBranch(pn->pn_kid2))
         return false;
 
     if (elseNode) {
-        if (!ifThenElse.emitElse())
-            return false;
-
         if (elseNode->isKind(ParseNodeKind::If)) {
             pn = elseNode;
+
+            if (!ifThenElse.emitElseIf())
+                return false;
+
             goto if_again;
         }
 
+        if (!ifThenElse.emitElse())
+            return false;
+
         /* Emit code for the else part. */
         if (!emitTreeInBranch(elseNode))
             return false;
     }
 
     if (!ifThenElse.emitEnd())
         return false;