Bug 771378 (part 1) - Remove use of MUST_FLOW_THROUGH from BytecodeEmitter.cpp. r=jwalden.
authorNicholas Nethercote <nnethercote@mozilla.com>
Tue, 17 Jul 2012 16:36:50 -0700
changeset 99612 6d030947dffea35e52ba30a631e787a0d0186b86
parent 99611 fcba8ae674df875450cf3c94a527e775949d970f
child 99613 0b273f6a04af2e0dae8cfcbbedfd8b1e19ad2995
push id23140
push useremorley@mozilla.com
push dateWed, 18 Jul 2012 12:33:13 +0000
treeherdermozilla-central@134e66224b04 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwalden
bugs771378
milestone17.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 771378 (part 1) - Remove use of MUST_FLOW_THROUGH from BytecodeEmitter.cpp. r=jwalden.
js/src/frontend/BytecodeEmitter.cpp
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -2199,30 +2199,27 @@ SetJumpOffsetAt(BytecodeEmitter *bce, pt
  * Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr12127.
  * LLVM is deciding to inline this function which uses a lot of stack space
  * into EmitTree which is recursive and uses relatively little stack space.
  */
 MOZ_NEVER_INLINE static bool
 EmitSwitch(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
 {
     JSOp switchOp;
-    bool ok, hasDefault;
+    bool hasDefault;
     ptrdiff_t top, off, defaultOffset;
     ParseNode *pn2, *pn3, *pn4;
-    uint32_t caseCount, tableLength;
-    ParseNode **table;
     int32_t i, low, high;
     int noteIndex;
     size_t switchSize, tableSize;
     jsbytecode *pc;
     StmtInfoBCE stmtInfo(cx);
 
     /* Try for most optimal, fall back if not dense ints, and per ECMAv2. */
     switchOp = JSOP_TABLESWITCH;
-    ok = true;
     hasDefault = false;
     defaultOffset = -1;
 
     pn2 = pn->pn_right;
 #if JS_HAS_BLOCK_SCOPE
     /*
      * If there are hoisted let declarations, their stack slots go under the
      * discriminant's value so push their slots now and enter the block later.
@@ -2264,27 +2261,28 @@ EmitSwitch(JSContext *cx, BytecodeEmitte
          */
         stmtInfo.update = top = bce->offset();
 
         /* Advance pn2 to refer to the switch case list. */
         pn2 = pn2->expr();
     }
 #endif
 
-    caseCount = pn2->pn_count;
-    tableLength = 0;
-    table = NULL;
+    uint32_t caseCount = pn2->pn_count;
+    uint32_t tableLength = 0;
+    js::ScopedFreePtr<ParseNode*> table(NULL);
 
     if (caseCount == 0 ||
         (caseCount == 1 &&
          (hasDefault = (pn2->pn_head->isKind(PNK_DEFAULT))))) {
         caseCount = 0;
         low = 0;
         high = -1;
     } else {
+        bool ok = true;
 #define INTMAP_LENGTH   256
         jsbitmap intmap_space[INTMAP_LENGTH];
         jsbitmap *intmap = NULL;
         int32_t intmap_bitlen = 0;
 
         low  = JSVAL_INT_MAX;
         high = JSVAL_INT_MIN;
 
@@ -2505,18 +2503,17 @@ EmitSwitch(JSContext *cx, BytecodeEmitte
             /* Fill in switch bounds, which we know fit in 16-bit offsets. */
             SET_JUMP_OFFSET(pc, low);
             pc += JUMP_OFFSET_LEN;
             SET_JUMP_OFFSET(pc, high);
             pc += JUMP_OFFSET_LEN;
 
             /*
              * Use malloc to avoid arena bloat for programs with many switches.
-             * We free table if non-null at label out, so all control flow must
-             * exit this function through goto out or goto bad.
+             * ScopedFreePtr takes care of freeing it on exit.
              */
             if (tableLength != 0) {
                 tableSize = (size_t)tableLength * sizeof *table;
                 table = (ParseNode **) cx->malloc_(tableSize);
                 if (!table)
                     return false;
                 memset(table, 0, tableSize);
                 for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
@@ -2530,33 +2527,25 @@ EmitSwitch(JSContext *cx, BytecodeEmitte
             }
         } else {
             JS_ASSERT(switchOp == JSOP_LOOKUPSWITCH);
 
             /* Fill in the number of cases. */
             SET_UINT16(pc, caseCount);
             pc += UINT16_LEN;
         }
-
-        /*
-         * After this point, all control flow involving JSOP_TABLESWITCH
-         * must set ok and goto out to exit this function.  To keep things
-         * simple, all switchOp cases exit that way.
-         */
-        MUST_FLOW_THROUGH("out");
     }
 
     /* Emit code for each case's statements, copying pn_offset up to pn3. */
     for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
         if (switchOp == JSOP_CONDSWITCH && !pn3->isKind(PNK_DEFAULT))
             SetJumpOffsetAt(bce, pn3->pn_offset);
         pn4 = pn3->pn_right;
-        ok = EmitTree(cx, bce, pn4);
-        if (!ok)
-            goto out;
+        if (!EmitTree(cx, bce, pn4))
+            return false;
         pn3->pn_offset = pn4->pn_offset;
         if (pn3->isKind(PNK_DEFAULT))
             off = pn3->pn_offset - top;
     }
 
     if (!hasDefault) {
         /* If no default case, offset for default is to end of switch. */
         off = bce->offset() - top;
@@ -2573,19 +2562,18 @@ EmitSwitch(JSContext *cx, BytecodeEmitte
     } else {
         pc = bce->code(top);
         SET_JUMP_OFFSET(pc, off);
         pc += JUMP_OFFSET_LEN;
     }
 
     /* Set the SRC_SWITCH note's offset operand to tell end of switch. */
     off = bce->offset() - top;
-    ok = SetSrcNoteOffset(cx, bce, (unsigned)noteIndex, 0, off);
-    if (!ok)
-        goto out;
+    if (!SetSrcNoteOffset(cx, bce, (unsigned)noteIndex, 0, off))
+        return false;
 
     if (switchOp == JSOP_TABLESWITCH) {
         /* Skip over the already-initialized switch bounds. */
         pc += 2 * JUMP_OFFSET_LEN;
 
         /* Fill in the jump table, if there is one. */
         for (i = 0; i < (int)tableLength; i++) {
             pn3 = table[i];
@@ -2596,42 +2584,35 @@ EmitSwitch(JSContext *cx, BytecodeEmitte
     } else if (switchOp == JSOP_LOOKUPSWITCH) {
         /* Skip over the already-initialized number of cases. */
         pc += UINT16_LEN;
 
         for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
             if (pn3->isKind(PNK_DEFAULT))
                 continue;
             if (!bce->constList.append(*pn3->pn_pval))
-                goto bad;
+                return false;
             SET_UINT32_INDEX(pc, bce->constList.length() - 1);
             pc += UINT32_INDEX_LEN;
 
             off = pn3->pn_offset - top;
             SET_JUMP_OFFSET(pc, off);
             pc += JUMP_OFFSET_LEN;
         }
     }
 
-out:
-    if (table)
-        cx->free_(table);
-    if (ok) {
-        ok = PopStatementBCE(cx, bce);
+    if (!PopStatementBCE(cx, bce))
+        return false;
 
 #if JS_HAS_BLOCK_SCOPE
-        if (ok && pn->pn_right->isKind(PNK_LEXICALSCOPE))
-            EMIT_UINT16_IMM_OP(JSOP_LEAVEBLOCK, blockObjCount);
+    if (pn->pn_right->isKind(PNK_LEXICALSCOPE))
+        EMIT_UINT16_IMM_OP(JSOP_LEAVEBLOCK, blockObjCount);
 #endif
-    }
-    return ok;
-
-bad:
-    ok = false;
-    goto out;
+
+    return true;
 }
 
 bool
 frontend::EmitFunctionScript(JSContext *cx, BytecodeEmitter *bce, ParseNode *body)
 {
     /*
      * The decompiler has assumptions about what may occur immediately after
      * script->main (e.g., in the case of destructuring params). Thus, put the