Bug 1143704 part 13 - Make emitJump, emitN etc return bool instead of ptrdiff_t. r=luke
authorJan de Mooij <jdemooij@mozilla.com>
Tue, 24 Mar 2015 09:45:22 +0100
changeset 265806 5e2113e373009f9a0aa9ac48d26e061fbf1521ee
parent 265805 ff0c37c1837b67bf5129ef2a7d189664c848d8de
child 265807 b6044f33b3e438638270ee9f981227d5b2710be2
push id830
push userraliiev@mozilla.com
push dateFri, 19 Jun 2015 19:24:37 +0000
treeherdermozilla-release@932614382a68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs1143704
milestone39.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 1143704 part 13 - Make emitJump, emitN etc return bool instead of ptrdiff_t. r=luke
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/BytecodeEmitter.h
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -183,32 +183,31 @@ BytecodeEmitter::updateLocalsToFrameSlot
     }
 
     for (size_t i = 0; i < script->bindings.numBlockScoped(); i++)
         localsToFrameSlots_.infallibleAppend(slot++);
 
     return true;
 }
 
-ptrdiff_t
-BytecodeEmitter::emitCheck(ptrdiff_t delta)
-{
-    ptrdiff_t offset = code().length();
+bool
+BytecodeEmitter::emitCheck(ptrdiff_t delta, ptrdiff_t *offset)
+{
+    *offset = code().length();
 
     // Start it off moderately large to avoid repeated resizings early on.
     // ~98% of cases fit within 1024 bytes.
     if (code().capacity() == 0 && !code().reserve(1024))
-        return -1;
-
-    jsbytecode dummy = 0;
-    if (!code().appendN(dummy, delta)) {
+        return false;
+
+    if (!code().growBy(delta)) {
         ReportOutOfMemory(cx);
-        return -1;
-    }
-    return offset;
+        return false;
+    }
+    return true;
 }
 
 void
 BytecodeEmitter::updateDepth(ptrdiff_t target)
 {
     jsbytecode *pc = code(target);
     JSOp op = (JSOp) *pc;
     const JSCodeSpec *cs = &js_CodeSpec[op];
@@ -245,32 +244,34 @@ BytecodeEmitter::checkStrictOrSloppy(JSO
     return true;
 }
 #endif
 
 bool
 BytecodeEmitter::emit1(JSOp op)
 {
     MOZ_ASSERT(checkStrictOrSloppy(op));
-    ptrdiff_t offset = emitCheck(1);
-    if (offset < 0)
+
+    ptrdiff_t offset;
+    if (!emitCheck(1, &offset))
         return false;
 
     jsbytecode *code = this->code(offset);
     code[0] = jsbytecode(op);
     updateDepth(offset);
     return true;
 }
 
 bool
 BytecodeEmitter::emit2(JSOp op, jsbytecode op1)
 {
     MOZ_ASSERT(checkStrictOrSloppy(op));
-    ptrdiff_t offset = emitCheck(2);
-    if (offset < 0)
+
+    ptrdiff_t offset;
+    if (!emitCheck(2, &offset))
         return false;
 
     jsbytecode *code = this->code(offset);
     code[0] = jsbytecode(op);
     code[1] = op1;
     updateDepth(offset);
     return true;
 }
@@ -279,63 +280,68 @@ bool
 BytecodeEmitter::emit3(JSOp op, jsbytecode op1, jsbytecode op2)
 {
     MOZ_ASSERT(checkStrictOrSloppy(op));
 
     /* These should filter through emitVarOp. */
     MOZ_ASSERT(!IsArgOp(op));
     MOZ_ASSERT(!IsLocalOp(op));
 
-    ptrdiff_t offset = emitCheck(3);
-    if (offset < 0)
+    ptrdiff_t offset;
+    if (!emitCheck(3, &offset))
         return false;
 
     jsbytecode *code = this->code(offset);
     code[0] = jsbytecode(op);
     code[1] = op1;
     code[2] = op2;
     updateDepth(offset);
     return true;
 }
 
-ptrdiff_t
-BytecodeEmitter::emitN(JSOp op, size_t extra)
+bool
+BytecodeEmitter::emitN(JSOp op, size_t extra, ptrdiff_t *offset)
 {
     MOZ_ASSERT(checkStrictOrSloppy(op));
-    ptrdiff_t length = 1 + (ptrdiff_t)extra;
-    ptrdiff_t offset = emitCheck(length);
-    if (offset < 0)
-        return -1;
-
-    jsbytecode *code = this->code(offset);
+    ptrdiff_t length = 1 + ptrdiff_t(extra);
+
+    ptrdiff_t off;
+    if (!emitCheck(length, &off))
+        return false;
+
+    jsbytecode *code = this->code(off);
     code[0] = jsbytecode(op);
     /* The remaining |extra| bytes are set by the caller */
 
     /*
      * Don't updateDepth if op's use-count comes from the immediate
      * operand yet to be stored in the extra bytes after op.
      */
     if (js_CodeSpec[op].nuses >= 0)
-        updateDepth(offset);
-
-    return offset;
-}
-
-ptrdiff_t
-BytecodeEmitter::emitJump(JSOp op, ptrdiff_t off)
-{
-    ptrdiff_t offset = emitCheck(5);
-    if (offset < 0)
-        return -1;
+        updateDepth(off);
+
+    if (offset)
+        *offset = off;
+    return true;
+}
+
+bool
+BytecodeEmitter::emitJump(JSOp op, ptrdiff_t off, ptrdiff_t *jumpOffset)
+{
+    ptrdiff_t offset;
+    if (!emitCheck(5, &offset))
+        return false;
 
     jsbytecode *code = this->code(offset);
     code[0] = jsbytecode(op);
     SET_JUMP_OFFSET(code, off);
     updateDepth(offset);
-    return offset;
+    if (jumpOffset)
+        *jumpOffset = offset;
+    return true;
 }
 
 bool
 BytecodeEmitter::emitCall(JSOp op, uint16_t argc, ParseNode *pn)
 {
     if (pn && !updateSourceCoordNotes(pn->pn_pos.begin))
         return false;
     return emit3(op, ARGC_HI(argc), ARGC_LO(argc));
@@ -348,18 +354,18 @@ BytecodeEmitter::emitDupAt(unsigned slot
 
     // The slot's position on the operand stack, measured from the top.
     unsigned slotFromTop = stackDepth - 1 - slot;
     if (slotFromTop >= JS_BIT(24)) {
         reportError(nullptr, JSMSG_TOO_MANY_LOCALS);
         return false;
     }
 
-    ptrdiff_t off = emitN(JSOP_DUPAT, 3);
-    if (off < 0)
+    ptrdiff_t off;
+    if (!emitN(JSOP_DUPAT, 3, &off))
         return false;
 
     jsbytecode *pc = code(off);
     SET_UINT24(pc, slotFromTop);
     return true;
 }
 
 /* XXX too many "... statement" L10N gaffes below -- fix via js.msg! */
@@ -409,17 +415,17 @@ ReportStatementTooLarge(TokenStream &ts,
  * so that we can walk back up the chain fixing up the op and jump offset.
  */
 bool
 BytecodeEmitter::emitBackPatchOp(ptrdiff_t *lastp)
 {
     ptrdiff_t delta = offset() - *lastp;
     *lastp = offset();
     MOZ_ASSERT(delta > 0);
-    return emitJump(JSOP_BACKPATCH, delta) >= 0;
+    return emitJump(JSOP_BACKPATCH, delta);
 }
 
 static inline unsigned
 LengthOfSetLine(unsigned line)
 {
     return 1 /* SN_SETLINE */ + (line > SN_4BYTE_OFFSET_MASK ? 4 : 1);
 }
 
@@ -668,32 +674,30 @@ NonLocalExitScope::prepareForNonLocalJum
     FLUSH_POPS();
     return true;
 
 #undef FLUSH_POPS
 }
 
 }  // anonymous namespace
 
-ptrdiff_t
+bool
 BytecodeEmitter::emitGoto(StmtInfoBCE *toStmt, ptrdiff_t *lastp, SrcNoteType noteType)
 {
     NonLocalExitScope nle(this);
 
     if (!nle.prepareForNonLocalJump(toStmt))
-        return -1;
+        return false;
 
     if (noteType != SRC_NULL) {
         if (newSrcNote(noteType) < 0)
-            return -1;
-    }
-
-    if (!emitBackPatchOp(lastp))
-        return -1;
-    return *lastp;
+            return false;
+    }
+
+    return emitBackPatchOp(lastp);
 }
 
 void
 BytecodeEmitter::backPatch(ptrdiff_t last, jsbytecode *target, jsbytecode op)
 {
     jsbytecode *pc = code(last);
     jsbytecode *stop = code(-1);
     while (pc != stop) {
@@ -988,18 +992,18 @@ BytecodeEmitter::leaveNestedScope(StmtIn
 bool
 BytecodeEmitter::emitIndex32(JSOp op, uint32_t index)
 {
     MOZ_ASSERT(checkStrictOrSloppy(op));
 
     const size_t len = 1 + UINT32_INDEX_LEN;
     MOZ_ASSERT(len == size_t(js_CodeSpec[op].length));
 
-    ptrdiff_t offset = emitCheck(len);
-    if (offset < 0)
+    ptrdiff_t offset;
+    if (!emitCheck(len, &offset))
         return false;
 
     jsbytecode *code = this->code(offset);
     code[0] = jsbytecode(op);
     SET_UINT32_INDEX(code, index);
     updateDepth(offset);
     checkTypeSet(op);
     return true;
@@ -1008,18 +1012,18 @@ BytecodeEmitter::emitIndex32(JSOp op, ui
 bool
 BytecodeEmitter::emitIndexOp(JSOp op, uint32_t index)
 {
     MOZ_ASSERT(checkStrictOrSloppy(op));
 
     const size_t len = js_CodeSpec[op].length;
     MOZ_ASSERT(len >= 1 + UINT32_INDEX_LEN);
 
-    ptrdiff_t offset = emitCheck(len);
-    if (offset < 0)
+    ptrdiff_t offset;
+    if (!emitCheck(len, &offset))
         return false;
 
     jsbytecode *code = this->code(offset);
     code[0] = jsbytecode(op);
     SET_UINT32_INDEX(code, index);
     updateDepth(offset);
     checkTypeSet(op);
     return true;
@@ -1082,18 +1086,18 @@ BytecodeEmitter::emitRegExp(uint32_t ind
 }
 
 bool
 BytecodeEmitter::emitLocalOp(JSOp op, uint32_t slot)
 {
     MOZ_ASSERT(JOF_OPTYPE(op) != JOF_SCOPECOORD);
     MOZ_ASSERT(IsLocalOp(op));
 
-    ptrdiff_t off = emitN(op, LOCALNO_LEN);
-    if (off < 0)
+    ptrdiff_t off;
+    if (!emitN(op, LOCALNO_LEN, &off))
         return false;
 
     SET_LOCALNO(code(off), slot);
     return true;
 }
 
 bool
 BytecodeEmitter::emitUnaliasedVarOp(JSOp op, uint32_t slot, MaybeCheckLexical checkLexical)
@@ -1112,34 +1116,34 @@ BytecodeEmitter::emitUnaliasedVarOp(JSOp
             if (!emitLocalOp(JSOP_CHECKLEXICAL, slot))
                 return false;
         }
 
         return emitLocalOp(op, slot);
     }
 
     MOZ_ASSERT(IsArgOp(op));
-    ptrdiff_t off = emitN(op, ARGNO_LEN);
-    if (off < 0)
+    ptrdiff_t off;
+    if (!emitN(op, ARGNO_LEN, &off))
         return false;
 
     SET_ARGNO(code(off), slot);
     return true;
 }
 
 bool
 BytecodeEmitter::emitScopeCoordOp(JSOp op, ScopeCoordinate sc)
 {
     MOZ_ASSERT(JOF_OPTYPE(op) == JOF_SCOPECOORD);
 
     unsigned n = SCOPECOORD_HOPS_LEN + SCOPECOORD_SLOT_LEN;
     MOZ_ASSERT(int(n) + 1 /* op */ == js_CodeSpec[op].length);
 
-    ptrdiff_t off = emitN(op, n);
-    if (off < 0)
+    ptrdiff_t off;
+    if (!emitN(op, n, &off))
         return false;
 
     jsbytecode *pc = code(off);
     SET_SCOPECOORD_HOPS(pc, sc.hops());
     pc += SCOPECOORD_HOPS_LEN;
     SET_SCOPECOORD_SLOT(pc, sc.slot());
     pc += SCOPECOORD_SLOT_LEN;
     checkTypeSet(op);
@@ -2159,18 +2163,18 @@ BytecodeEmitter::reportStrictModeError(P
     va_end(args);
     return result;
 }
 
 bool
 BytecodeEmitter::emitNewInit(JSProtoKey key)
 {
     const size_t len = 1 + UINT32_INDEX_LEN;
-    ptrdiff_t offset = emitCheck(len);
-    if (offset < 0)
+    ptrdiff_t offset;
+    if (!emitCheck(len, &offset))
         return false;
 
     jsbytecode *code = this->code(offset);
     code[0] = JSOP_NEWINIT;
     code[1] = jsbytecode(key);
     code[2] = 0;
     code[3] = 0;
     code[4] = 0;
@@ -2502,43 +2506,37 @@ BytecodeEmitter::emitElemIncDec(ParseNod
 
     return true;
 }
 
 bool
 BytecodeEmitter::emitNumberOp(double dval)
 {
     int32_t ival;
-    uint32_t u;
-    ptrdiff_t off;
-    jsbytecode *pc;
-
     if (NumberIsInt32(dval, &ival)) {
         if (ival == 0)
             return emit1(JSOP_ZERO);
         if (ival == 1)
             return emit1(JSOP_ONE);
         if ((int)(int8_t)ival == ival)
             return emit2(JSOP_INT8, (jsbytecode)(int8_t)ival);
 
-        u = (uint32_t)ival;
+        uint32_t u = uint32_t(ival);
         if (u < JS_BIT(16)) {
             emitUint16Operand(JSOP_UINT16, u);
         } else if (u < JS_BIT(24)) {
-            off = emitN(JSOP_UINT24, 3);
-            if (off < 0)
-                return false;
-            pc = code(off);
-            SET_UINT24(pc, u);
+            ptrdiff_t off;
+            if (!emitN(JSOP_UINT24, 3, &off))
+                return false;
+            SET_UINT24(code(off), u);
         } else {
-            off = emitN(JSOP_INT32, 4);
-            if (off < 0)
-                return false;
-            pc = code(off);
-            SET_INT32(pc, ival);
+            ptrdiff_t off;
+            if (!emitN(JSOP_INT32, 4, &off))
+                return false;
+            SET_INT32(code(off), ival);
         }
         return true;
     }
 
     if (!constList.append(DoubleValue(dval)))
         return false;
 
     return emitIndex32(JSOP_DOUBLE, constList.length() - 1);
@@ -2775,17 +2773,17 @@ BytecodeEmitter::emitSwitch(ParseNode *p
         /* 3 offsets (len, low, high) before the table, 1 per entry. */
         switchSize = (size_t)(JUMP_OFFSET_LEN * (3 + tableLength));
         noteIndex = newSrcNote2(SRC_TABLESWITCH, 0);
     }
     if (noteIndex < 0)
         return false;
 
     /* Emit switchOp followed by switchSize bytes of jump or lookup table. */
-    if (emitN(switchOp, switchSize) < 0)
+    if (!emitN(switchOp, switchSize))
         return false;
 
     off = -1;
     if (switchOp == JSOP_CONDSWITCH) {
         int caseNoteIndex = -1;
         bool beforeCases = true;
 
         /* Emit code for evaluating cases and jumping to case statements. */
@@ -2800,18 +2798,17 @@ BytecodeEmitter::emitSwitch(ParseNode *p
             }
             if (!pn4) {
                 MOZ_ASSERT(pn3->isKind(PNK_DEFAULT));
                 continue;
             }
             caseNoteIndex = newSrcNote2(SRC_NEXTCASE, 0);
             if (caseNoteIndex < 0)
                 return false;
-            off = emitJump(JSOP_CASE, 0);
-            if (off < 0)
+            if (!emitJump(JSOP_CASE, 0, &off))
                 return false;
             pn3->pn_offset = off;
             if (beforeCases) {
                 unsigned noteCount, noteCountDelta;
 
                 /* Switch note's second offset is to first JSOP_CASE. */
                 noteCount = notes().length();
                 if (!setSrcNoteOffset(unsigned(noteIndex), 1, off - top))
@@ -2832,18 +2829,17 @@ BytecodeEmitter::emitSwitch(ParseNode *p
         if (!hasDefault &&
             caseNoteIndex >= 0 &&
             !setSrcNoteOffset(unsigned(caseNoteIndex), 0, offset() - off))
         {
             return false;
         }
 
         /* Emit default even if no explicit default statement. */
-        defaultOffset = emitJump(JSOP_DEFAULT, 0);
-        if (defaultOffset < 0)
+        if (!emitJump(JSOP_DEFAULT, 0, &defaultOffset))
             return false;
     } else {
         MOZ_ASSERT(switchOp == JSOP_TABLESWITCH);
         pc = code(top + JUMP_OFFSET_LEN);
 
         /* Fill in switch bounds, which we know fit in 16-bit offsets. */
         SET_JUMP_OFFSET(pc, low);
         pc += JUMP_OFFSET_LEN;
@@ -2958,18 +2954,18 @@ BytecodeEmitter::isRunOnceLambda()
 bool
 BytecodeEmitter::emitYieldOp(JSOp op)
 {
     if (op == JSOP_FINALYIELDRVAL)
         return emit1(JSOP_FINALYIELDRVAL);
 
     MOZ_ASSERT(op == JSOP_INITIALYIELD || op == JSOP_YIELD);
 
-    ptrdiff_t off = emitN(op, 3);
-    if (off < 0)
+    ptrdiff_t off;
+    if (!emitN(op, 3, &off))
         return false;
 
     uint32_t yieldIndex = yieldOffsetList.length();
     if (yieldIndex >= JS_BIT(24)) {
         reportError(nullptr, JSMSG_TOO_MANY_YIELDS);
         return false;
     }
 
@@ -3380,18 +3376,18 @@ BytecodeEmitter::emitDefault(ParseNode *
         return false;
     if (!emit1(JSOP_UNDEFINED))                           // VALUE VALUE UNDEFINED
         return false;
     if (!emit1(JSOP_STRICTEQ))                            // VALUE EQL?
         return false;
     // Emit source note to enable ion compilation.
     if (newSrcNote(SRC_IF) < 0)
         return false;
-    ptrdiff_t jump = emitJump(JSOP_IFEQ, 0);              // VALUE
-    if (jump < 0)
+    ptrdiff_t jump;
+    if (!emitJump(JSOP_IFEQ, 0, &jump))                   // VALUE
         return false;
     if (!emit1(JSOP_POP))                                 // .
         return false;
     if (!emitTree(defaultExpr))                           // DEFAULTVALUE
         return false;
     setJumpOffsetAt(jump);
     return true;
 }
@@ -3425,18 +3421,18 @@ BytecodeEmitter::emitDestructuringOpsArr
         ParseNode *elem = member;
         if (elem->isKind(PNK_ASSIGN)) {
             pndefault = elem->pn_right;
             elem = elem->pn_left;
         }
 
         if (elem->isKind(PNK_SPREAD)) {
             /* Create a new array with the rest of the iterator */
-            ptrdiff_t off = emitN(JSOP_NEWARRAY, 3);              // ... OBJ? ITER ARRAY
-            if (off < 0)
+            ptrdiff_t off;
+            if (!emitN(JSOP_NEWARRAY, 3, &off))                   // ... OBJ? ITER ARRAY
                 return false;
             checkTypeSet(JSOP_NEWARRAY);
             jsbytecode *pc = code(off);
             SET_UINT24(pc, 0);
 
             if (!emitNumberOp(0))                                 // ... OBJ? ITER ARRAY INDEX
                 return false;
             if (!emitSpread())                                    // ... OBJ? ARRAY INDEX
@@ -3450,33 +3446,33 @@ BytecodeEmitter::emitDestructuringOpsArr
             if (!emitIteratorNext(pattern))                       // ... OBJ? ITER RESULT
                 return false;
             if (!emit1(JSOP_DUP))                                 // ... OBJ? ITER RESULT RESULT
                 return false;
             if (!emitAtomOp(cx->names().done, JSOP_GETPROP))      // ... OBJ? ITER RESULT DONE?
                 return false;
 
             // Emit (result.done ? undefined : result.value)
-            // This is mostly copied from EmitConditionalExpression, except that this code
+            // This is mostly copied from emitConditionalExpression, except that this code
             // does not push new values onto the stack.
             ptrdiff_t noteIndex = newSrcNote(SRC_COND);
             if (noteIndex < 0)
                 return false;
-            ptrdiff_t beq = emitJump(JSOP_IFEQ, 0);
-            if (beq < 0)
+            ptrdiff_t beq;
+            if (!emitJump(JSOP_IFEQ, 0, &beq))
                 return false;
 
             if (!emit1(JSOP_POP))                                 // ... OBJ? ITER
                 return false;
             if (!emit1(JSOP_UNDEFINED))                           // ... OBJ? ITER UNDEFINED
                 return false;
 
             /* Jump around else, fixup the branch, emit else, fixup jump. */
-            ptrdiff_t jmp = emitJump(JSOP_GOTO, 0);
-            if (jmp < 0)
+            ptrdiff_t jmp;
+            if (!emitJump(JSOP_GOTO, 0, &jmp))
                 return false;
             setJumpOffsetAt(beq);
 
             if (!emitAtomOp(cx->names().value, JSOP_GETPROP))     // ... OBJ? ITER VALUE
                 return false;
 
             setJumpOffsetAt(jmp);
             if (!setSrcNoteOffset(noteIndex, 0, jmp - beq))
@@ -4327,35 +4323,35 @@ BytecodeEmitter::emitCatch(ParseNode *pn
     // catch block if the guard expression is false.
     if (pn->pn_kid2) {
         if (!emitTree(pn->pn_kid2))
             return false;
 
         // If the guard expression is false, fall through, pop the block scope,
         // and jump to the next catch block.  Otherwise jump over that code and
         // pop the dupped exception.
-        ptrdiff_t guardCheck = emitJump(JSOP_IFNE, 0);
-        if (guardCheck < 0)
+        ptrdiff_t guardCheck;
+        if (!emitJump(JSOP_IFNE, 0, &guardCheck))
             return false;
 
         {
             NonLocalExitScope nle(this);
 
             // Move exception back to cx->exception to prepare for
             // the next catch.
             if (!emit1(JSOP_THROWING))
                 return false;
 
             // Leave the scope for this catch block.
             if (!nle.prepareForNonLocalJump(stmt))
                 return false;
 
             // Jump to the next handler.  The jump target is backpatched by emitTry.
-            ptrdiff_t guardJump = emitJump(JSOP_GOTO, 0);
-            if (guardJump < 0)
+            ptrdiff_t guardJump;
+            if (!emitJump(JSOP_GOTO, 0, &guardJump))
                 return false;
             stmt->guardJump() = guardJump;
         }
 
         // Back to normal control flow.
         setJumpOffsetAt(guardCheck);
 
         // Pop duplicated exception object as we no longer need it.
@@ -4566,36 +4562,35 @@ BytecodeEmitter::emitIf(ParseNode *pn)
             return false;
     }
 
     /* Emit an annotated branch-if-false around the then part. */
     ParseNode *pn3 = pn->pn_kid3;
     noteIndex = newSrcNote(pn3 ? SRC_IF_ELSE : SRC_IF);
     if (noteIndex < 0)
         return false;
-    beq = emitJump(JSOP_IFEQ, 0);
-    if (beq < 0)
+    if (!emitJump(JSOP_IFEQ, 0, &beq))
         return false;
 
     /* Emit code for the then and optional else parts. */
     if (!emitTree(pn->pn_kid2))
         return false;
     if (pn3) {
         /* Modify stmtInfo so we know we're in the else part. */
         stmtInfo.type = STMT_ELSE;
 
         /*
          * Emit a JSOP_BACKPATCH op to jump from the end of our then part
          * around the else part.  The popStatement call at the bottom of
          * this function will fix up the backpatch chain linked from
          * stmtInfo.breaks.
          */
-        jmp = emitGoto(&stmtInfo, &stmtInfo.breaks);
-        if (jmp < 0)
-            return false;
+        if (!emitGoto(&stmtInfo, &stmtInfo.breaks))
+            return false;
+        jmp = stmtInfo.breaks;
 
         /* Ensure the branch-if-false comes here, then emit the else. */
         setJumpOffsetAt(beq);
         if (pn3->isKind(PNK_IF)) {
             pn = pn3;
             goto if_again;
         }
 
@@ -4813,18 +4808,18 @@ BytecodeEmitter::emitForOf(StmtType type
     pushLoopStatement(&stmtInfo, type, top);
 
     // Jump down to the loop condition to minimize overhead assuming at least
     // one iteration, as the other loop forms do.  Annotate so IonMonkey can
     // find the loop-closing jump.
     int noteIndex = newSrcNote(SRC_FOR_OF);
     if (noteIndex < 0)
         return false;
-    ptrdiff_t jmp = emitJump(JSOP_GOTO, 0);
-    if (jmp < 0)
+    ptrdiff_t jmp;
+    if (!emitJump(JSOP_GOTO, 0, &jmp))
         return false;
 
     top = offset();
     SET_STATEMENT_TOP(&stmtInfo, top);
     if (!emitLoopHead(nullptr))
         return false;
 
     if (type == STMT_SPREAD)
@@ -4884,18 +4879,18 @@ BytecodeEmitter::emitForOf(StmtType type
     }
     if (!emitIteratorNext(forHead))                       // ... RESULT
         return false;
     if (!emit1(JSOP_DUP))                                 // ... RESULT RESULT
         return false;
     if (!emitAtomOp(cx->names().done, JSOP_GETPROP))      // ... RESULT DONE?
         return false;
 
-    ptrdiff_t beq = emitJump(JSOP_IFEQ, top - offset());  // ... RESULT
-    if (beq < 0)
+    ptrdiff_t beq;
+    if (!emitJump(JSOP_IFEQ, top - offset(), &beq))       // ... RESULT
         return false;
 
     MOZ_ASSERT(this->stackDepth == loopDepth);
 
     // Let Ion know where the closing jump of this loop is.
     if (!setSrcNoteOffset(unsigned(noteIndex), 0, beq - jmp))
         return false;
 
@@ -4965,18 +4960,18 @@ BytecodeEmitter::emitForIn(ParseNode *pn
     int noteIndex = newSrcNote(SRC_FOR_IN);
     if (noteIndex < 0)
         return false;
 
     /*
      * Jump down to the loop condition to minimize overhead assuming at
      * least one iteration, as the other loop forms do.
      */
-    ptrdiff_t jmp = emitJump(JSOP_GOTO, 0);
-    if (jmp < 0)
+    ptrdiff_t jmp;
+    if (!emitJump(JSOP_GOTO, 0, &jmp))
         return false;
 
     top = offset();
     SET_STATEMENT_TOP(&stmtInfo, top);
     if (!emitLoopHead(nullptr))
         return false;
 
 #ifdef DEBUG
@@ -5008,18 +5003,18 @@ BytecodeEmitter::emitForIn(ParseNode *pn
     if (!emitLoopEntry(nullptr))
         return false;
     if (!emit1(JSOP_POP))
         return false;
     if (!emit1(JSOP_MOREITER))
         return false;
     if (!emit1(JSOP_ISNOITER))
         return false;
-    ptrdiff_t beq = emitJump(JSOP_IFEQ, top - offset());
-    if (beq < 0)
+    ptrdiff_t beq;
+    if (!emitJump(JSOP_IFEQ, top - offset(), &beq))
         return false;
 
     /* Set the srcnote offset so we can find the closing jump. */
     if (!setSrcNoteOffset(unsigned(noteIndex), 0, beq - jmp))
         return false;
 
     // Fix up breaks and continues.
     popStatement();
@@ -5075,18 +5070,17 @@ BytecodeEmitter::emitNormalFor(ParseNode
     int noteIndex = newSrcNote(SRC_FOR);
     if (noteIndex < 0 || !emit1(op))
         return false;
     ptrdiff_t tmp = offset();
 
     ptrdiff_t jmp = -1;
     if (forHead->pn_kid2) {
         /* Goto the loop condition, which branches back to iterate. */
-        jmp = emitJump(JSOP_GOTO, 0);
-        if (jmp < 0)
+        if (!emitJump(JSOP_GOTO, 0, &jmp))
             return false;
     } else {
         if (op != JSOP_NOP && !emit1(JSOP_NOP))
             return false;
     }
 
     top = offset();
     SET_STATEMENT_TOP(&stmtInfo, top);
@@ -5151,17 +5145,17 @@ BytecodeEmitter::emitNormalFor(ParseNode
     if (!setSrcNoteOffset(unsigned(noteIndex), 1, tmp2 - tmp))
         return false;
     /* The third note offset helps us find the loop-closing jump. */
     if (!setSrcNoteOffset(unsigned(noteIndex), 2, offset() - tmp))
         return false;
 
     /* If no loop condition, just emit a loop-closing jump. */
     op = forHead->pn_kid2 ? JSOP_IFNE : JSOP_GOTO;
-    if (emitJump(op, top - offset()) < 0)
+    if (!emitJump(op, top - offset()))
         return false;
 
     if (!tryNoteList.append(JSTRY_LOOP, stackDepth, top, offset()))
         return false;
 
     /* Now fixup all breaks and continues. */
     popStatement();
     return true;
@@ -5363,18 +5357,18 @@ BytecodeEmitter::emitDo(ParseNode *pn)
     do {
         stmt->update = off;
     } while ((stmt = stmt->down) != nullptr && stmt->type == STMT_LABEL);
 
     /* Compile the loop condition, now that continues know where to go. */
     if (!emitTree(pn->pn_right))
         return false;
 
-    ptrdiff_t beq = emitJump(JSOP_IFNE, top - offset());
-    if (beq < 0)
+    ptrdiff_t beq;
+    if (!emitJump(JSOP_IFNE, top - offset(), &beq))
         return false;
 
     if (!tryNoteList.append(JSTRY_LOOP, stackDepth, top, offset()))
         return false;
 
     /*
      * Update the annotations with the update and back edge positions, for
      * IonBuilder.
@@ -5409,35 +5403,35 @@ BytecodeEmitter::emitWhile(ParseNode *pn
      */
     LoopStmtInfo stmtInfo(cx);
     pushLoopStatement(&stmtInfo, STMT_WHILE_LOOP, top);
 
     ptrdiff_t noteIndex = newSrcNote(SRC_WHILE);
     if (noteIndex < 0)
         return false;
 
-    ptrdiff_t jmp = emitJump(JSOP_GOTO, 0);
-    if (jmp < 0)
+    ptrdiff_t jmp;
+    if (!emitJump(JSOP_GOTO, 0, &jmp))
         return false;
 
     top = offset();
     if (!emitLoopHead(pn->pn_right))
         return false;
 
     if (!emitTree(pn->pn_right))
         return false;
 
     setJumpOffsetAt(jmp);
     if (!emitLoopEntry(pn->pn_left))
         return false;
     if (!emitTree(pn->pn_left))
         return false;
 
-    ptrdiff_t beq = emitJump(JSOP_IFNE, top - offset());
-    if (beq < 0)
+    ptrdiff_t beq;
+    if (!emitJump(JSOP_IFNE, top - offset(), &beq))
         return false;
 
     if (!tryNoteList.append(JSTRY_LOOP, stackDepth, top, offset()))
         return false;
 
     if (!setSrcNoteOffset(noteIndex, 0, beq - jmp))
         return false;
 
@@ -5455,17 +5449,17 @@ BytecodeEmitter::emitBreak(PropertyName 
             stmt = stmt->down;
         noteType = SRC_BREAK2LABEL;
     } else {
         while (!stmt->isLoop() && stmt->type != STMT_SWITCH)
             stmt = stmt->down;
         noteType = (stmt->type == STMT_SWITCH) ? SRC_SWITCHBREAK : SRC_BREAK;
     }
 
-    return emitGoto(stmt, &stmt->breaks, noteType) >= 0;
+    return emitGoto(stmt, &stmt->breaks, noteType);
 }
 
 bool
 BytecodeEmitter::emitContinue(PropertyName *label)
 {
     StmtInfoBCE *stmt = topStmt;
     if (label) {
         /* Find the loop statement enclosed by the matching label. */
@@ -5476,17 +5470,17 @@ BytecodeEmitter::emitContinue(PropertyNa
             stmt = stmt->down;
         }
         stmt = loop;
     } else {
         while (!stmt->isLoop())
             stmt = stmt->down;
     }
 
-    return emitGoto(stmt, &stmt->continues, SRC_CONTINUE) >= 0;
+    return emitGoto(stmt, &stmt->continues, SRC_CONTINUE);
 }
 
 bool
 BytecodeEmitter::inTryBlockWithFinally()
 {
     for (StmtInfoBCE *stmt = topStmt; stmt; stmt = stmt->down) {
         if (stmt->type == STMT_FINALLY)
             return true;
@@ -5683,18 +5677,18 @@ BytecodeEmitter::emitYieldStar(ParseNode
         return false;
     if (!emitAtomOp(cx->names().throw_, JSOP_STRING))            // EXCEPTION ITER ITER "throw"
         return false;
     if (!emit1(JSOP_SWAP))                                       // EXCEPTION ITER "throw" ITER
         return false;
     if (!emit1(JSOP_IN))                                         // EXCEPTION ITER THROW?
         return false;
     // if (THROW?) goto delegate
-    ptrdiff_t checkThrow = emitJump(JSOP_IFNE, 0);               // EXCEPTION ITER
-    if (checkThrow < 0)
+    ptrdiff_t checkThrow;
+    if (!emitJump(JSOP_IFNE, 0, &checkThrow))                    // EXCEPTION ITER
         return false;
     if (!emit1(JSOP_POP))                                        // EXCEPTION
         return false;
     if (!emit1(JSOP_THROW))                                      // throw EXCEPTION
         return false;
 
     setJumpOffsetAt(checkThrow);                                 // delegate:
     // RESULT = ITER.throw(EXCEPTION)                            // EXCEPTION ITER
@@ -5752,17 +5746,17 @@ BytecodeEmitter::emitYieldStar(ParseNode
     backPatch(checkResult, code().end(), JSOP_GOTO);             // checkResult:
 
     // if (!result.done) goto tryStart;                          // ITER RESULT
     if (!emit1(JSOP_DUP))                                        // ITER RESULT RESULT
         return false;
     if (!emitAtomOp(cx->names().done, JSOP_GETPROP))             // ITER RESULT DONE
         return false;
     // if (!DONE) goto tryStart;
-    if (emitJump(JSOP_IFEQ, tryStart - offset()) < 0)            // ITER RESULT
+    if (!emitJump(JSOP_IFEQ, tryStart - offset()))               // ITER RESULT
         return false;
 
     // result.value
     if (!emit1(JSOP_SWAP))                                       // RESULT ITER
         return false;
     if (!emit1(JSOP_POP))                                        // RESULT
         return false;
     if (!emitAtomOp(cx->names().value, JSOP_GETPROP))            // VALUE
@@ -6177,29 +6171,29 @@ BytecodeEmitter::emitLogical(ParseNode *
      * JSOP_AND converts the operand on the stack to boolean and jumps if false;
      * otherwise it falls into the right operand's bytecode.
      */
 
     /* Left-associative operator chain: avoid too much recursion. */
     ParseNode *pn2 = pn->pn_head;
     if (!emitTree(pn2))
         return false;
-    ptrdiff_t top = emitJump(JSOP_BACKPATCH, 0);
-    if (top < 0)
+    ptrdiff_t top;
+    if (!emitJump(JSOP_BACKPATCH, 0, &top))
         return false;
     if (!emit1(JSOP_POP))
         return false;
 
     /* Emit nodes between the head and the tail. */
     ptrdiff_t jmp = top;
     while ((pn2 = pn2->pn_next)->pn_next) {
         if (!emitTree(pn2))
             return false;
-        ptrdiff_t off = emitJump(JSOP_BACKPATCH, 0);
-        if (off < 0)
+        ptrdiff_t off;
+        if (!emitJump(JSOP_BACKPATCH, 0, &off))
             return false;
         if (!emit1(JSOP_POP))
             return false;
         SET_JUMP_OFFSET(code(jmp), off - jmp);
         jmp = off;
     }
     if (!emitTree(pn2))
         return false;
@@ -6304,18 +6298,18 @@ BytecodeEmitter::emitLabeledStatement(co
     /*
      * Emit a JSOP_LABEL instruction. The argument is the offset to the statement
      * following the labeled statement.
      */
     jsatomid index;
     if (!makeAtomIndex(pn->label(), &index))
         return false;
 
-    ptrdiff_t top = emitJump(JSOP_LABEL, 0);
-    if (top < 0)
+    ptrdiff_t top;
+    if (!emitJump(JSOP_LABEL, 0, &top))
         return false;
 
     /* Emit code for the labeled statement. */
     StmtInfoBCE stmtInfo(cx);
     pushStatement(&stmtInfo, STMT_LABEL, offset());
     stmtInfo.label = pn->label();
 
     if (!emitTree(pn->statement()))
@@ -6355,23 +6349,26 @@ BytecodeEmitter::emitConditionalExpressi
     /* Emit the condition, then branch if false to the else part. */
     if (!emitTree(&conditional.condition()))
         return false;
 
     ptrdiff_t noteIndex = newSrcNote(SRC_COND);
     if (noteIndex < 0)
         return false;
 
-    ptrdiff_t beq = emitJump(JSOP_IFEQ, 0);
-    if (beq < 0 || !emitTree(&conditional.thenExpression()))
+    ptrdiff_t beq;
+    if (!emitJump(JSOP_IFEQ, 0, &beq))
+        return false;
+
+    if (!emitTree(&conditional.thenExpression()))
         return false;
 
     /* Jump around else, fixup the branch, emit else, fixup jump. */
-    ptrdiff_t jmp = emitJump(JSOP_GOTO, 0);
-    if (jmp < 0)
+    ptrdiff_t jmp;
+    if (!emitJump(JSOP_GOTO, 0, &jmp))
         return false;
     setJumpOffsetAt(beq);
 
     /*
      * Because each branch pushes a single value, but our stack budgeting
      * analysis ignores branches, we now have to adjust this->stackDepth to
      * ignore the value pushed by the first branch.  Execution will follow
      * only one path, so we must decrement this->stackDepth.
@@ -6594,18 +6591,18 @@ BytecodeEmitter::emitArray(ParseNode *pn
      */
 
     int32_t nspread = 0;
     for (ParseNode *elt = pn; elt; elt = elt->pn_next) {
         if (elt->isKind(PNK_SPREAD))
             nspread++;
     }
 
-    ptrdiff_t off = emitN(JSOP_NEWARRAY, 3);                        // ARRAY
-    if (off < 0)
+    ptrdiff_t off;
+    if (!emitN(JSOP_NEWARRAY, 3, &off))                             // ARRAY
         return false;
     checkTypeSet(JSOP_NEWARRAY);
     jsbytecode *pc = code(off);
 
     // For arrays with spread, this is a very pessimistic allocation, the
     // minimum possible final size.
     SET_UINT24(pc, count - nspread);
 
@@ -6636,18 +6633,17 @@ BytecodeEmitter::emitArray(ParseNode *pn
             if (!emit2(JSOP_PICK, (jsbytecode)2))                        // ITER ARRAY INDEX
                 return false;
             if (!emitSpread())                                           // ARRAY INDEX
                 return false;
         } else if (afterSpread) {
             if (!emit1(JSOP_INITELEM_INC))
                 return false;
         } else {
-            off = emitN(JSOP_INITELEM_ARRAY, 3);
-            if (off < 0)
+            if (!emitN(JSOP_INITELEM_ARRAY, 3, &off))
                 return false;
             SET_UINT24(code(off), atomIndex);
         }
     }
     MOZ_ASSERT(atomIndex == count);
     if (afterSpread) {
         if (!emit1(JSOP_POP))                                            // ARRAY
             return false;
@@ -6692,18 +6688,18 @@ BytecodeEmitter::emitDefaults(ParseNode 
             return false;
         if (!emit1(JSOP_UNDEFINED))
             return false;
         if (!emit1(JSOP_STRICTEQ))
             return false;
         // Emit source note to enable ion compilation.
         if (newSrcNote(SRC_IF) < 0)
             return false;
-        ptrdiff_t jump = emitJump(JSOP_IFEQ, 0);
-        if (jump < 0)
+        ptrdiff_t jump;
+        if (!emitJump(JSOP_IFEQ, 0, &jump))
             return false;
         if (!emitTree(arg->expr()))
             return false;
         if (!emitVarOp(arg, JSOP_SETARG))
             return false;
         if (!emit1(JSOP_POP))
             return false;
         SET_JUMP_OFFSET(code(jump), offset() - jump);
--- a/js/src/frontend/BytecodeEmitter.h
+++ b/js/src/frontend/BytecodeEmitter.h
@@ -362,17 +362,17 @@ struct BytecodeEmitter
     // In a function, block-scoped locals go after the vars, and form part of the
     // fixed part of a stack frame.  Outside a function, there are no fixed vars,
     // but block-scoped locals still form part of the fixed part of a stack frame
     // and are thus addressable via GETLOCAL and friends.
     void computeLocalOffset(Handle<StaticBlockObject *> blockObj);
 
     bool flushPops(int *npops);
 
-    ptrdiff_t emitCheck(ptrdiff_t delta);
+    bool emitCheck(ptrdiff_t delta, ptrdiff_t *offset);
 
     // Emit one bytecode.
     bool emit1(JSOp op);
 
     // Emit two bytecodes, an opcode (op) with a byte of immediate operand
     // (op1).
     bool emit2(JSOp op, jsbytecode op1);
 
@@ -391,33 +391,33 @@ struct BytecodeEmitter
     // frame).
     bool emitDupAt(unsigned slot);
 
     // Emit a bytecode followed by an uint16 immediate operand stored in
     // big-endian order.
     bool emitUint16Operand(JSOp op, uint32_t i);
 
     // Emit (1 + extra) bytecodes, for N bytes of op and its immediate operand.
-    ptrdiff_t emitN(JSOp op, size_t extra);
+    bool emitN(JSOp op, size_t extra, ptrdiff_t *offset = nullptr);
 
     bool emitNumberOp(double dval);
 
-    ptrdiff_t emitJump(JSOp op, ptrdiff_t off);
+    bool emitJump(JSOp op, ptrdiff_t off, ptrdiff_t *jumpOffset = nullptr);
     bool emitCall(JSOp op, uint16_t argc, ParseNode *pn = nullptr);
 
     bool emitLoopHead(ParseNode *nextpn);
     bool emitLoopEntry(ParseNode *nextpn);
 
     // Emit a backpatch op with offset pointing to the previous jump of this
     // type, so that we can walk back up the chain fixing up the op and jump
     // offset.
     bool emitBackPatchOp(ptrdiff_t *lastp);
     void backPatch(ptrdiff_t last, jsbytecode *target, jsbytecode op);
 
-    ptrdiff_t emitGoto(StmtInfoBCE *toStmt, ptrdiff_t *lastp, SrcNoteType noteType = SRC_NULL);
+    bool emitGoto(StmtInfoBCE *toStmt, ptrdiff_t *lastp, SrcNoteType noteType = SRC_NULL);
 
     bool emitIndex32(JSOp op, uint32_t index);
     bool emitIndexOp(JSOp op, uint32_t index);
 
     bool emitAtomOp(JSAtom *atom, JSOp op);
     bool emitAtomOp(ParseNode *pn, JSOp op);
 
     bool emitArray(ParseNode *pn, uint32_t count);