Bug 1143704 part 11 - Move more functions into BytecodeEmitter. r=jorendorff
authorJan de Mooij <jdemooij@mozilla.com>
Sat, 21 Mar 2015 12:55:54 +0100
changeset 265232 787394ba34a2a5bbe0ca9f540fff066f79bed3db
parent 265231 af3aa3ee5b4168a90a32cb2d395bfe15c79c2d19
child 265233 ac4464790ec4896a5188fa50cfc69ae0ffeddc08
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)
reviewersjorendorff
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 11 - Move more functions into BytecodeEmitter. r=jorendorff
js/src/frontend/BytecodeCompiler.cpp
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/BytecodeEmitter.h
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -371,17 +371,17 @@ frontend::CompileScript(ExclusiveContext
                 pn = parser.statement();
             }
             if (!pn) {
                 MOZ_ASSERT(!parser.hadAbortedSyntaxParse());
                 return nullptr;
             }
         }
 
-        // Accumulate the maximum block scope depth, so that EmitTree can assert
+        // Accumulate the maximum block scope depth, so that emitTree can assert
         // when emitting JSOP_GETLOCAL that the local is indeed within the fixed
         // part of the stack frame.
         script->bindings.updateNumBlockScoped(pc->blockScopeDepth);
 
         if (canHaveDirectives) {
             if (!parser.maybeParseDirective(/* stmtList = */ nullptr, pn, &canHaveDirectives))
                 return nullptr;
         }
@@ -390,17 +390,17 @@ frontend::CompileScript(ExclusiveContext
             return nullptr;
 
         if (!NameFunctions(cx, pn))
             return nullptr;
 
         if (!bce.updateLocalsToFrameSlots())
             return nullptr;
 
-        if (!EmitTree(cx, &bce, pn))
+        if (!bce.emitTree(pn))
             return nullptr;
 
         parser.handler.freeTree(pn);
     }
 
     if (!MaybeCheckEvalFreeVariables(cx, evalCaller, scopeChain, parser, *pc))
         return nullptr;
 
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -48,22 +48,16 @@ using namespace js;
 using namespace js::gc;
 using namespace js::frontend;
 
 using mozilla::DebugOnly;
 using mozilla::NumberIsInt32;
 using mozilla::PodCopy;
 using mozilla::UniquePtr;
 
-static bool
-SetSrcNoteOffset(ExclusiveContext *cx, BytecodeEmitter *bce, unsigned index, unsigned which, ptrdiff_t offset);
-
-static bool
-UpdateSourceCoordNotes(ExclusiveContext *cx, BytecodeEmitter *bce, uint32_t offset);
-
 struct frontend::StmtInfoBCE : public StmtInfoBase
 {
     StmtInfoBCE     *down;          /* info for enclosing statement */
     StmtInfoBCE     *downScope;     /* next enclosing lexical scope */
 
     ptrdiff_t       update;         /* loop update offset (top if none) */
     ptrdiff_t       breaks;         /* offset of last break in loop */
     ptrdiff_t       continues;      /* offset of last continue in loop */
@@ -211,42 +205,42 @@ BytecodeEmitter::emitCheck(ptrdiff_t del
     jsbytecode dummy = 0;
     if (!code().appendN(dummy, delta)) {
         ReportOutOfMemory(cx);
         return -1;
     }
     return offset;
 }
 
-static void
-UpdateDepth(ExclusiveContext *cx, BytecodeEmitter *bce, ptrdiff_t target)
-{
-    jsbytecode *pc = bce->code(target);
+void
+BytecodeEmitter::updateDepth(ptrdiff_t target)
+{
+    jsbytecode *pc = code(target);
     JSOp op = (JSOp) *pc;
     const JSCodeSpec *cs = &js_CodeSpec[op];
 
     if (cs->format & JOF_TMPSLOT_MASK) {
         /*
          * An opcode may temporarily consume stack space during execution.
          * Account for this in maxStackDepth separately from uses/defs here.
          */
-        uint32_t depth = (uint32_t) bce->stackDepth +
+        uint32_t depth = (uint32_t) stackDepth +
                          ((cs->format & JOF_TMPSLOT_MASK) >> JOF_TMPSLOT_SHIFT);
-        if (depth > bce->maxStackDepth)
-            bce->maxStackDepth = depth;
+        if (depth > maxStackDepth)
+            maxStackDepth = depth;
     }
 
     int nuses = StackUses(nullptr, pc);
     int ndefs = StackDefs(nullptr, pc);
 
-    bce->stackDepth -= nuses;
-    MOZ_ASSERT(bce->stackDepth >= 0);
-    bce->stackDepth += ndefs;
-    if ((uint32_t)bce->stackDepth > bce->maxStackDepth)
-        bce->maxStackDepth = bce->stackDepth;
+    stackDepth -= nuses;
+    MOZ_ASSERT(stackDepth >= 0);
+    stackDepth += ndefs;
+    if ((uint32_t)stackDepth > maxStackDepth)
+        maxStackDepth = stackDepth;
 }
 
 #ifdef DEBUG
 static bool
 CheckStrictOrSloppy(BytecodeEmitter *bce, JSOp op)
 {
     if (IsCheckStrictOp(op) && !bce->sc->strict())
         return false;
@@ -261,32 +255,32 @@ BytecodeEmitter::emit1(JSOp op)
 {
     MOZ_ASSERT(CheckStrictOrSloppy(this, op));
     ptrdiff_t offset = emitCheck(1);
     if (offset < 0)
         return false;
 
     jsbytecode *code = this->code(offset);
     code[0] = jsbytecode(op);
-    UpdateDepth(cx, this, offset);
+    updateDepth(offset);
     return true;
 }
 
 bool
 BytecodeEmitter::emit2(JSOp op, jsbytecode op1)
 {
     MOZ_ASSERT(CheckStrictOrSloppy(this, op));
     ptrdiff_t offset = emitCheck(2);
     if (offset < 0)
         return false;
 
     jsbytecode *code = this->code(offset);
     code[0] = jsbytecode(op);
     code[1] = op1;
-    UpdateDepth(cx, this, offset);
+    updateDepth(offset);
     return true;
 }
 
 bool
 BytecodeEmitter::emit3(JSOp op, jsbytecode op1, jsbytecode op2)
 {
     MOZ_ASSERT(CheckStrictOrSloppy(this, op));
 
@@ -297,17 +291,17 @@ BytecodeEmitter::emit3(JSOp op, jsbyteco
     ptrdiff_t offset = emitCheck(3);
     if (offset < 0)
         return false;
 
     jsbytecode *code = this->code(offset);
     code[0] = jsbytecode(op);
     code[1] = op1;
     code[2] = op2;
-    UpdateDepth(cx, this, offset);
+    updateDepth(offset);
     return true;
 }
 
 ptrdiff_t
 BytecodeEmitter::emitN(JSOp op, size_t extra)
 {
     MOZ_ASSERT(CheckStrictOrSloppy(this, op));
     ptrdiff_t length = 1 + (ptrdiff_t)extra;
@@ -315,43 +309,43 @@ BytecodeEmitter::emitN(JSOp op, size_t e
     if (offset < 0)
         return -1;
 
     jsbytecode *code = this->code(offset);
     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
+     * 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(cx, this, offset);
+        updateDepth(offset);
 
     return offset;
 }
 
 ptrdiff_t
 BytecodeEmitter::emitJump(JSOp op, ptrdiff_t off)
 {
     ptrdiff_t offset = emitCheck(5);
     if (offset < 0)
         return -1;
 
     jsbytecode *code = this->code(offset);
     code[0] = jsbytecode(op);
     SET_JUMP_OFFSET(code, off);
-    UpdateDepth(cx, this, offset);
+    updateDepth(offset);
     return offset;
 }
 
 bool
 BytecodeEmitter::emitCall(JSOp op, uint16_t argc, ParseNode *pn)
 {
-    if (pn && !UpdateSourceCoordNotes(cx, this, pn->pn_pos.begin))
+    if (pn && !updateSourceCoordNotes(pn->pn_pos.begin))
         return false;
     return emit3(op, ARGC_HI(argc), ARGC_LO(argc));
 }
 
 bool
 BytecodeEmitter::emitDupAt(unsigned slot)
 {
     MOZ_ASSERT(slot < unsigned(stackDepth));
@@ -429,102 +423,102 @@ BytecodeEmitter::emitBackPatchOp(ptrdiff
 
 static inline unsigned
 LengthOfSetLine(unsigned line)
 {
     return 1 /* SN_SETLINE */ + (line > SN_4BYTE_OFFSET_MASK ? 4 : 1);
 }
 
 /* Updates line number notes, not column notes. */
-static inline bool
-UpdateLineNumberNotes(ExclusiveContext *cx, BytecodeEmitter *bce, uint32_t offset)
-{
-    TokenStream *ts = &bce->parser->tokenStream;
-    if (!ts->srcCoords.isOnThisLine(offset, bce->currentLine())) {
+bool
+BytecodeEmitter::updateLineNumberNotes(uint32_t offset)
+{
+    TokenStream *ts = &parser->tokenStream;
+    if (!ts->srcCoords.isOnThisLine(offset, currentLine())) {
         unsigned line = ts->srcCoords.lineNum(offset);
-        unsigned delta = line - bce->currentLine();
+        unsigned delta = line - currentLine();
 
         /*
          * Encode any change in the current source line number by using
          * either several SRC_NEWLINE notes or just one SRC_SETLINE note,
          * whichever consumes less space.
          *
          * NB: We handle backward line number deltas (possible with for
          * loops where the update part is emitted after the body, but its
          * line number is <= any line number in the body) here by letting
          * unsigned delta_ wrap to a very large number, which triggers a
          * SRC_SETLINE.
          */
-        bce->current->currentLine = line;
-        bce->current->lastColumn  = 0;
+        current->currentLine = line;
+        current->lastColumn  = 0;
         if (delta >= LengthOfSetLine(line)) {
-            if (NewSrcNote2(cx, bce, SRC_SETLINE, (ptrdiff_t)line) < 0)
+            if (NewSrcNote2(cx, this, SRC_SETLINE, (ptrdiff_t)line) < 0)
                 return false;
         } else {
             do {
-                if (NewSrcNote(cx, bce, SRC_NEWLINE) < 0)
+                if (NewSrcNote(cx, this, SRC_NEWLINE) < 0)
                     return false;
             } while (--delta != 0);
         }
     }
     return true;
 }
 
 /* Updates the line number and column number information in the source notes. */
-static bool
-UpdateSourceCoordNotes(ExclusiveContext *cx, BytecodeEmitter *bce, uint32_t offset)
-{
-    if (!UpdateLineNumberNotes(cx, bce, offset))
-        return false;
-
-    uint32_t columnIndex = bce->parser->tokenStream.srcCoords.columnIndex(offset);
-    ptrdiff_t colspan = ptrdiff_t(columnIndex) - ptrdiff_t(bce->current->lastColumn);
+bool
+BytecodeEmitter::updateSourceCoordNotes(uint32_t offset)
+{
+    if (!updateLineNumberNotes(offset))
+        return false;
+
+    uint32_t columnIndex = parser->tokenStream.srcCoords.columnIndex(offset);
+    ptrdiff_t colspan = ptrdiff_t(columnIndex) - ptrdiff_t(current->lastColumn);
     if (colspan != 0) {
         // If the column span is so large that we can't store it, then just
         // discard this information. This can happen with minimized or otherwise
         // machine-generated code. Even gigantic column numbers are still
         // valuable if you have a source map to relate them to something real;
         // but it's better to fail soft here.
         if (!SN_REPRESENTABLE_COLSPAN(colspan))
             return true;
-        if (NewSrcNote2(cx, bce, SRC_COLSPAN, SN_COLSPAN_TO_OFFSET(colspan)) < 0)
-            return false;
-        bce->current->lastColumn = columnIndex;
+        if (NewSrcNote2(cx, this, SRC_COLSPAN, SN_COLSPAN_TO_OFFSET(colspan)) < 0)
+            return false;
+        current->lastColumn = columnIndex;
     }
     return true;
 }
 
 bool
 BytecodeEmitter::emitLoopHead(ParseNode *nextpn)
 {
     if (nextpn) {
         /*
          * Try to give the JSOP_LOOPHEAD the same line number as the next
          * instruction. nextpn is often a block, in which case the next
          * instruction typically comes from the first statement inside.
          */
         MOZ_ASSERT_IF(nextpn->isKind(PNK_STATEMENTLIST), nextpn->isArity(PN_LIST));
         if (nextpn->isKind(PNK_STATEMENTLIST) && nextpn->pn_head)
             nextpn = nextpn->pn_head;
-        if (!UpdateSourceCoordNotes(cx, this, nextpn->pn_pos.begin))
+        if (!updateSourceCoordNotes(nextpn->pn_pos.begin))
             return false;
     }
 
     return emit1(JSOP_LOOPHEAD);
 }
 
 bool
 BytecodeEmitter::emitLoopEntry(ParseNode *nextpn)
 {
     if (nextpn) {
         /* Update the line number, as for LOOPHEAD. */
         MOZ_ASSERT_IF(nextpn->isKind(PNK_STATEMENTLIST), nextpn->isArity(PN_LIST));
         if (nextpn->isKind(PNK_STATEMENTLIST) && nextpn->pn_head)
             nextpn = nextpn->pn_head;
-        if (!UpdateSourceCoordNotes(cx, this, nextpn->pn_pos.begin))
+        if (!updateSourceCoordNotes(nextpn->pn_pos.begin))
             return false;
     }
 
     LoopStmtInfo *loop = LoopStmtInfo::fromStmtInfo(topStmt);
     MOZ_ASSERT(loop->loopDepth > 0);
 
     uint8_t loopDepthAndFlags = PackLoopEntryDepthHintAndFlags(loop->loopDepth, loop->canIonOsr);
     return emit2(JSOP_LOOPENTRY, loopDepthAndFlags);
@@ -721,34 +715,34 @@ BytecodeEmitter::backPatch(ptrdiff_t las
         *pc = op;
         pc -= delta;
     }
 }
 
 #define SET_STATEMENT_TOP(stmt, top)                                          \
     ((stmt)->update = (top), (stmt)->breaks = (stmt)->continues = (-1))
 
-static void
-PushStatementInner(BytecodeEmitter *bce, StmtInfoBCE *stmt, StmtType type, ptrdiff_t top)
+void
+BytecodeEmitter::pushStatementInner(StmtInfoBCE *stmt, StmtType type, ptrdiff_t top)
 {
     SET_STATEMENT_TOP(stmt, top);
-    PushStatement(bce, stmt, type);
-}
-
-static void
-PushStatementBCE(BytecodeEmitter *bce, StmtInfoBCE *stmt, StmtType type, ptrdiff_t top)
-{
-    PushStatementInner(bce, stmt, type, top);
+    PushStatement(this, stmt, type);
+}
+
+void
+BytecodeEmitter::pushStatement(StmtInfoBCE *stmt, StmtType type, ptrdiff_t top)
+{
+    pushStatementInner(stmt, type, top);
     MOZ_ASSERT(!stmt->isLoop());
 }
 
 static void
 PushLoopStatement(BytecodeEmitter *bce, LoopStmtInfo *stmt, StmtType type, ptrdiff_t top)
 {
-    PushStatementInner(bce, stmt, type, top);
+    bce->pushStatementInner(stmt, type, top);
     MOZ_ASSERT(stmt->isLoop());
 
     LoopStmtInfo *downLoop = nullptr;
     for (StmtInfoBCE *outer = stmt->down; outer; outer = outer->down) {
         if (outer->isLoop()) {
             downLoop = LoopStmtInfo::fromStmtInfo(outer);
             break;
         }
@@ -952,38 +946,36 @@ EnterNestedScope(ExclusiveContext *cx, B
         for (; stmt->staticScope != bce->staticScope; stmt = stmt->down) {}
         parent = stmt->blockScopeIndex;
     }
 
     stmt->blockScopeIndex = bce->blockScopeList.length();
     if (!bce->blockScopeList.append(scopeObjectIndex, bce->offset(), parent))
         return false;
 
-    PushStatementBCE(bce, stmt, stmtType, bce->offset());
+    bce->pushStatement(stmt, stmtType, bce->offset());
     scopeObj->initEnclosingNestedScope(EnclosingStaticScope(bce));
     FinishPushNestedScope(bce, stmt, *scopeObj);
     MOZ_ASSERT(stmt->isNestedScope);
     stmt->isBlockScope = (stmtType == STMT_BLOCK);
 
     return true;
 }
 
 // Patches |breaks| and |continues| unless the top statement info record
-// represents a try-catch-finally suite. May fail if a jump offset overflows.
-static bool
-PopStatementBCE(ExclusiveContext *cx, BytecodeEmitter *bce)
-{
-    StmtInfoBCE *stmt = bce->topStmt;
-    if (!stmt->isTrying()) {
-        bce->backPatch(stmt->breaks, bce->code().end(), JSOP_GOTO);
-        bce->backPatch(stmt->continues, bce->code(stmt->update), JSOP_GOTO);
-    }
-
-    FinishPopStatement(bce);
-    return true;
+// represents a try-catch-finally suite.
+void
+BytecodeEmitter::popStatement()
+{
+    if (!topStmt->isTrying()) {
+        backPatch(topStmt->breaks, code().end(), JSOP_GOTO);
+        backPatch(topStmt->continues, code(topStmt->update), JSOP_GOTO);
+    }
+
+    FinishPopStatement(this);
 }
 
 static bool
 LeaveNestedScope(ExclusiveContext *cx, BytecodeEmitter *bce, StmtInfoBCE *stmt)
 {
     MOZ_ASSERT(stmt == bce->topStmt);
     MOZ_ASSERT(stmt->isNestedScope);
     MOZ_ASSERT(stmt->isBlockScope == !(stmt->type == STMT_WITH));
@@ -994,18 +986,17 @@ LeaveNestedScope(ExclusiveContext *cx, B
     uint32_t blockObjIndex = bce->blockScopeList.list[blockScopeIndex].index;
     ObjectBox *blockObjBox = bce->objectList.find(blockObjIndex);
     NestedScopeObject *staticScope = &blockObjBox->object->as<NestedScopeObject>();
     MOZ_ASSERT(stmt->staticScope == staticScope);
     MOZ_ASSERT(staticScope == bce->staticScope);
     MOZ_ASSERT_IF(!stmt->isBlockScope, staticScope->is<StaticWithObject>());
 #endif
 
-    if (!PopStatementBCE(cx, bce))
-        return false;
+    bce->popStatement();
 
     if (!bce->emit1(stmt->isBlockScope ? JSOP_DEBUGLEAVEBLOCK : JSOP_LEAVEWITH))
         return false;
 
     bce->blockScopeList.recordEnd(blockScopeIndex, bce->offset());
 
     if (stmt->isBlockScope && stmt->staticScope->as<StaticBlockObject>().needsClone()) {
         if (!bce->emit1(JSOP_POPBLOCKSCOPE))
@@ -1025,17 +1016,17 @@ BytecodeEmitter::emitIndex32(JSOp op, ui
 
     ptrdiff_t offset = emitCheck(len);
     if (offset < 0)
         return false;
 
     jsbytecode *code = this->code(offset);
     code[0] = jsbytecode(op);
     SET_UINT32_INDEX(code, index);
-    UpdateDepth(cx, this, offset);
+    updateDepth(offset);
     checkTypeSet(op);
     return true;
 }
 
 bool
 BytecodeEmitter::emitIndexOp(JSOp op, uint32_t index)
 {
     MOZ_ASSERT(CheckStrictOrSloppy(this, op));
@@ -1045,17 +1036,17 @@ BytecodeEmitter::emitIndexOp(JSOp op, ui
 
     ptrdiff_t offset = emitCheck(len);
     if (offset < 0)
         return false;
 
     jsbytecode *code = this->code(offset);
     code[0] = jsbytecode(op);
     SET_UINT32_INDEX(code, index);
-    UpdateDepth(cx, this, offset);
+    updateDepth(offset);
     checkTypeSet(op);
     return true;
 }
 
 bool
 BytecodeEmitter::emitAtomOp(JSAtom *atom, JSOp op)
 {
     MOZ_ASSERT(JOF_OPTYPE(op) == JOF_ATOM);
@@ -1296,17 +1287,17 @@ BytecodeEmitter::emitAliasedVarOp(JSOp o
      *  - a heavyweight named function scope contributes an extra scope to the scope chain (a
      *    DeclEnvObject that holds just the name).
      *  - all the intervening let/catch blocks must be counted.
      */
     unsigned skippedScopes = 0;
     BytecodeEmitter *bceOfDef = this;
     if (pn->isUsed()) {
         /*
-         * As explained in BindNameToSlot, the 'level' of a use indicates how
+         * As explained in bindNameToSlot, the 'level' of a use indicates how
          * many function scopes (i.e., BytecodeEmitters) to skip to find the
          * enclosing function scope of the definition being accessed.
          */
         for (unsigned i = pn->pn_cookie.level(); i; i--) {
             skippedScopes += DynamicNestedScopeDepth(bceOfDef);
             FunctionBox *funbox = bceOfDef->sc->asFunctionBox();
             if (funbox->isHeavyweight()) {
                 skippedScopes++;
@@ -1888,26 +1879,26 @@ BindNameToSlotHelper(ExclusiveContext *c
     return true;
 }
 
 /*
  * Attempts to bind the name, then checks that no dynamic scope lookup ops are
  * emitted in self-hosting mode. NAME ops do lookups off current scope chain,
  * and we do not want to allow self-hosted code to use the dynamic scope.
  */
-static bool
-BindNameToSlot(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
-{
-    if (!BindNameToSlotHelper(cx, bce, pn))
-        return false;
-
-    StrictifySetNameNode(pn, bce);
-
-    if (bce->emitterMode == BytecodeEmitter::SelfHosting && !pn->isBound()) {
-        bce->reportError(pn, JSMSG_SELFHOSTED_UNBOUND_NAME);
+bool
+BytecodeEmitter::bindNameToSlot(ParseNode *pn)
+{
+    if (!BindNameToSlotHelper(cx, this, pn))
+        return false;
+
+    StrictifySetNameNode(pn, this);
+
+    if (emitterMode == BytecodeEmitter::SelfHosting && !pn->isBound()) {
+        reportError(pn, JSMSG_SELFHOSTED_UNBOUND_NAME);
         return false;
     }
 
     return true;
 }
 
 /*
  * If pn contains a useful expression, return true with *answer set to true.
@@ -1991,17 +1982,17 @@ CheckSideEffects(ExclusiveContext *cx, B
              *
              * The only exception is assignment of a useless value to a const
              * declared in the function currently being compiled.
              */
             ParseNode *pn2 = pn->pn_left;
             if (!pn2->isKind(PNK_NAME)) {
                 *answer = true;
             } else {
-                if (!BindNameToSlot(cx, bce, pn2))
+                if (!bce->bindNameToSlot(pn2))
                     return false;
                 if (!CheckSideEffects(cx, bce, pn->pn_right, answer))
                     return false;
                 if (!*answer && (!pn->isOp(JSOP_NOP) || !pn2->isConst()))
                     *answer = true;
             }
             return true;
         }
@@ -2020,17 +2011,17 @@ CheckSideEffects(ExclusiveContext *cx, B
 
       case PN_UNARY:
         switch (pn->getKind()) {
           case PNK_DELETE:
           {
             ParseNode *pn2 = pn->pn_kid;
             switch (pn2->getKind()) {
               case PNK_NAME:
-                if (!BindNameToSlot(cx, bce, pn2))
+                if (!bce->bindNameToSlot(pn2))
                     return false;
                 if (pn2->isConst()) {
                     MOZ_ASSERT(*answer == false);
                     return true;
                 }
                 /* FALL THROUGH */
               case PNK_DOT:
               case PNK_CALL:
@@ -2068,17 +2059,17 @@ CheckSideEffects(ExclusiveContext *cx, B
 
       case PN_NAME:
         /*
          * Take care to avoid trying to bind a label name (labels, both for
          * statements and property values in object initialisers, have pn_op
          * defaulted to JSOP_NOP).
          */
         if (pn->isKind(PNK_NAME) && !pn->isOp(JSOP_NOP)) {
-            if (!BindNameToSlot(cx, bce, pn))
+            if (!bce->bindNameToSlot(pn))
                 return false;
             if (!pn->isOp(JSOP_CALLEE) && pn->pn_cookie.isFree()) {
                 /*
                  * Not a use of an unshadowed named function expression's given
                  * name, so this expression could invoke a getter that has side
                  * effects.
                  */
                 *answer = true;
@@ -2204,17 +2195,17 @@ BytecodeEmitter::emitNewInit(JSProtoKey 
         return false;
 
     jsbytecode *code = this->code(offset);
     code[0] = JSOP_NEWINIT;
     code[1] = jsbytecode(key);
     code[2] = 0;
     code[3] = 0;
     code[4] = 0;
-    UpdateDepth(cx, this, offset);
+    updateDepth(offset);
     checkTypeSet(JSOP_NEWINIT);
     return true;
 }
 
 static bool
 IteratorResultShape(ExclusiveContext *cx, BytecodeEmitter *bce, unsigned *shape)
 {
     MOZ_ASSERT(bce->script->compileAndGo());
@@ -2277,17 +2268,17 @@ BytecodeEmitter::emitFinishIteratorResul
     if (!emitIndex32(JSOP_INITPROP, done_id))
         return false;
     return true;
 }
 
 bool
 BytecodeEmitter::emitNameOp(ParseNode *pn, bool callContext)
 {
-    if (!BindNameToSlot(cx, this, pn))
+    if (!bindNameToSlot(pn))
         return false;
 
     JSOp op = pn->getOp();
 
     if (op == JSOP_CALLEE) {
         if (!emit1(op))
             return false;
     } else {
@@ -2339,34 +2330,34 @@ BytecodeEmitter::emitPropLHS(ParseNode *
             pndot->pn_expr = pnup;
             if (!pndown->isKind(PNK_DOT))
                 break;
             pnup = pndot;
             pndot = pndown;
         }
 
         /* pndown is a primary expression, not a dotted property reference. */
-        if (!EmitTree(cx, this, pndown))
+        if (!emitTree(pndown))
             return false;
 
         do {
             /* Walk back up the list, emitting annotated name ops. */
             if (!emitAtomOp(pndot, JSOP_GETPROP))
                 return false;
 
             /* Reverse the pn_expr link again. */
             pnup = pndot->pn_expr;
             pndot->pn_expr = pndown;
             pndown = pndot;
         } while ((pndot = pnup) != nullptr);
         return true;
     }
 
     // The non-optimized case.
-    return EmitTree(cx, this, pn2);
+    return emitTree(pn2);
 }
 
 bool
 BytecodeEmitter::emitPropOp(ParseNode *pn, JSOp op)
 {
     MOZ_ASSERT(pn->isArity(PN_NAME));
 
     if (!emitPropLHS(pn, op))
@@ -2461,21 +2452,21 @@ BytecodeEmitter::emitNameIncDec(ParseNod
 
     return true;
 }
 
 bool
 BytecodeEmitter::emitElemOperands(ParseNode *pn, JSOp op)
 {
     MOZ_ASSERT(pn->isArity(PN_BINARY));
-    if (!EmitTree(cx, this, pn->pn_left))
+    if (!emitTree(pn->pn_left))
         return false;
     if (op == JSOP_CALLELEM && !emit1(JSOP_DUP))
         return false;
-    if (!EmitTree(cx, this, pn->pn_right))
+    if (!emitTree(pn->pn_right))
         return false;
     bool isSetElem = op == JSOP_SETELEM || op == JSOP_STRICTSETELEM;
     if (isSetElem && !emit2(JSOP_PICK, (jsbytecode)2))
         return false;
     return true;
 }
 
 bool
@@ -2579,20 +2570,20 @@ BytecodeEmitter::emitNumberOp(double dva
     }
 
     if (!constList.append(DoubleValue(dval)))
         return false;
 
     return emitIndex32(JSOP_DOUBLE, constList.length() - 1);
 }
 
-static inline void
-SetJumpOffsetAt(BytecodeEmitter *bce, ptrdiff_t off)
-{
-    SET_JUMP_OFFSET(bce->code(off), bce->offset() - off);
+void
+BytecodeEmitter::setJumpOffsetAt(ptrdiff_t off)
+{
+    SET_JUMP_OFFSET(code(off), offset() - off);
 }
 
 static bool
 PushInitialConstants(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp op, unsigned n)
 {
     MOZ_ASSERT(op == JSOP_UNDEFINED || op == JSOP_UNINITIALIZED);
     for (unsigned i = 0; i < n; ++i) {
         if (!bce->emit1(op))
@@ -2647,17 +2638,17 @@ EnterBlockScope(ExclusiveContext *cx, By
         return false;
 
     return true;
 }
 
 /*
  * Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047.
  * 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.
+ * into emitTree which is recursive and uses relatively little stack space.
  */
 MOZ_NEVER_INLINE bool
 BytecodeEmitter::emitSwitch(ParseNode *pn)
 {
     JSOp switchOp;
     bool hasDefault;
     ptrdiff_t top, off, defaultOffset;
     ParseNode *pn2, *pn3, *pn4;
@@ -2670,32 +2661,32 @@ BytecodeEmitter::emitSwitch(ParseNode *p
     switchOp = JSOP_TABLESWITCH;
     hasDefault = false;
     defaultOffset = -1;
 
     pn2 = pn->pn_right;
     MOZ_ASSERT(pn2->isKind(PNK_LEXICALSCOPE) || pn2->isKind(PNK_STATEMENTLIST));
 
     /* Push the discriminant. */
-    if (!EmitTree(cx, this, pn->pn_left))
+    if (!emitTree(pn->pn_left))
         return false;
 
     StmtInfoBCE stmtInfo(cx);
     if (pn2->isKind(PNK_LEXICALSCOPE)) {
         if (!EnterBlockScope(cx, this, &stmtInfo, pn2->pn_objbox, JSOP_UNINITIALIZED, 0))
             return false;
 
         stmtInfo.type = STMT_SWITCH;
         stmtInfo.update = top = offset();
         /* Advance pn2 to refer to the switch case list. */
         pn2 = pn2->expr();
     } else {
         MOZ_ASSERT(pn2->isKind(PNK_STATEMENTLIST));
         top = offset();
-        PushStatementBCE(this, &stmtInfo, STMT_SWITCH, top);
+        pushStatement(&stmtInfo, STMT_SWITCH, top);
     }
 
     /* Switch bytecodes run from here till end of final case. */
     uint32_t caseCount = pn2->pn_count;
     uint32_t tableLength = 0;
     UniquePtr<ParseNode*[], JS::FreePolicy> table(nullptr);
 
     if (caseCount > JS_BIT(16)) {
@@ -2825,21 +2816,21 @@ BytecodeEmitter::emitSwitch(ParseNode *p
     off = -1;
     if (switchOp == JSOP_CONDSWITCH) {
         int caseNoteIndex = -1;
         bool beforeCases = true;
 
         /* Emit code for evaluating cases and jumping to case statements. */
         for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
             pn4 = pn3->pn_left;
-            if (pn4 && !EmitTree(cx, this, pn4))
+            if (pn4 && !emitTree(pn4))
                 return false;
             if (caseNoteIndex >= 0) {
                 /* off is the previous JSOP_CASE's bytecode offset. */
-                if (!SetSrcNoteOffset(cx, this, (unsigned)caseNoteIndex, 0, offset() - off))
+                if (!setSrcNoteOffset(unsigned(caseNoteIndex), 0, offset() - off))
                     return false;
             }
             if (!pn4) {
                 MOZ_ASSERT(pn3->isKind(PNK_DEFAULT));
                 continue;
             }
             caseNoteIndex = NewSrcNote2(cx, this, SRC_NEXTCASE, 0);
             if (caseNoteIndex < 0)
@@ -2848,34 +2839,34 @@ BytecodeEmitter::emitSwitch(ParseNode *p
             if (off < 0)
                 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(cx, this, (unsigned)noteIndex, 1, off - top))
+                if (!setSrcNoteOffset(unsigned(noteIndex), 1, off - top))
                     return false;
                 noteCountDelta = notes().length() - noteCount;
                 if (noteCountDelta != 0)
                     caseNoteIndex += noteCountDelta;
                 beforeCases = false;
             }
         }
 
         /*
          * If we didn't have an explicit default (which could fall in between
-         * cases, preventing us from fusing this SetSrcNoteOffset with the call
+         * cases, preventing us from fusing this setSrcNoteOffset with the call
          * in the loop above), link the last case to the implicit default for
          * the benefit of IonBuilder.
          */
         if (!hasDefault &&
             caseNoteIndex >= 0 &&
-            !SetSrcNoteOffset(cx, this, (unsigned)caseNoteIndex, 0, offset() - off))
+            !setSrcNoteOffset(unsigned(caseNoteIndex), 0, offset() - off))
         {
             return false;
         }
 
         /* Emit default even if no explicit default statement. */
         defaultOffset = emitJump(JSOP_DEFAULT, 0);
         if (defaultOffset < 0)
             return false;
@@ -2914,19 +2905,19 @@ BytecodeEmitter::emitSwitch(ParseNode *p
                 table[i] = pn3;
             }
         }
     }
 
     /* 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(this, pn3->pn_offset);
+            setJumpOffsetAt(pn3->pn_offset);
         pn4 = pn3->pn_right;
-        if (!EmitTree(cx, this, pn4))
+        if (!emitTree(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. */
@@ -2944,17 +2935,17 @@ BytecodeEmitter::emitSwitch(ParseNode *p
     } else {
         pc = 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 = offset() - top;
-    if (!SetSrcNoteOffset(cx, this, (unsigned)noteIndex, 0, off))
+    if (!setSrcNoteOffset(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 (uint32_t i = 0; i < tableLength; i++) {
@@ -2964,18 +2955,17 @@ BytecodeEmitter::emitSwitch(ParseNode *p
             pc += JUMP_OFFSET_LEN;
         }
     }
 
     if (pn->pn_right->isKind(PNK_LEXICALSCOPE)) {
         if (!LeaveNestedScope(cx, this, &stmtInfo))
             return false;
     } else {
-        if (!PopStatementBCE(cx, this))
-            return false;
+        popStatement();
     }
 
     return true;
 }
 
 bool
 BytecodeEmitter::isRunOnceLambda()
 {
@@ -3066,17 +3056,17 @@ frontend::EmitFunctionScript(ExclusiveCo
     bool runOnce = bce->isRunOnceLambda();
     if (runOnce) {
         bce->switchToProlog();
         if (!bce->emit1(JSOP_RUNONCE))
             return false;
         bce->switchToMain();
     }
 
-    if (!EmitTree(cx, bce, body))
+    if (!bce->emitTree(body))
         return false;
 
     if (bce->sc->isFunctionBox()) {
         if (bce->sc->asFunctionBox()->isGenerator()) {
             // If we fall off the end of a generator, do a final yield.
             if (bce->sc->asFunctionBox()->isStarGenerator() && !bce->emitPrepareIteratorResult())
                 return false;
 
@@ -3166,17 +3156,17 @@ BytecodeEmitter::maybeEmitVarDecl(JSOp p
         if (!makeAtomIndex(pn->pn_atom, &atomIndex))
             return false;
     }
 
     if (JOF_OPTYPE(pn->getOp()) == JOF_ATOM &&
         (!sc->isFunctionBox() || sc->asFunctionBox()->isHeavyweight()))
     {
         switchToProlog();
-        if (!UpdateSourceCoordNotes(cx, this, pn->pn_pos.begin))
+        if (!updateSourceCoordNotes(pn->pn_pos.begin))
             return false;
         if (!emitIndexOp(prologOp, atomIndex))
             return false;
         switchToMain();
     }
 
     if (result)
         *result = atomIndex;
@@ -3233,17 +3223,17 @@ EmitDestructuringDeclsWithEmitter(Exclus
     }
     return true;
 }
 
 bool
 EmitDestructuringDecl(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp prologOp, ParseNode *pn)
 {
     MOZ_ASSERT(pn->isKind(PNK_NAME));
-    if (!BindNameToSlot(cx, bce, pn))
+    if (!bce->bindNameToSlot(pn))
         return false;
 
     MOZ_ASSERT(!pn->isOp(JSOP_CALLEE));
     return bce->maybeEmitVarDecl(prologOp, pn, nullptr);
 }
 
 static inline bool
 EmitDestructuringDecls(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp prologOp,
@@ -3300,17 +3290,17 @@ BytecodeEmitter::emitDestructuringLHS(Pa
     } else if (emitOption == PushInitialValues) {
         // The lhs is a simple name so the to-be-destructured value is
         // its initial value and there is nothing to do.
         MOZ_ASSERT(target->getOp() == JSOP_SETLOCAL || target->getOp() == JSOP_INITLEXICAL);
         MOZ_ASSERT(target->pn_dflags & PND_BOUND);
     } else {
         switch (target->getKind()) {
           case PNK_NAME:
-            if (!BindNameToSlot(cx, this, target))
+            if (!bindNameToSlot(target))
                 return false;
 
             switch (target->getOp()) {
               case JSOP_SETNAME:
               case JSOP_STRICTSETNAME:
               case JSOP_SETGNAME:
               case JSOP_STRICTSETGNAME:
               case JSOP_SETCONST: {
@@ -3359,17 +3349,17 @@ BytecodeEmitter::emitDestructuringLHS(Pa
             // See the (PNK_NAME, JSOP_SETNAME) case above.
             //
             // In `a.x = b`, `a` is evaluated first, then `b`, then a
             // JSOP_SETPROP instruction.
             //
             // In `[a.x] = [b]`, per spec, `b` is evaluated before `a`. Then we
             // need a property set -- but the operands are on the stack in the
             // wrong order for JSOP_SETPROP, so we have to add a JSOP_SWAP.
-            if (!EmitTree(cx, this, target->pn_expr))
+            if (!emitTree(target->pn_expr))
                 return false;
             if (!emit1(JSOP_SWAP))
                 return false;
             JSOp setOp = sc->strict() ? JSOP_STRICTSETPROP : JSOP_SETPROP;
             if (!emitAtomOp(target, setOp))
                 return false;
             break;
           }
@@ -3382,17 +3372,17 @@ BytecodeEmitter::emitDestructuringLHS(Pa
             JSOp setOp = sc->strict() ? JSOP_STRICTSETELEM : JSOP_SETELEM;
             if (!emitElemOp(target, setOp))
                 return false;
             break;
           }
 
           case PNK_CALL:
             MOZ_ASSERT(target->pn_xflags & PNX_SETCALL);
-            if (!EmitTree(cx, this, target))
+            if (!emitTree(target))
                 return false;
 
             // Pop the call return value. Below, we pop the RHS too, balancing
             // the stack --- presumably for the benefit of bytecode
             // analysis. (The interpreter will never reach these instructions
             // since we just emitted JSOP_SETCALL, which always throws. It's
             // possible no analyses actually depend on this either.)
             if (!emit1(JSOP_POP))
@@ -3442,19 +3432,19 @@ BytecodeEmitter::emitDefault(ParseNode *
     // Emit source note to enable ion compilation.
     if (NewSrcNote(cx, this, SRC_IF) < 0)
         return false;
     ptrdiff_t jump = emitJump(JSOP_IFEQ, 0);              // VALUE
     if (jump < 0)
         return false;
     if (!emit1(JSOP_POP))                                 // .
         return false;
-    if (!EmitTree(cx, this, defaultExpr))                 // DEFAULTVALUE
-        return false;
-    SetJumpOffsetAt(this, jump);
+    if (!emitTree(defaultExpr))                           // DEFAULTVALUE
+        return false;
+    setJumpOffsetAt(jump);
     return true;
 }
 
 static bool
 EmitDestructuringOpsArrayHelper(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pattern,
                                 VarEmitOption emitOption)
 {
     MOZ_ASSERT(pattern->isKind(PNK_ARRAY));
@@ -3526,23 +3516,23 @@ EmitDestructuringOpsArrayHelper(Exclusiv
                 return false;
             if (!bce->emit1(JSOP_UNDEFINED))                           // ... OBJ? ITER UNDEFINED
                 return false;
 
             /* Jump around else, fixup the branch, emit else, fixup jump. */
             ptrdiff_t jmp = bce->emitJump(JSOP_GOTO, 0);
             if (jmp < 0)
                 return false;
-            SetJumpOffsetAt(bce, beq);
+            bce->setJumpOffsetAt(beq);
 
             if (!bce->emitAtomOp(cx->names().value, JSOP_GETPROP))     // ... OBJ? ITER VALUE
                 return false;
 
-            SetJumpOffsetAt(bce, jmp);
-            if (!SetSrcNoteOffset(cx, bce, noteIndex, 0, jmp - beq))
+            bce->setJumpOffsetAt(jmp);
+            if (!bce->setSrcNoteOffset(noteIndex, 0, jmp - beq))
                 return false;
         }
 
         if (pndefault && !bce->emitDefault(pndefault))
             return false;
 
         // Destructure into the pattern the element contains.
         ParseNode *subpattern = elem;
@@ -3622,26 +3612,26 @@ EmitDestructuringOpsObjectHelper(Exclusi
             } else if (key->isKind(PNK_OBJECT_PROPERTY_NAME) || key->isKind(PNK_STRING)) {
                 PropertyName *name = key->pn_atom->asPropertyName();
 
                 // The parser already checked for atoms representing indexes and
                 // used PNK_NUMBER instead, but also watch for ids which TI treats
                 // as indexes for simplification of downstream analysis.
                 jsid id = NameToId(name);
                 if (id != IdToTypeId(id)) {
-                    if (!EmitTree(cx, bce, key))                       // ... OBJ OBJ KEY
+                    if (!bce->emitTree(key))                           // ... OBJ OBJ KEY
                         return false;
                 } else {
                     if (!bce->emitAtomOp(name, JSOP_GETPROP))          // ...OBJ PROP
                         return false;
                     needsGetElem = false;
                 }
             } else {
                 MOZ_ASSERT(key->isKind(PNK_COMPUTED_NAME));
-                if (!EmitTree(cx, bce, key->pn_kid))                   // ... OBJ OBJ KEY
+                if (!bce->emitTree(key->pn_kid))                       // ... OBJ OBJ KEY
                     return false;
             }
 
             subpattern = member->pn_right;
         }
 
         // Get the property value if not done already.
         if (needsGetElem && !bce->emitElemOpBase(JSOP_GETELEM))        // ... OBJ PROP
@@ -3752,20 +3742,20 @@ EmitDestructuringOps(ExclusiveContext *c
 bool
 BytecodeEmitter::emitTemplateString(ParseNode *pn)
 {
     MOZ_ASSERT(pn->isArity(PN_LIST));
 
     for (ParseNode *pn2 = pn->pn_head; pn2 != NULL; pn2 = pn2->pn_next) {
         if (pn2->getKind() != PNK_STRING && pn2->getKind() != PNK_TEMPLATE_STRING) {
             // We update source notes before emitting the expression
-            if (!UpdateSourceCoordNotes(cx, this, pn2->pn_pos.begin))
+            if (!updateSourceCoordNotes(pn2->pn_pos.begin))
                 return false;
         }
-        if (!EmitTree(cx, this, pn2))
+        if (!emitTree(pn2))
             return false;
 
         if (pn2->getKind() != PNK_STRING && pn2->getKind() != PNK_TEMPLATE_STRING) {
             // We need to convert the expression to a string
             if (!emit1(JSOP_TOSTRING))
                 return false;
         }
 
@@ -3782,27 +3772,27 @@ BytecodeEmitter::emitTemplateString(Pars
 bool
 BytecodeEmitter::emitVariables(ParseNode *pn, VarEmitOption emitOption, bool isLetExpr)
 {
     MOZ_ASSERT(pn->isArity(PN_LIST));
     MOZ_ASSERT(isLetExpr == (emitOption == PushInitialValues));
 
     ParseNode *next;
     for (ParseNode *pn2 = pn->pn_head; ; pn2 = next) {
-        if (!UpdateSourceCoordNotes(cx, this, pn2->pn_pos.begin))
+        if (!updateSourceCoordNotes(pn2->pn_pos.begin))
             return false;
         next = pn2->pn_next;
 
         ParseNode *pn3;
         if (!pn2->isKind(PNK_NAME)) {
             if (pn2->isKind(PNK_ARRAY) || pn2->isKind(PNK_OBJECT)) {
                 // If the emit option is DefineVars, emit variable binding
                 // ops, but not destructuring ops.  The parser (see
                 // Parser::variables) has ensured that our caller will be the
-                // PNK_FOR/PNK_FORIN/PNK_FOROF case in EmitTree (we don't have
+                // PNK_FOR/PNK_FORIN/PNK_FOROF case in emitTree (we don't have
                 // to worry about this being a variable declaration, as
                 // destructuring declarations without initializers, e.g., |var
                 // [x]|, are not legal syntax), and that case will emit the
                 // destructuring code only after emitting an enumerating
                 // opcode and a branch that tests whether the enumeration
                 // ended. Thus, each iteration's assignment is responsible for
                 // initializing, and nothing needs to be done here.
                 //
@@ -3846,17 +3836,17 @@ BytecodeEmitter::emitVariables(ParseNode
                 pn2 = pn2->pn_left;
                 goto do_name;
             }
 
             pn3 = pn2->pn_left;
             if (!EmitDestructuringDecls(cx, this, pn->getOp(), pn3))
                 return false;
 
-            if (!EmitTree(cx, this, pn2->pn_right))
+            if (!emitTree(pn2->pn_right))
                 return false;
 
             if (!EmitDestructuringOps(cx, this, pn3, isLetExpr))
                 return false;
 
             /* If we are not initializing, nothing to pop. */
             if (emitOption != InitializeVars) {
                 if (next)
@@ -3870,17 +3860,17 @@ BytecodeEmitter::emitVariables(ParseNode
          * Load initializer early to share code above that jumps to do_name.
          * NB: if this var redeclares an existing binding, then pn2 is linked
          * on its definition's use-chain and pn_expr has been overlayed with
          * pn_lexdef.
          */
         pn3 = pn2->maybeExpr();
 
      do_name:
-        if (!BindNameToSlot(cx, this, pn2))
+        if (!bindNameToSlot(pn2))
             return false;
 
 
         JSOp op;
         op = pn2->getOp();
         MOZ_ASSERT(op != JSOP_CALLEE);
         MOZ_ASSERT(!pn2->pn_cookie.isFree() || !pn->isOp(JSOP_NOP));
 
@@ -3905,17 +3895,17 @@ BytecodeEmitter::emitVariables(ParseNode
                 else
                     bindOp = JSOP_BINDINTRINSIC;
                 if (!emitIndex32(bindOp, atomIndex))
                     return false;
             }
 
             bool oldEmittingForInit = emittingForInit;
             emittingForInit = false;
-            if (!EmitTree(cx, this, pn3))
+            if (!emitTree(pn3))
                 return false;
             emittingForInit = oldEmittingForInit;
         } else if (op == JSOP_INITLEXICAL || isLetExpr) {
             // 'let' bindings cannot be used before they are
             // initialized. JSOP_INITLEXICAL distinguishes the binding site.
             MOZ_ASSERT(emitOption != DefineVars);
             MOZ_ASSERT_IF(emitOption == InitializeVars, pn->pn_xflags & PNX_POPVAR);
             if (!emit1(JSOP_UNDEFINED))
@@ -3962,17 +3952,17 @@ BytecodeEmitter::emitAssignment(ParseNod
      * Specialize to avoid ECMA "reference type" values on the operand
      * stack, which impose pervasive runtime "GetValue" costs.
      */
     jsatomid atomIndex = (jsatomid) -1;
     jsbytecode offset = 1;
 
     switch (lhs->getKind()) {
       case PNK_NAME:
-        if (!BindNameToSlot(cx, this, lhs))
+        if (!bindNameToSlot(lhs))
             return false;
         if (lhs->pn_cookie.isFree()) {
             if (!makeAtomIndex(lhs->pn_atom, &atomIndex))
                 return false;
             if (!lhs->isConst()) {
                 JSOp bindOp;
                 if (lhs->isOp(JSOP_SETNAME) || lhs->isOp(JSOP_STRICTSETNAME))
                     bindOp = JSOP_BINDNAME;
@@ -3982,36 +3972,36 @@ BytecodeEmitter::emitAssignment(ParseNod
                     bindOp = JSOP_BINDINTRINSIC;
                 if (!emitIndex32(bindOp, atomIndex))
                     return false;
                 offset++;
             }
         }
         break;
       case PNK_DOT:
-        if (!EmitTree(cx, this, lhs->expr()))
+        if (!emitTree(lhs->expr()))
             return false;
         offset++;
         if (!makeAtomIndex(lhs->pn_atom, &atomIndex))
             return false;
         break;
       case PNK_ELEM:
         MOZ_ASSERT(lhs->isArity(PN_BINARY));
-        if (!EmitTree(cx, this, lhs->pn_left))
-            return false;
-        if (!EmitTree(cx, this, lhs->pn_right))
+        if (!emitTree(lhs->pn_left))
+            return false;
+        if (!emitTree(lhs->pn_right))
             return false;
         offset += 2;
         break;
       case PNK_ARRAY:
       case PNK_OBJECT:
         break;
       case PNK_CALL:
         MOZ_ASSERT(lhs->pn_xflags & PNX_SETCALL);
-        if (!EmitTree(cx, this, lhs))
+        if (!emitTree(lhs))
             return false;
         if (!emit1(JSOP_POP))
             return false;
         break;
       default:
         MOZ_ASSERT(0);
     }
 
@@ -4081,17 +4071,17 @@ BytecodeEmitter::emitAssignment(ParseNod
                 return false;
             break;
           default:;
         }
     }
 
     /* Now emit the right operand (it may affect the namespace). */
     if (rhs) {
-        if (!EmitTree(cx, this, rhs))
+        if (!emitTree(rhs))
             return false;
     } else {
         /*
          * The value to assign is the next enumeration value in a for-in or
          * for-of loop.  That value has already been emitted: by JSOP_ITERNEXT
          * in the for-in case, or via a GETPROP "value" on the result object in
          * the for-of case.  If offset == 1, that slot is already at the top of
          * the stack. Otherwise, rearrange the stack to put that value on top.
@@ -4367,32 +4357,32 @@ BytecodeEmitter::emitCatch(ParseNode *pn
       case PNK_OBJECT:
         if (!EmitDestructuringOps(cx, this, pn2))
             return false;
         if (!emit1(JSOP_POP))
             return false;
         break;
 
       case PNK_NAME:
-        /* Inline and specialize BindNameToSlot for pn2. */
+        /* Inline and specialize bindNameToSlot for pn2. */
         MOZ_ASSERT(!pn2->pn_cookie.isFree());
         if (!emitVarOp(pn2, JSOP_INITLEXICAL))
             return false;
         if (!emit1(JSOP_POP))
             return false;
         break;
 
       default:
         MOZ_ASSERT(0);
     }
 
     // If there is a guard expression, emit it and arrange to jump to the next
     // catch block if the guard expression is false.
     if (pn->pn_kid2) {
-        if (!EmitTree(cx, this, 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)
             return false;
@@ -4412,25 +4402,25 @@ BytecodeEmitter::emitCatch(ParseNode *pn
             // Jump to the next handler.  The jump target is backpatched by emitTry.
             ptrdiff_t guardJump = emitJump(JSOP_GOTO, 0);
             if (guardJump < 0)
                 return false;
             stmt->guardJump() = guardJump;
         }
 
         // Back to normal control flow.
-        SetJumpOffsetAt(this, guardCheck);
+        setJumpOffsetAt(guardCheck);
 
         // Pop duplicated exception object as we no longer need it.
         if (!emit1(JSOP_POP))
             return false;
     }
 
     /* Emit the catch body. */
-    return EmitTree(cx, this, pn->pn_kid3);
+    return emitTree(pn->pn_kid3);
 }
 
 // Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See the
 // comment on EmitSwitch.
 MOZ_NEVER_INLINE bool
 BytecodeEmitter::emitTry(ParseNode *pn)
 {
     StmtInfoBCE stmtInfo(cx);
@@ -4438,45 +4428,45 @@ BytecodeEmitter::emitTry(ParseNode *pn)
     // Push stmtInfo to track jumps-over-catches and gosubs-to-finally
     // for later fixup.
     //
     // When a finally block is active (STMT_FINALLY in our parse context),
     // non-local jumps (including jumps-over-catches) result in a GOSUB
     // being written into the bytecode stream and fixed-up later (c.f.
     // emitBackPatchOp and backPatch).
     //
-    PushStatementBCE(this, &stmtInfo, pn->pn_kid3 ? STMT_FINALLY : STMT_TRY, offset());
+    pushStatement(&stmtInfo, pn->pn_kid3 ? STMT_FINALLY : STMT_TRY, offset());
 
     // Since an exception can be thrown at any place inside the try block,
     // we need to restore the stack and the scope chain before we transfer
     // the control to the exception handler.
     //
     // For that we store in a try note associated with the catch or
     // finally block the stack depth upon the try entry. The interpreter
     // uses this depth to properly unwind the stack and the scope chain.
     //
     int depth = stackDepth;
 
     // Record the try location, then emit the try block.
     ptrdiff_t noteIndex = NewSrcNote(cx, this, SRC_TRY);
     if (noteIndex < 0 || !emit1(JSOP_TRY))
         return false;
     ptrdiff_t tryStart = offset();
-    if (!EmitTree(cx, this, pn->pn_kid1))
+    if (!emitTree(pn->pn_kid1))
         return false;
     MOZ_ASSERT(depth == stackDepth);
 
     // GOSUB to finally, if present.
     if (pn->pn_kid3) {
         if (!emitBackPatchOp(&stmtInfo.gosubs()))
             return false;
     }
 
     // Source note points to the jump at the end of the try block.
-    if (!SetSrcNoteOffset(cx, this, noteIndex, 0, offset() - tryStart + JSOP_TRY_LENGTH))
+    if (!setSrcNoteOffset(noteIndex, 0, offset() - tryStart + JSOP_TRY_LENGTH))
         return false;
 
     // Emit jump over catch and/or finally.
     ptrdiff_t catchJump = -1;
     if (!emitBackPatchOp(&catchJump))
         return false;
 
     ptrdiff_t tryEnd = offset();
@@ -4511,17 +4501,17 @@ BytecodeEmitter::emitTry(ParseNode *pn)
         // code if appropriate, and is also used for the catch-all trynote for
         // capturing exceptions thrown from catch{} blocks.
         //
         for (ParseNode *pn3 = catchList->pn_head; pn3; pn3 = pn3->pn_next) {
             MOZ_ASSERT(this->stackDepth == depth);
 
             // Emit the lexical scope and catch body.
             MOZ_ASSERT(pn3->isKind(PNK_LEXICALSCOPE));
-            if (!EmitTree(cx, this, pn3))
+            if (!emitTree(pn3))
                 return false;
 
             // gosub <finally>, if required.
             if (pn->pn_kid3) {
                 if (!emitBackPatchOp(&stmtInfo.gosubs()))
                     return false;
                 MOZ_ASSERT(this->stackDepth == depth);
             }
@@ -4529,17 +4519,17 @@ BytecodeEmitter::emitTry(ParseNode *pn)
             // Jump over the remaining catch blocks.  This will get fixed
             // up to jump to after catch/finally.
             if (!emitBackPatchOp(&catchJump))
                 return false;
 
             // If this catch block had a guard clause, patch the guard jump to
             // come here.
             if (stmtInfo.guardJump() != -1) {
-                SetJumpOffsetAt(this, stmtInfo.guardJump());
+                setJumpOffsetAt(stmtInfo.guardJump());
                 stmtInfo.guardJump() = -1;
 
                 // If this catch block is the last one, rethrow, delegating
                 // execution of any finally block to the exception handler.
                 if (!pn3->pn_next) {
                     if (!emit1(JSOP_EXCEPTION))
                         return false;
                     if (!emit1(JSOP_THROW))
@@ -4557,29 +4547,28 @@ BytecodeEmitter::emitTry(ParseNode *pn)
         // Fix up the gosubs that might have been emitted before non-local
         // jumps to the finally code.
         backPatch(stmtInfo.gosubs(), code().end(), JSOP_GOSUB);
 
         finallyStart = offset();
 
         // Indicate that we're emitting a subroutine body.
         stmtInfo.type = STMT_SUBROUTINE;
-        if (!UpdateSourceCoordNotes(cx, this, pn->pn_kid3->pn_pos.begin))
+        if (!updateSourceCoordNotes(pn->pn_kid3->pn_pos.begin))
             return false;
         if (!emit1(JSOP_FINALLY) ||
-            !EmitTree(cx, this, pn->pn_kid3) ||
+            !emitTree(pn->pn_kid3) ||
             !emit1(JSOP_RETSUB))
         {
             return false;
         }
         hasTryFinally = true;
         MOZ_ASSERT(this->stackDepth == depth);
     }
-    if (!PopStatementBCE(cx, this))
-        return false;
+    popStatement();
 
     // ReconstructPCStack needs a NOP here to mark the end of the last catch block.
     if (!emit1(JSOP_NOP))
         return false;
 
     // Fix up the end-of-try/catch jumps to come here.
     backPatch(catchJump, code().end(), JSOP_GOTO);
 
@@ -4605,84 +4594,86 @@ BytecodeEmitter::emitIf(ParseNode *pn)
     /* Initialize so we can detect else-if chains and avoid recursion. */
     stmtInfo.type = STMT_IF;
     ptrdiff_t beq = -1;
     ptrdiff_t jmp = -1;
     ptrdiff_t noteIndex = -1;
 
   if_again:
     /* Emit code for the condition before pushing stmtInfo. */
-    if (!EmitTree(cx, this, pn->pn_kid1))
+    if (!emitTree(pn->pn_kid1))
         return false;
     ptrdiff_t top = offset();
     if (stmtInfo.type == STMT_IF) {
-        PushStatementBCE(this, &stmtInfo, STMT_IF, top);
+        pushStatement(&stmtInfo, STMT_IF, top);
     } else {
         /*
          * We came here from the goto further below that detects else-if
          * chains, so we must mutate stmtInfo back into a STMT_IF record.
          * Also we need a note offset for SRC_IF_ELSE to help IonMonkey.
          */
         MOZ_ASSERT(stmtInfo.type == STMT_ELSE);
         stmtInfo.type = STMT_IF;
         stmtInfo.update = top;
-        if (!SetSrcNoteOffset(cx, this, noteIndex, 0, jmp - beq))
+        if (!setSrcNoteOffset(noteIndex, 0, jmp - beq))
             return false;
     }
 
     /* Emit an annotated branch-if-false around the then part. */
     ParseNode *pn3 = pn->pn_kid3;
     noteIndex = NewSrcNote(cx, this, pn3 ? SRC_IF_ELSE : SRC_IF);
     if (noteIndex < 0)
         return false;
     beq = emitJump(JSOP_IFEQ, 0);
     if (beq < 0)
         return false;
 
     /* Emit code for the then and optional else parts. */
-    if (!EmitTree(cx, this, pn->pn_kid2))
+    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 PopStatementBCE call at the bottom of
+         * 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;
 
         /* Ensure the branch-if-false comes here, then emit the else. */
-        SetJumpOffsetAt(this, beq);
+        setJumpOffsetAt(beq);
         if (pn3->isKind(PNK_IF)) {
             pn = pn3;
             goto if_again;
         }
 
-        if (!EmitTree(cx, this, pn3))
+        if (!emitTree(pn3))
             return false;
 
         /*
          * Annotate SRC_IF_ELSE with the offset from branch to jump, for
          * IonMonkey's benefit.  We can't just "back up" from the pc
          * of the else clause, because we don't know whether an extended
          * jump was required to leap from the end of the then clause over
          * the else clause.
          */
-        if (!SetSrcNoteOffset(cx, this, noteIndex, 0, jmp - beq))
+        if (!setSrcNoteOffset(noteIndex, 0, jmp - beq))
             return false;
     } else {
         /* No else part, fixup the branch-if-false to come here. */
-        SetJumpOffsetAt(this, beq);
-    }
-    return PopStatementBCE(cx, this);
+        setJumpOffsetAt(beq);
+    }
+
+    popStatement();
+    return true;
 }
 
 /*
  * pnLet represents one of:
  *
  *   let-expression:   (let (x = y) EXPR)
  *   let-statement:    let (x = y) { ... }
  *
@@ -4729,17 +4720,17 @@ EmitLet(ExclusiveContext *cx, BytecodeEm
         return false;
 
     /* Push storage for hoisted let decls (e.g. 'let (x) { let y }'). */
     uint32_t valuesPushed = bce->stackDepth - letHeadDepth;
     StmtInfoBCE stmtInfo(cx);
     if (!EnterBlockScope(cx, bce, &stmtInfo, letBody->pn_objbox, JSOP_UNINITIALIZED, valuesPushed))
         return false;
 
-    if (!EmitTree(cx, bce, letBody->pn_expr))
+    if (!bce->emitTree(letBody->pn_expr))
         return false;
 
     if (!LeaveNestedScope(cx, bce, &stmtInfo))
         return false;
 
     return true;
 }
 
@@ -4751,34 +4742,34 @@ MOZ_NEVER_INLINE static bool
 EmitLexicalScope(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
 {
     MOZ_ASSERT(pn->isKind(PNK_LEXICALSCOPE));
 
     StmtInfoBCE stmtInfo(cx);
     if (!EnterBlockScope(cx, bce, &stmtInfo, pn->pn_objbox, JSOP_UNINITIALIZED, 0))
         return false;
 
-    if (!EmitTree(cx, bce, pn->pn_expr))
+    if (!bce->emitTree(pn->pn_expr))
         return false;
 
     if (!LeaveNestedScope(cx, bce, &stmtInfo))
         return false;
 
     return true;
 }
 
 bool
 BytecodeEmitter::emitWith(ParseNode *pn)
 {
     StmtInfoBCE stmtInfo(cx);
-    if (!EmitTree(cx, this, pn->pn_left))
+    if (!emitTree(pn->pn_left))
         return false;
     if (!EnterNestedScope(cx, this, &stmtInfo, pn->pn_binary_obj, STMT_WITH))
         return false;
-    if (!EmitTree(cx, this, pn->pn_right))
+    if (!emitTree(pn->pn_right))
         return false;
     if (!LeaveNestedScope(cx, this, &stmtInfo))
         return false;
     return true;
 }
 
 bool
 BytecodeEmitter::emitIterator()
@@ -4847,17 +4838,17 @@ BytecodeEmitter::emitForOf(StmtType type
     if (pn1 && !emitForInOrOfVariables(pn1, &letDecl))
         return false;
 
     if (type == STMT_FOR_OF_LOOP) {
         // For-of loops run with two values on the stack: the iterator and the
         // current result object.
 
         // Compile the object expression to the right of 'of'.
-        if (!EmitTree(cx, this, forHeadExpr))
+        if (!emitTree(forHeadExpr))
             return false;
         if (!emitIterator())
             return false;
 
         // Push a dummy result so that we properly enter iteration midstream.
         if (!emit1(JSOP_UNDEFINED))                // ITER RESULT
             return false;
     }
@@ -4908,17 +4899,17 @@ BytecodeEmitter::emitForOf(StmtType type
             return false;
         if (!emit1(JSOP_POP))                             // ITER RESULT
             return false;
 
         // The stack should be balanced around the assignment opcode sequence.
         MOZ_ASSERT(this->stackDepth == loopDepth);
 
         // Emit code for the loop body.
-        if (!EmitTree(cx, this, forBody))
+        if (!emitTree(forBody))
             return false;
 
         // Set loop and enclosing "update" offsets, for continue.
         StmtInfoBCE *stmt = &stmtInfo;
         do {
             stmt->update = offset();
         } while ((stmt = stmt->down) != nullptr && stmt->type == STMT_LABEL);
     } else {
@@ -4926,17 +4917,17 @@ BytecodeEmitter::emitForOf(StmtType type
             return false;
 
         MOZ_ASSERT(this->stackDepth == loopDepth - 1);
 
         // STMT_SPREAD never contain continue, so do not set "update" offset.
     }
 
     // COME FROM the beginning of the loop to here.
-    SetJumpOffsetAt(this, jmp);
+    setJumpOffsetAt(jmp);
     if (!emitLoopEntry(forHeadExpr))
         return false;
 
     if (type == STMT_FOR_OF_LOOP) {
         if (!emit1(JSOP_POP))                             // ITER
             return false;
         if (!emit1(JSOP_DUP))                             // ITER ITER
             return false;
@@ -4953,23 +4944,22 @@ BytecodeEmitter::emitForOf(StmtType type
 
     ptrdiff_t beq = emitJump(JSOP_IFEQ, top - offset());  // ... RESULT
     if (beq < 0)
         return false;
 
     MOZ_ASSERT(this->stackDepth == loopDepth);
 
     // Let Ion know where the closing jump of this loop is.
-    if (!SetSrcNoteOffset(cx, this, (unsigned)noteIndex, 0, beq - jmp))
+    if (!setSrcNoteOffset(unsigned(noteIndex), 0, beq - jmp))
         return false;
 
     // Fixup breaks and continues.
     // For STMT_SPREAD, just pop pc->topStmt.
-    if (!PopStatementBCE(cx, this))
-        return false;
+    popStatement();
 
     if (letDecl) {
         if (!LeaveNestedScope(cx, this, &letStmt))
             return false;
     }
 
     if (type == STMT_SPREAD) {
         if (!emit2(JSOP_PICK, (jsbytecode)3))      // ARR I RESULT ITER
@@ -4987,17 +4977,17 @@ BytecodeEmitter::emitForIn(ParseNode *pn
     ParseNode *forBody = pn->pn_right;
 
     ParseNode *pn1 = forHead->pn_kid1;
     bool letDecl = false;
     if (pn1 && !emitForInOrOfVariables(pn1, &letDecl))
         return false;
 
     /* Compile the object expression to the right of 'in'. */
-    if (!EmitTree(cx, this, forHead->pn_kid3))
+    if (!emitTree(forHead->pn_kid3))
         return false;
 
     /*
      * Emit a bytecode to convert top of stack value to the iterator
      * object depending on the loop variant (for-in, for-each-in, or
      * destructuring for-in).
      */
     MOZ_ASSERT(pn->isOp(JSOP_ITER));
@@ -5047,48 +5037,47 @@ BytecodeEmitter::emitForIn(ParseNode *pn
     // also leave it on the stack.
     if (!emitAssignment(forHead->pn_kid2, JSOP_NOP, nullptr))
         return false;
 
     /* The stack should be balanced around the assignment opcode sequence. */
     MOZ_ASSERT(this->stackDepth == loopDepth);
 
     /* Emit code for the loop body. */
-    if (!EmitTree(cx, this, forBody))
+    if (!emitTree(forBody))
         return false;
 
     /* Set loop and enclosing "update" offsets, for continue. */
     StmtInfoBCE *stmt = &stmtInfo;
     do {
         stmt->update = offset();
     } while ((stmt = stmt->down) != nullptr && stmt->type == STMT_LABEL);
 
     /*
      * Fixup the goto that starts the loop to jump down to JSOP_MOREITER.
      */
-    SetJumpOffsetAt(this, jmp);
+    setJumpOffsetAt(jmp);
     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)
         return false;
 
     /* Set the srcnote offset so we can find the closing jump. */
-    if (!SetSrcNoteOffset(cx, this, (unsigned)noteIndex, 0, beq - jmp))
+    if (!setSrcNoteOffset(unsigned(noteIndex), 0, beq - jmp))
         return false;
 
     // Fix up breaks and continues.
-    if (!PopStatementBCE(cx, this))
-        return false;
+    popStatement();
 
     // Pop the enumeration value.
     if (!emit1(JSOP_POP))
         return false;
 
     if (!tryNoteList.append(JSTRY_ITER, this->stackDepth, top, offset()))
         return false;
     if (!emit1(JSOP_ENDITER))
@@ -5115,19 +5104,19 @@ BytecodeEmitter::emitNormalFor(ParseNode
     JSOp op = JSOP_POP;
     ParseNode *pn3 = forHead->pn_kid1;
     if (!pn3) {
         // No initializer, but emit a nop so that there's somewhere to put the
         // SRC_FOR annotation that IonBuilder will look for.
         op = JSOP_NOP;
     } else {
         emittingForInit = true;
-        if (!UpdateSourceCoordNotes(cx, this, pn3->pn_pos.begin))
-            return false;
-        if (!EmitTree(cx, this, pn3))
+        if (!updateSourceCoordNotes(pn3->pn_pos.begin))
+            return false;
+        if (!emitTree(pn3))
             return false;
         emittingForInit = false;
     }
 
     /*
      * NB: the SRC_FOR note has offsetBias 1 (JSOP_{NOP,POP}_LENGTH).
      * Use tmp to hold the biased srcnote "top" offset, which differs
      * from the top local variable by the length of the JSOP_GOTO
@@ -5152,36 +5141,36 @@ BytecodeEmitter::emitNormalFor(ParseNode
     top = offset();
     SET_STATEMENT_TOP(&stmtInfo, top);
 
     /* Emit code for the loop body. */
     if (!emitLoopHead(forBody))
         return false;
     if (jmp == -1 && !emitLoopEntry(forBody))
         return false;
-    if (!EmitTree(cx, this, forBody))
+    if (!emitTree(forBody))
         return false;
 
     /* Set the second note offset so we can find the update part. */
     MOZ_ASSERT(noteIndex != -1);
     ptrdiff_t tmp2 = offset();
 
     /* Set loop and enclosing "update" offsets, for continue. */
     StmtInfoBCE *stmt = &stmtInfo;
     do {
         stmt->update = offset();
     } while ((stmt = stmt->down) != nullptr && stmt->type == STMT_LABEL);
 
     /* Check for update code to do before the condition (if any). */
     pn3 = forHead->pn_kid3;
     if (pn3) {
-        if (!UpdateSourceCoordNotes(cx, this, pn3->pn_pos.begin))
+        if (!updateSourceCoordNotes(pn3->pn_pos.begin))
             return false;
         op = JSOP_POP;
-        if (!EmitTree(cx, this, pn3))
+        if (!emitTree(pn3))
             return false;
 
         /* Always emit the POP or NOP to help IonBuilder. */
         if (!emit1(op))
             return false;
 
         /* Restore the absolute line number for source note readers. */
         uint32_t lineNum = parser->tokenStream.srcCoords.lineNum(pn->pn_pos.end);
@@ -5193,43 +5182,44 @@ BytecodeEmitter::emitNormalFor(ParseNode
         }
     }
 
     ptrdiff_t tmp3 = offset();
 
     if (forHead->pn_kid2) {
         /* Fix up the goto from top to target the loop condition. */
         MOZ_ASSERT(jmp >= 0);
-        SetJumpOffsetAt(this, jmp);
+        setJumpOffsetAt(jmp);
         if (!emitLoopEntry(forHead->pn_kid2))
             return false;
 
-        if (!EmitTree(cx, this, forHead->pn_kid2))
+        if (!emitTree(forHead->pn_kid2))
             return false;
     }
 
     /* Set the first note offset so we can find the loop condition. */
-    if (!SetSrcNoteOffset(cx, this, (unsigned)noteIndex, 0, tmp3 - tmp))
-        return false;
-    if (!SetSrcNoteOffset(cx, this, (unsigned)noteIndex, 1, tmp2 - tmp))
+    if (!setSrcNoteOffset(unsigned(noteIndex), 0, tmp3 - tmp))
+        return false;
+    if (!setSrcNoteOffset(unsigned(noteIndex), 1, tmp2 - tmp))
         return false;
     /* The third note offset helps us find the loop-closing jump. */
-    if (!SetSrcNoteOffset(cx, this, (unsigned)noteIndex, 2, offset() - tmp))
+    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)
         return false;
 
     if (!tryNoteList.append(JSTRY_LOOP, stackDepth, top, offset()))
         return false;
 
     /* Now fixup all breaks and continues. */
-    return PopStatementBCE(cx, this);
+    popStatement();
+    return true;
 }
 
 bool
 BytecodeEmitter::emitFor(ParseNode *pn, ptrdiff_t top)
 {
     if (pn->pn_left->isKind(PNK_FORIN))
         return emitForIn(pn, top);
 
@@ -5351,27 +5341,27 @@ EmitFunc(ExclusiveContext *cx, BytecodeE
     MOZ_ASSERT(!needsProto);
 
     /*
      * For a script we emit the code as we parse. Thus the bytecode for
      * top-level functions should go in the prolog to predefine their
      * names in the variable object before the already-generated main code
      * is executed. This extra work for top-level scripts is not necessary
      * when we emit the code for a function. It is fully parsed prior to
-     * invocation of the emitter and calls to EmitTree for function
+     * invocation of the emitter and calls to emitTree for function
      * definitions can be scheduled before generating the rest of code.
      */
     if (!bce->sc->isFunctionBox()) {
         MOZ_ASSERT(pn->pn_cookie.isFree());
         MOZ_ASSERT(pn->getOp() == JSOP_NOP);
         MOZ_ASSERT(!bce->topStmt);
         bce->switchToProlog();
         if (!bce->emitIndex32(JSOP_DEFFUN, index))
             return false;
-        if (!UpdateSourceCoordNotes(cx, bce, pn->pn_pos.begin))
+        if (!bce->updateSourceCoordNotes(pn->pn_pos.begin))
             return false;
         bce->switchToMain();
     } else {
 #ifdef DEBUG
         BindingIter bi(bce->script);
         while (bi->name() != fun->atom())
             bi++;
         MOZ_ASSERT(bi->kind() == Binding::VARIABLE || bi->kind() == Binding::CONSTANT ||
@@ -5410,50 +5400,51 @@ BytecodeEmitter::emitDo(ParseNode *pn)
         return false;
 
     LoopStmtInfo stmtInfo(cx);
     PushLoopStatement(this, &stmtInfo, STMT_DO_LOOP, top);
 
     if (!emitLoopEntry(nullptr))
         return false;
 
-    if (!EmitTree(cx, this, pn->pn_left))
+    if (!emitTree(pn->pn_left))
         return false;
 
     /* Set loop and enclosing label update offsets, for continue. */
     ptrdiff_t off = offset();
     StmtInfoBCE *stmt = &stmtInfo;
     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(cx, this, pn->pn_right))
+    if (!emitTree(pn->pn_right))
         return false;
 
     ptrdiff_t beq = emitJump(JSOP_IFNE, top - offset());
     if (beq < 0)
         return false;
 
     if (!tryNoteList.append(JSTRY_LOOP, stackDepth, top, offset()))
         return false;
 
     /*
      * Update the annotations with the update and back edge positions, for
      * IonBuilder.
      *
      * Be careful: We must set noteIndex2 before noteIndex in case the noteIndex
      * note gets bigger.
      */
-    if (!SetSrcNoteOffset(cx, this, noteIndex2, 0, beq - top))
-        return false;
-    if (!SetSrcNoteOffset(cx, this, noteIndex, 0, 1 + (off - top)))
-        return false;
-
-    return PopStatementBCE(cx, this);
+    if (!setSrcNoteOffset(noteIndex2, 0, beq - top))
+        return false;
+    if (!setSrcNoteOffset(noteIndex, 0, 1 + (off - top)))
+        return false;
+
+    popStatement();
+    return true;
 }
 
 bool
 BytecodeEmitter::emitWhile(ParseNode *pn, ptrdiff_t top)
 {
     /*
      * Minimize bytecodes issued for one or more iterations by jumping to
      * the condition below the body and closing the loop if the condition
@@ -5477,36 +5468,37 @@ BytecodeEmitter::emitWhile(ParseNode *pn
     ptrdiff_t jmp = emitJump(JSOP_GOTO, 0);
     if (jmp < 0)
         return false;
 
     top = offset();
     if (!emitLoopHead(pn->pn_right))
         return false;
 
-    if (!EmitTree(cx, this, pn->pn_right))
-        return false;
-
-    SetJumpOffsetAt(this, jmp);
+    if (!emitTree(pn->pn_right))
+        return false;
+
+    setJumpOffsetAt(jmp);
     if (!emitLoopEntry(pn->pn_left))
         return false;
-    if (!EmitTree(cx, this, pn->pn_left))
+    if (!emitTree(pn->pn_left))
         return false;
 
     ptrdiff_t beq = emitJump(JSOP_IFNE, top - offset());
     if (beq < 0)
         return false;
 
     if (!tryNoteList.append(JSTRY_LOOP, stackDepth, top, offset()))
         return false;
 
-    if (!SetSrcNoteOffset(cx, this, noteIndex, 0, beq - jmp))
-        return false;
-
-    return PopStatementBCE(cx, this);
+    if (!setSrcNoteOffset(noteIndex, 0, beq - jmp))
+        return false;
+
+    popStatement();
+    return true;
 }
 
 bool
 BytecodeEmitter::emitBreak(PropertyName *label)
 {
     StmtInfoBCE *stmt = topStmt;
     SrcNoteType noteType;
     if (label) {
@@ -5551,27 +5543,27 @@ InTryBlockWithFinally(BytecodeEmitter *b
             return true;
     }
     return false;
 }
 
 bool
 BytecodeEmitter::emitReturn(ParseNode *pn)
 {
-    if (!UpdateSourceCoordNotes(cx, this, pn->pn_pos.begin))
+    if (!updateSourceCoordNotes(pn->pn_pos.begin))
         return false;
 
     if (sc->isFunctionBox() && sc->asFunctionBox()->isStarGenerator()) {
         if (!emitPrepareIteratorResult())
             return false;
     }
 
     /* Push a return value */
     if (ParseNode *pn2 = pn->pn_left) {
-        if (!EmitTree(cx, this, pn2))
+        if (!emitTree(pn2))
             return false;
     } else {
         /* No explicit return value provided */
         if (!emit1(JSOP_UNDEFINED))
             return false;
     }
 
     if (sc->isFunctionBox() && sc->asFunctionBox()->isStarGenerator()) {
@@ -5595,17 +5587,17 @@ BytecodeEmitter::emitReturn(ParseNode *p
     bool isGenerator = sc->isFunctionBox() && sc->asFunctionBox()->isGenerator();
     bool useGenRVal = false;
     if (isGenerator) {
         if (sc->asFunctionBox()->isStarGenerator() && InTryBlockWithFinally(this)) {
             // Emit JSOP_SETALIASEDVAR .genrval to store the return value on the
             // scope chain, so it's not lost when we yield in a finally block.
             useGenRVal = true;
             MOZ_ASSERT(pn->pn_right);
-            if (!EmitTree(cx, this, pn->pn_right))
+            if (!emitTree(pn->pn_right))
                 return false;
             if (!emit1(JSOP_POP))
                 return false;
         } else {
             if (!emit1(JSOP_SETRVAL))
                 return false;
         }
     } else {
@@ -5651,31 +5643,31 @@ BytecodeEmitter::emitYield(ParseNode *pn
     MOZ_ASSERT(sc->isFunctionBox());
 
     if (pn->getOp() == JSOP_YIELD) {
         if (sc->asFunctionBox()->isStarGenerator()) {
             if (!emitPrepareIteratorResult())
                 return false;
         }
         if (pn->pn_left) {
-            if (!EmitTree(cx, this, pn->pn_left))
+            if (!emitTree(pn->pn_left))
                 return false;
         } else {
             if (!emit1(JSOP_UNDEFINED))
                 return false;
         }
         if (sc->asFunctionBox()->isStarGenerator()) {
             if (!emitFinishIteratorResult(false))
                 return false;
         }
     } else {
         MOZ_ASSERT(pn->getOp() == JSOP_INITIALYIELD);
     }
 
-    if (!EmitTree(cx, this, pn->pn_right))
+    if (!emitTree(pn->pn_right))
         return false;
 
     if (!emitYieldOp(pn->getOp()))
         return false;
 
     if (pn->getOp() == JSOP_INITIALYIELD && !emit1(JSOP_POP))
         return false;
 
@@ -5683,17 +5675,17 @@ BytecodeEmitter::emitYield(ParseNode *pn
 }
 
 bool
 BytecodeEmitter::emitYieldStar(ParseNode *iter, ParseNode *gen)
 {
     MOZ_ASSERT(sc->isFunctionBox());
     MOZ_ASSERT(sc->asFunctionBox()->isStarGenerator());
 
-    if (!EmitTree(cx, this, iter))                               // ITERABLE
+    if (!emitTree(iter))                                         // ITERABLE
         return false;
     if (!emitIterator())                                         // ITER
         return false;
 
     // Initial send value is undefined.
     if (!emit1(JSOP_UNDEFINED))                                  // ITER RECEIVED
         return false;
 
@@ -5701,33 +5693,33 @@ BytecodeEmitter::emitYieldStar(ParseNode
     MOZ_ASSERT(depth >= 2);
 
     ptrdiff_t initialSend = -1;
     if (!emitBackPatchOp(&initialSend))                          // goto initialSend
         return false;
 
     // Try prologue.                                             // ITER RESULT
     StmtInfoBCE stmtInfo(cx);
-    PushStatementBCE(this, &stmtInfo, STMT_TRY, offset());
+    pushStatement(&stmtInfo, STMT_TRY, offset());
     ptrdiff_t noteIndex = NewSrcNote(cx, this, SRC_TRY);
     ptrdiff_t tryStart = offset();                               // tryStart:
     if (noteIndex < 0 || !emit1(JSOP_TRY))
         return false;
     MOZ_ASSERT(this->stackDepth == depth);
 
     // Load the generator object.
-    if (!EmitTree(cx, this, gen))                                // ITER RESULT GENOBJ
+    if (!emitTree(gen))                                          // ITER RESULT GENOBJ
         return false;
 
     // Yield RESULT as-is, without re-boxing.
     if (!emitYieldOp(JSOP_YIELD))                                // ITER RECEIVED
         return false;
 
     // Try epilogue.
-    if (!SetSrcNoteOffset(cx, this, noteIndex, 0, offset() - tryStart))
+    if (!setSrcNoteOffset(noteIndex, 0, offset() - tryStart))
         return false;
     ptrdiff_t subsequentSend = -1;
     if (!emitBackPatchOp(&subsequentSend))                       // goto subsequentSend
         return false;
     ptrdiff_t tryEnd = offset();                                 // tryEnd:
 
     // Catch location.
     stackDepth = uint32_t(depth);                                // ITER RESULT
@@ -5750,17 +5742,17 @@ BytecodeEmitter::emitYieldStar(ParseNode
     ptrdiff_t checkThrow = emitJump(JSOP_IFNE, 0);               // EXCEPTION ITER
     if (checkThrow < 0)
         return false;
     if (!emit1(JSOP_POP))                                        // EXCEPTION
         return false;
     if (!emit1(JSOP_THROW))                                      // throw EXCEPTION
         return false;
 
-    SetJumpOffsetAt(this, checkThrow);                           // delegate:
+    setJumpOffsetAt(checkThrow);                                 // delegate:
     // RESULT = ITER.throw(EXCEPTION)                            // EXCEPTION ITER
     stackDepth = uint32_t(depth);
     if (!emit1(JSOP_DUP))                                        // EXCEPTION ITER ITER
         return false;
     if (!emit1(JSOP_DUP))                                        // EXCEPTION ITER ITER ITER
         return false;
     if (!emitAtomOp(cx->names().throw_, JSOP_CALLPROP))          // EXCEPTION ITER ITER THROW
         return false;
@@ -5772,18 +5764,18 @@ BytecodeEmitter::emitYieldStar(ParseNode
         return false;
     checkTypeSet(JSOP_CALL);
     MOZ_ASSERT(this->stackDepth == depth);
     ptrdiff_t checkResult = -1;
     if (!emitBackPatchOp(&checkResult))                          // goto checkResult
         return false;
 
     // Catch epilogue.
-    if (!PopStatementBCE(cx, this))
-        return false;
+    popStatement();
+
     // This is a peace offering to ReconstructPCStack.  See the note in EmitTry.
     if (!emit1(JSOP_NOP))
         return false;
     if (!tryNoteList.append(JSTRY_CATCH, depth, tryStart + JSOP_TRY_LENGTH, tryEnd))
         return false;
 
     // After the try/catch block: send the received value to the iterator.
     backPatch(initialSend, code().end(), JSOP_GOTO);  // initialSend:
@@ -5833,41 +5825,42 @@ BytecodeEmitter::emitYieldStar(ParseNode
 }
 
 bool
 BytecodeEmitter::emitStatementList(ParseNode *pn, ptrdiff_t top)
 {
     MOZ_ASSERT(pn->isArity(PN_LIST));
 
     StmtInfoBCE stmtInfo(cx);
-    PushStatementBCE(this, &stmtInfo, STMT_BLOCK, top);
+    pushStatement(&stmtInfo, STMT_BLOCK, top);
 
     ParseNode *pnchild = pn->pn_head;
 
     if (pn->pn_xflags & PNX_DESTRUCT)
         pnchild = pnchild->pn_next;
 
     for (ParseNode *pn2 = pnchild; pn2; pn2 = pn2->pn_next) {
-        if (!EmitTree(cx, this, pn2))
-            return false;
-    }
-
-    return PopStatementBCE(cx, this);
+        if (!emitTree(pn2))
+            return false;
+    }
+
+    popStatement();
+    return true;
 }
 
 bool
 BytecodeEmitter::emitStatement(ParseNode *pn)
 {
     MOZ_ASSERT(pn->isKind(PNK_SEMI));
 
     ParseNode *pn2 = pn->pn_kid;
     if (!pn2)
         return true;
 
-    if (!UpdateSourceCoordNotes(cx, this, pn->pn_pos.begin))
+    if (!updateSourceCoordNotes(pn->pn_pos.begin))
         return false;
 
     /*
      * Top-level or called-from-a-native JS_Execute/EvaluateScript,
      * debugger, and eval frames may need the value of the ultimate
      * expression statement as the script's result, despite the fact
      * that it appears useless to the compiler.
      *
@@ -5884,31 +5877,31 @@ BytecodeEmitter::emitStatement(ParseNode
     /* Don't eliminate expressions with side effects. */
     if (!useful) {
         if (!CheckSideEffects(cx, this, pn2, &useful))
             return false;
 
         /*
          * Don't eliminate apparently useless expressions if they are
          * labeled expression statements.  The pc->topStmt->update test
-         * catches the case where we are nesting in EmitTree for a labeled
+         * catches the case where we are nesting in emitTree for a labeled
          * compound statement.
          */
         if (topStmt &&
             topStmt->type == STMT_LABEL &&
             topStmt->update >= offset())
         {
             useful = true;
         }
     }
 
     if (useful) {
         JSOp op = wantval ? JSOP_SETRVAL : JSOP_POP;
         MOZ_ASSERT_IF(pn2->isKind(PNK_ASSIGN), pn2->isOp(JSOP_NOP));
-        if (!EmitTree(cx, this, pn2))
+        if (!emitTree(pn2))
             return false;
         if (!emit1(op))
             return false;
     } else if (pn->isDirectivePrologueMember()) {
         // Don't complain about directive prologue members; just don't emit
         // their code.
     } else {
         if (JSAtom *atom = pn->isStringExprStatement()) {
@@ -5949,17 +5942,17 @@ BytecodeEmitter::emitDelete(ParseNode *p
 {
     /*
      * Under ECMA 3, deleting a non-reference returns true -- but alas we
      * must evaluate the operand if it appears it might have side effects.
      */
     ParseNode *pn2 = pn->pn_kid;
     switch (pn2->getKind()) {
       case PNK_NAME:
-        if (!BindNameToSlot(cx, this, pn2))
+        if (!bindNameToSlot(pn2))
             return false;
         if (!emitAtomOp(pn2, pn2->getOp()))
             return false;
         break;
       case PNK_DOT:
       {
         JSOp delOp = sc->strict() ? JSOP_STRICTDELPROP : JSOP_DELPROP;
         if (!emitPropOp(pn2, delOp))
@@ -5980,17 +5973,17 @@ BytecodeEmitter::emitDelete(ParseNode *p
          * to foo(), true (a comma expression).
          */
         bool useful = false;
         if (!CheckSideEffects(cx, this, pn2, &useful))
             return false;
 
         if (useful) {
             MOZ_ASSERT_IF(pn2->isKind(PNK_CALL), !(pn2->pn_xflags & PNX_SETCALL));
-            if (!EmitTree(cx, this, pn2))
+            if (!emitTree(pn2))
                 return false;
             if (!emit1(JSOP_POP))
                 return false;
         }
 
         if (!emit1(JSOP_TRUE))
             return false;
       }
@@ -6013,28 +6006,28 @@ BytecodeEmitter::emitSelfHostedCallFunct
     // emitting of args below is disabled by setting emitArgs to false.
     if (pn->pn_count < 3) {
         reportError(pn, JSMSG_MORE_ARGS_NEEDED, "callFunction", "1", "s");
         return false;
     }
 
     ParseNode *pn2 = pn->pn_head;
     ParseNode *funNode = pn2->pn_next;
-    if (!EmitTree(cx, this, funNode))
+    if (!emitTree(funNode))
         return false;
 
     ParseNode *thisArg = funNode->pn_next;
-    if (!EmitTree(cx, this, thisArg))
+    if (!emitTree(thisArg))
         return false;
 
     bool oldEmittingForInit = emittingForInit;
     emittingForInit = false;
 
     for (ParseNode *argpn = thisArg->pn_next; argpn; argpn = argpn->pn_next) {
-        if (!EmitTree(cx, this, argpn))
+        if (!emitTree(argpn))
             return false;
     }
 
     emittingForInit = oldEmittingForInit;
 
     uint32_t argc = pn->pn_count - 3;
     if (!emitCall(pn->getOp(), argc))
         return false;
@@ -6050,21 +6043,21 @@ BytecodeEmitter::emitSelfHostedResumeGen
     if (pn->pn_count != 4) {
         reportError(pn, JSMSG_MORE_ARGS_NEEDED, "resumeGenerator", "1", "s");
         return false;
     }
 
     ParseNode *funNode = pn->pn_head;  // The resumeGenerator node.
 
     ParseNode *genNode = funNode->pn_next;
-    if (!EmitTree(cx, this, genNode))
+    if (!emitTree(genNode))
         return false;
 
     ParseNode *valNode = genNode->pn_next;
-    if (!EmitTree(cx, this, valNode))
+    if (!emitTree(valNode))
         return false;
 
     ParseNode *kindNode = valNode->pn_next;
     MOZ_ASSERT(kindNode->isKind(PNK_STRING));
     uint16_t operand = GeneratorObject::getResumeKind(cx, kindNode->pn_atom);
     MOZ_ASSERT(!kindNode->pn_next);
 
     if (!emitCall(JSOP_RESUME, operand))
@@ -6153,27 +6146,27 @@ BytecodeEmitter::emitCallOrNew(ParseNode
          * backend optimizations. Note that this does not depend on the
          * lambda being invoked at most once (it may be named or be
          * accessed via foo.caller indirection), as multiple executions
          * will just cause the inner scripts to be repeatedly cloned.
          */
         MOZ_ASSERT(!emittingRunOnceLambda);
         if (checkSingletonContext() || (!isInLoop() && isRunOnceLambda())) {
             emittingRunOnceLambda = true;
-            if (!EmitTree(cx, this, pn2))
+            if (!emitTree(pn2))
                 return false;
             emittingRunOnceLambda = false;
         } else {
-            if (!EmitTree(cx, this, pn2))
+            if (!emitTree(pn2))
                 return false;
         }
         callop = false;
         break;
       default:
-        if (!EmitTree(cx, this, pn2))
+        if (!emitTree(pn2))
             return false;
         callop = false;             /* trigger JSOP_UNDEFINED after */
         break;
     }
     if (!callop) {
         JSOp thisop = pn->isKind(PNK_GENEXP) ? JSOP_THIS : JSOP_UNDEFINED;
         if (!emit1(thisop))
             return false;
@@ -6183,17 +6176,17 @@ BytecodeEmitter::emitCallOrNew(ParseNode
      * Emit code for each argument in order, then emit the JSOP_*CALL or
      * JSOP_NEW bytecode with a two-byte immediate telling how many args
      * were pushed on the operand stack.
      */
     bool oldEmittingForInit = emittingForInit;
     emittingForInit = false;
     if (!spread) {
         for (ParseNode *pn3 = pn2->pn_next; pn3; pn3 = pn3->pn_next) {
-            if (!EmitTree(cx, this, pn3))
+            if (!emitTree(pn3))
                 return false;
         }
     } else {
         if (!emitArray(pn2->pn_next, argc))
             return false;
     }
     emittingForInit = oldEmittingForInit;
 
@@ -6233,38 +6226,38 @@ BytecodeEmitter::emitLogical(ParseNode *
      * The jump goes around the right operand evaluation.
      *
      * 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(cx, this, pn2))
+    if (!emitTree(pn2))
         return false;
     ptrdiff_t top = emitJump(JSOP_BACKPATCH, 0);
     if (top < 0)
         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(cx, this, pn2))
+        if (!emitTree(pn2))
             return false;
         ptrdiff_t off = emitJump(JSOP_BACKPATCH, 0);
         if (off < 0)
             return false;
         if (!emit1(JSOP_POP))
             return false;
         SET_JUMP_OFFSET(code(jmp), off - jmp);
         jmp = off;
     }
-    if (!EmitTree(cx, this, pn2))
+    if (!emitTree(pn2))
         return false;
 
     pn2 = pn->pn_head;
     ptrdiff_t off = offset();
     do {
         jsbytecode *pc = code(top);
         ptrdiff_t tmp = GET_JUMP_OFFSET(pc);
         SET_JUMP_OFFSET(pc, off - top);
@@ -6288,23 +6281,23 @@ BytecodeEmitter::emitIncOrDec(ParseNode 
             return false;
         break;
       case PNK_ELEM:
         if (!emitElemIncDec(pn))
             return false;
         break;
       case PNK_CALL:
         MOZ_ASSERT(pn2->pn_xflags & PNX_SETCALL);
-        if (!EmitTree(cx, this, pn2))
+        if (!emitTree(pn2))
             return false;
         break;
       default:
         MOZ_ASSERT(pn2->isKind(PNK_NAME));
         pn2->setOp(JSOP_SETNAME);
-        if (!BindNameToSlot(cx, this, pn2))
+        if (!bindNameToSlot(pn2))
             return false;
         JSOp op = pn2->getOp();
         bool maySet;
         switch (op) {
           case JSOP_SETLOCAL:
           case JSOP_SETARG:
           case JSOP_SETALIASEDVAR:
           case JSOP_SETNAME:
@@ -6370,95 +6363,95 @@ EmitLabeledStatement(ExclusiveContext *c
         return false;
 
     ptrdiff_t top = bce->emitJump(JSOP_LABEL, 0);
     if (top < 0)
         return false;
 
     /* Emit code for the labeled statement. */
     StmtInfoBCE stmtInfo(cx);
-    PushStatementBCE(bce, &stmtInfo, STMT_LABEL, bce->offset());
+    bce->pushStatement(&stmtInfo, STMT_LABEL, bce->offset());
     stmtInfo.label = pn->label();
-    if (!EmitTree(cx, bce, pn->statement()))
-        return false;
-    if (!PopStatementBCE(cx, bce))
-        return false;
+    if (!bce->emitTree(pn->statement()))
+        return false;
+    bce->popStatement();
 
     /* Patch the JSOP_LABEL offset. */
-    SetJumpOffsetAt(bce, top);
+    bce->setJumpOffsetAt(top);
     return true;
 }
 
 static bool
 EmitSyntheticStatements(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
 {
     MOZ_ASSERT(pn->isArity(PN_LIST));
     StmtInfoBCE stmtInfo(cx);
-    PushStatementBCE(bce, &stmtInfo, STMT_SEQ, top);
+    bce->pushStatement(&stmtInfo, STMT_SEQ, top);
     ParseNode *pn2 = pn->pn_head;
     if (pn->pn_xflags & PNX_DESTRUCT)
         pn2 = pn2->pn_next;
     for (; pn2; pn2 = pn2->pn_next) {
-        if (!EmitTree(cx, bce, pn2))
-            return false;
-    }
-    return PopStatementBCE(cx, bce);
+        if (!bce->emitTree(pn2))
+            return false;
+    }
+    bce->popStatement();
+    return true;
 }
 
 bool
 BytecodeEmitter::emitConditionalExpression(ConditionalExpression &conditional)
 {
     /* Emit the condition, then branch if false to the else part. */
-    if (!EmitTree(cx, this, &conditional.condition()))
+    if (!emitTree(&conditional.condition()))
         return false;
 
     ptrdiff_t noteIndex = NewSrcNote(cx, this, SRC_COND);
     if (noteIndex < 0)
         return false;
 
     ptrdiff_t beq = emitJump(JSOP_IFEQ, 0);
-    if (beq < 0 || !EmitTree(cx, this, &conditional.thenExpression()))
+    if (beq < 0 || !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)
         return false;
-    SetJumpOffsetAt(this, beq);
+    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.
      *
      * Failing to do this will foil code, such as let expression and block
      * code generation, which must use the stack depth to compute local
      * stack indexes correctly.
      */
     MOZ_ASSERT(stackDepth > 0);
     stackDepth--;
-    if (!EmitTree(cx, this, &conditional.elseExpression()))
-        return false;
-    SetJumpOffsetAt(this, jmp);
-    return SetSrcNoteOffset(cx, this, noteIndex, 0, jmp - beq);
+    if (!emitTree(&conditional.elseExpression()))
+        return false;
+    setJumpOffsetAt(jmp);
+    return setSrcNoteOffset(noteIndex, 0, jmp - beq);
 }
 
 bool
 BytecodeEmitter::emitPropertyList(ParseNode *pn, MutableHandlePlainObject objp, PropListType type)
 {
     for (ParseNode *propdef = pn->pn_head; propdef; propdef = propdef->pn_next) {
-        if (!UpdateSourceCoordNotes(cx, this, propdef->pn_pos.begin))
+        if (!updateSourceCoordNotes(propdef->pn_pos.begin))
             return false;
 
         // Handle __proto__: v specially because *only* this form, and no other
         // involving "__proto__", performs [[Prototype]] mutation.
         if (propdef->isKind(PNK_MUTATEPROTO)) {
             MOZ_ASSERT(type == ObjectLiteral);
-            if (!EmitTree(cx, this, propdef->pn_kid))
+            if (!emitTree(propdef->pn_kid))
                 return false;
             objp.set(nullptr);
             if (!emit1(JSOP_MUTATEPROTO))
                 return false;
             continue;
         }
 
         bool extraPop = false;
@@ -6482,29 +6475,29 @@ BytecodeEmitter::emitPropertyList(ParseN
             if (type == ClassBody && key->pn_atom == cx->names().constructor)
                 continue;
 
             // The parser already checked for atoms representing indexes and
             // used PNK_NUMBER instead, but also watch for ids which TI treats
             // as indexes for simpliciation of downstream analysis.
             jsid id = NameToId(key->pn_atom->asPropertyName());
             if (id != IdToTypeId(id)) {
-                if (!EmitTree(cx, this, key))
+                if (!emitTree(key))
                     return false;
                 isIndex = true;
             }
         } else {
             MOZ_ASSERT(key->isKind(PNK_COMPUTED_NAME));
-            if (!EmitTree(cx, this, key->pn_kid))
+            if (!emitTree(key->pn_kid))
                 return false;
             isIndex = true;
         }
 
         /* Emit code for the property initializer. */
-        if (!EmitTree(cx, this, propdef->pn_right))
+        if (!emitTree(propdef->pn_right))
             return false;
 
         JSOp op = propdef->getOp();
         MOZ_ASSERT(op == JSOP_INITPROP ||
                    op == JSOP_INITPROP_GETTER ||
                    op == JSOP_INITPROP_SETTER);
 
         if (op == JSOP_INITPROP_GETTER || op == JSOP_INITPROP_SETTER)
@@ -6617,17 +6610,17 @@ BytecodeEmitter::emitArrayComp(ParseNode
     /*
      * Pass the new array's stack index to the PNK_ARRAYPUSH case via
      * arrayCompDepth, then simply traverse the PNK_FOR node and
      * its kids under pn2 to generate this comprehension.
      */
     MOZ_ASSERT(stackDepth > 0);
     uint32_t saveDepth = arrayCompDepth;
     arrayCompDepth = (uint32_t) (stackDepth - 1);
-    if (!EmitTree(cx, this, pn->pn_head))
+    if (!emitTree(pn->pn_head))
         return false;
     arrayCompDepth = saveDepth;
 
     return true;
 }
 
 bool
 BytecodeEmitter::emitSpread()
@@ -6667,24 +6660,24 @@ BytecodeEmitter::emitArray(ParseNode *pn
     jsatomid atomIndex;
     bool afterSpread = false;
     for (atomIndex = 0; pn2; atomIndex++, pn2 = pn2->pn_next) {
         if (!afterSpread && pn2->isKind(PNK_SPREAD)) {
             afterSpread = true;
             if (!emitNumberOp(atomIndex))                           // ARRAY INDEX
                 return false;
         }
-        if (!UpdateSourceCoordNotes(cx, this, pn2->pn_pos.begin))
+        if (!updateSourceCoordNotes(pn2->pn_pos.begin))
             return false;
         if (pn2->isKind(PNK_ELISION)) {
             if (!emit1(JSOP_HOLE))
                 return false;
         } else {
             ParseNode *expr = pn2->isKind(PNK_SPREAD) ? pn2->pn_kid : pn2;
-            if (!EmitTree(cx, this, expr))                               // ARRAY INDEX? VALUE
+            if (!emitTree(expr))                                         // ARRAY INDEX? VALUE
                 return false;
         }
         if (pn2->isKind(PNK_SPREAD)) {
             if (!emitIterator())                                         // ARRAY INDEX ITER
                 return false;
             if (!emit2(JSOP_PICK, (jsbytecode)2))                        // INDEX ITER ARRAY
                 return false;
             if (!emit2(JSOP_PICK, (jsbytecode)2))                        // ITER ARRAY INDEX
@@ -6707,59 +6700,59 @@ BytecodeEmitter::emitArray(ParseNode *pn
             return false;
     }
     return true;
 }
 
 bool
 BytecodeEmitter::emitUnary(ParseNode *pn)
 {
-    if (!UpdateSourceCoordNotes(cx, this, pn->pn_pos.begin))
+    if (!updateSourceCoordNotes(pn->pn_pos.begin))
         return false;
 
     /* Unary op, including unary +/-. */
     JSOp op = pn->getOp();
     ParseNode *pn2 = pn->pn_kid;
 
     if (op == JSOP_TYPEOF && !pn2->isKind(PNK_NAME))
         op = JSOP_TYPEOFEXPR;
 
     bool oldEmittingForInit = emittingForInit;
     emittingForInit = false;
-    if (!EmitTree(cx, this, pn2))
+    if (!emitTree(pn2))
         return false;
 
     emittingForInit = oldEmittingForInit;
     return emit1(op);
 }
 
 bool
 BytecodeEmitter::emitDefaults(ParseNode *pn)
 {
     MOZ_ASSERT(pn->isKind(PNK_ARGSBODY));
 
     ParseNode *arg, *pnlast = pn->last();
     for (arg = pn->pn_head; arg != pnlast; arg = arg->pn_next) {
         if (!(arg->pn_dflags & PND_DEFAULT))
             continue;
-        if (!BindNameToSlot(cx, this, arg))
+        if (!bindNameToSlot(arg))
             return false;
         if (!emitVarOp(arg, JSOP_GETARG))
             return false;
         if (!emit1(JSOP_UNDEFINED))
             return false;
         if (!emit1(JSOP_STRICTEQ))
             return false;
         // Emit source note to enable ion compilation.
         if (NewSrcNote(cx, this, SRC_IF) < 0)
             return false;
         ptrdiff_t jump = emitJump(JSOP_IFEQ, 0);
         if (jump < 0)
             return false;
-        if (!EmitTree(cx, this, arg->expr()))
+        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);
     }
 
@@ -6774,17 +6767,17 @@ BytecodeEmitter::emitLexicalInitializati
      * This function is significantly more complicated than it needs to be.
      * In fact, it shouldn't exist at all. This should all be a
      * JSOP_INITLEXIAL. Unfortunately, toplevel lexicals are broken, and
      * are emitted as vars :(. As such, we have to do these ministrations to
      * to make sure that all works properly.
      */
     MOZ_ASSERT(pn->isKind(PNK_NAME));
 
-    if (!BindNameToSlot(cx, this, pn))
+    if (!bindNameToSlot(pn))
         return false;
 
     jsatomid atomIndex;
     if (!maybeEmitVarDecl(globalDefOp, pn, &atomIndex))
         return false;
 
     if (pn->getOp() != JSOP_INITLEXICAL) {
         bool global = js_CodeSpec[pn->getOp()].format & JOF_GNAME;
@@ -6834,17 +6827,17 @@ BytecodeEmitter::emitClass(ParseNode *pn
 
     StmtInfoBCE stmtInfo(cx);
     if (names) {
         if (!EnterBlockScope(cx, this, &stmtInfo, classNode.scopeObject(), JSOP_UNINITIALIZED))
             return false;
     }
 
     if (heritageExpression) {
-        if (!EmitTree(cx, this, heritageExpression))
+        if (!emitTree(heritageExpression))
             return false;
         if (!emit1(JSOP_CLASSHERITAGE))
             return false;
     }
 
     if (!EmitFunc(cx, this, constructor, !!heritageExpression))
         return false;
 
@@ -6895,230 +6888,230 @@ BytecodeEmitter::emitClass(ParseNode *pn
     }
 
     MOZ_ALWAYS_TRUE(sc->setLocalStrictMode(savedStrictness));
 
     return true;
 }
 
 bool
-frontend::EmitTree(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
+BytecodeEmitter::emitTree(ParseNode *pn)
 {
     JS_CHECK_RECURSION(cx, return false);
 
-    EmitLevelManager elm(bce);
+    EmitLevelManager elm(this);
 
     bool ok = true;
-    ptrdiff_t top = bce->offset();
+    ptrdiff_t top = offset();
     pn->pn_offset = top;
 
     /* Emit notes to tell the current bytecode's source line number. */
-    if (!UpdateLineNumberNotes(cx, bce, pn->pn_pos.begin))
+    if (!updateLineNumberNotes(pn->pn_pos.begin))
         return false;
 
     switch (pn->getKind()) {
       case PNK_FUNCTION:
-        ok = EmitFunc(cx, bce, pn);
+        ok = EmitFunc(cx, this, pn);
         break;
 
       case PNK_ARGSBODY:
       {
-        RootedFunction fun(cx, bce->sc->asFunctionBox()->function());
+        RootedFunction fun(cx, sc->asFunctionBox()->function());
         ParseNode *pnlast = pn->last();
 
         // Carefully emit everything in the right order:
         // 1. Destructuring
         // 2. Defaults
         // 3. Functions
         ParseNode *pnchild = pnlast->pn_head;
         if (pnlast->pn_xflags & PNX_DESTRUCT) {
             // Assign the destructuring arguments before defining any functions,
             // see bug 419662.
             MOZ_ASSERT(pnchild->isKind(PNK_SEMI));
             MOZ_ASSERT(pnchild->pn_kid->isKind(PNK_VAR) || pnchild->pn_kid->isKind(PNK_GLOBALCONST));
-            if (!EmitTree(cx, bce, pnchild))
+            if (!emitTree(pnchild))
                 return false;
             pnchild = pnchild->pn_next;
         }
-        bool hasDefaults = bce->sc->asFunctionBox()->hasDefaults();
+        bool hasDefaults = sc->asFunctionBox()->hasDefaults();
         if (hasDefaults) {
             ParseNode *rest = nullptr;
             bool restIsDefn = false;
             if (fun->hasRest()) {
-                MOZ_ASSERT(!bce->sc->asFunctionBox()->argumentsHasLocalBinding());
+                MOZ_ASSERT(!sc->asFunctionBox()->argumentsHasLocalBinding());
 
                 // Defaults with a rest parameter need special handling. The
                 // rest parameter needs to be undefined while defaults are being
                 // processed. To do this, we create the rest argument and let it
                 // sit on the stack while processing defaults. The rest
                 // parameter's slot is set to undefined for the course of
                 // default processing.
                 rest = pn->pn_head;
                 while (rest->pn_next != pnlast)
                     rest = rest->pn_next;
                 restIsDefn = rest->isDefn();
-                if (!bce->emit1(JSOP_REST))
+                if (!emit1(JSOP_REST))
                     return false;
-                bce->checkTypeSet(JSOP_REST);
+                checkTypeSet(JSOP_REST);
 
                 // Only set the rest parameter if it's not aliased by a nested
                 // function in the body.
                 if (restIsDefn) {
-                    if (!bce->emit1(JSOP_UNDEFINED))
+                    if (!emit1(JSOP_UNDEFINED))
                         return false;
-                    if (!BindNameToSlot(cx, bce, rest))
+                    if (!bindNameToSlot(rest))
                         return false;
-                    if (!bce->emitVarOp(rest, JSOP_SETARG))
+                    if (!emitVarOp(rest, JSOP_SETARG))
                         return false;
-                    if (!bce->emit1(JSOP_POP))
+                    if (!emit1(JSOP_POP))
                         return false;
                 }
             }
-            if (!bce->emitDefaults(pn))
+            if (!emitDefaults(pn))
                 return false;
             if (fun->hasRest()) {
-                if (restIsDefn && !bce->emitVarOp(rest, JSOP_SETARG))
+                if (restIsDefn && !emitVarOp(rest, JSOP_SETARG))
                     return false;
-                if (!bce->emit1(JSOP_POP))
+                if (!emit1(JSOP_POP))
                     return false;
             }
         }
         for (ParseNode *pn2 = pn->pn_head; pn2 != pnlast; pn2 = pn2->pn_next) {
             // Only bind the parameter if it's not aliased by a nested function
             // in the body.
             if (!pn2->isDefn())
                 continue;
-            if (!BindNameToSlot(cx, bce, pn2))
+            if (!bindNameToSlot(pn2))
                 return false;
             if (pn2->pn_next == pnlast && fun->hasRest() && !hasDefaults) {
                 // Fill rest parameter. We handled the case with defaults above.
-                MOZ_ASSERT(!bce->sc->asFunctionBox()->argumentsHasLocalBinding());
-                bce->switchToProlog();
-                if (!bce->emit1(JSOP_REST))
+                MOZ_ASSERT(!sc->asFunctionBox()->argumentsHasLocalBinding());
+                switchToProlog();
+                if (!emit1(JSOP_REST))
                     return false;
-                bce->checkTypeSet(JSOP_REST);
-                if (!bce->emitVarOp(pn2, JSOP_SETARG))
+                checkTypeSet(JSOP_REST);
+                if (!emitVarOp(pn2, JSOP_SETARG))
                     return false;
-                if (!bce->emit1(JSOP_POP))
+                if (!emit1(JSOP_POP))
                     return false;
-                bce->switchToMain();
+                switchToMain();
             }
         }
         if (pnlast->pn_xflags & PNX_FUNCDEFS) {
             // This block contains top-level function definitions. To ensure
             // that we emit the bytecode defining them before the rest of code
             // in the block we use a separate pass over functions. During the
             // main pass later the emitter will add JSOP_NOP with source notes
             // for the function to preserve the original functions position
             // when decompiling.
             //
             // Currently this is used only for functions, as compile-as-we go
             // mode for scripts does not allow separate emitter passes.
             for (ParseNode *pn2 = pnchild; pn2; pn2 = pn2->pn_next) {
                 if (pn2->isKind(PNK_FUNCTION) && pn2->functionIsHoisted()) {
-                    if (!EmitTree(cx, bce, pn2))
+                    if (!emitTree(pn2))
                         return false;
                 }
             }
         }
-        ok = EmitTree(cx, bce, pnlast);
+        ok = emitTree(pnlast);
         break;
       }
 
       case PNK_IF:
-        ok = bce->emitIf(pn);
+        ok = emitIf(pn);
         break;
 
       case PNK_SWITCH:
-        ok = bce->emitSwitch(pn);
+        ok = emitSwitch(pn);
         break;
 
       case PNK_WHILE:
-        ok = bce->emitWhile(pn, top);
+        ok = emitWhile(pn, top);
         break;
 
       case PNK_DOWHILE:
-        ok = bce->emitDo(pn);
+        ok = emitDo(pn);
         break;
 
       case PNK_FOR:
-        ok = bce->emitFor(pn, top);
+        ok = emitFor(pn, top);
         break;
 
       case PNK_BREAK:
-        ok = bce->emitBreak(pn->as<BreakStatement>().label());
+        ok = emitBreak(pn->as<BreakStatement>().label());
         break;
 
       case PNK_CONTINUE:
-        ok = bce->emitContinue(pn->as<ContinueStatement>().label());
+        ok = emitContinue(pn->as<ContinueStatement>().label());
         break;
 
       case PNK_WITH:
-        ok = bce->emitWith(pn);
+        ok = emitWith(pn);
         break;
 
       case PNK_TRY:
-        if (!bce->emitTry(pn))
+        if (!emitTry(pn))
             return false;
         break;
 
       case PNK_CATCH:
-        if (!bce->emitCatch(pn))
+        if (!emitCatch(pn))
             return false;
         break;
 
       case PNK_VAR:
       case PNK_GLOBALCONST:
-        if (!bce->emitVariables(pn, InitializeVars))
+        if (!emitVariables(pn, InitializeVars))
             return false;
         break;
 
       case PNK_RETURN:
-        ok = bce->emitReturn(pn);
+        ok = emitReturn(pn);
         break;
 
       case PNK_YIELD_STAR:
-        ok = bce->emitYieldStar(pn->pn_left, pn->pn_right);
+        ok = emitYieldStar(pn->pn_left, pn->pn_right);
         break;
 
       case PNK_GENERATOR:
-        if (!bce->emit1(JSOP_GENERATOR))
+        if (!emit1(JSOP_GENERATOR))
             return false;
         break;
 
       case PNK_YIELD:
-        ok = bce->emitYield(pn);
+        ok = emitYield(pn);
         break;
 
       case PNK_STATEMENTLIST:
-        ok = bce->emitStatementList(pn, top);
+        ok = emitStatementList(pn, top);
         break;
 
       case PNK_SEQ:
-        ok = EmitSyntheticStatements(cx, bce, pn, top);
+        ok = EmitSyntheticStatements(cx, this, pn, top);
         break;
 
       case PNK_SEMI:
-        ok = bce->emitStatement(pn);
+        ok = emitStatement(pn);
         break;
 
       case PNK_LABEL:
-        ok = EmitLabeledStatement(cx, bce, &pn->as<LabeledStatement>());
+        ok = EmitLabeledStatement(cx, this, &pn->as<LabeledStatement>());
         break;
 
       case PNK_COMMA:
       {
         for (ParseNode *pn2 = pn->pn_head; ; pn2 = pn2->pn_next) {
-            if (!UpdateSourceCoordNotes(cx, bce, pn2->pn_pos.begin))
-                return false;
-            if (!EmitTree(cx, bce, pn2))
+            if (!updateSourceCoordNotes(pn2->pn_pos.begin))
+                return false;
+            if (!emitTree(pn2))
                 return false;
             if (!pn2->pn_next)
                 break;
-            if (!bce->emit1(JSOP_POP))
+            if (!emit1(JSOP_POP))
                 return false;
         }
         break;
       }
 
       case PNK_ASSIGN:
       case PNK_ADDASSIGN:
       case PNK_SUBASSIGN:
@@ -7126,27 +7119,27 @@ frontend::EmitTree(ExclusiveContext *cx,
       case PNK_BITXORASSIGN:
       case PNK_BITANDASSIGN:
       case PNK_LSHASSIGN:
       case PNK_RSHASSIGN:
       case PNK_URSHASSIGN:
       case PNK_MULASSIGN:
       case PNK_DIVASSIGN:
       case PNK_MODASSIGN:
-        if (!bce->emitAssignment(pn->pn_left, pn->getOp(), pn->pn_right))
+        if (!emitAssignment(pn->pn_left, pn->getOp(), pn->pn_right))
             return false;
         break;
 
       case PNK_CONDITIONAL:
-        ok = bce->emitConditionalExpression(pn->as<ConditionalExpression>());
+        ok = emitConditionalExpression(pn->as<ConditionalExpression>());
         break;
 
       case PNK_OR:
       case PNK_AND:
-        ok = bce->emitLogical(pn);
+        ok = emitLogical(pn);
         break;
 
       case PNK_ADD:
       case PNK_SUB:
       case PNK_BITOR:
       case PNK_BITXOR:
       case PNK_BITAND:
       case PNK_STRICTEQ:
@@ -7163,205 +7156,205 @@ frontend::EmitTree(ExclusiveContext *cx,
       case PNK_RSH:
       case PNK_URSH:
       case PNK_STAR:
       case PNK_DIV:
       case PNK_MOD: {
         MOZ_ASSERT(pn->isArity(PN_LIST));
         /* Left-associative operator chain: avoid too much recursion. */
         ParseNode *subexpr = pn->pn_head;
-        if (!EmitTree(cx, bce, subexpr))
+        if (!emitTree(subexpr))
             return false;
         JSOp op = pn->getOp();
         while ((subexpr = subexpr->pn_next) != nullptr) {
-            if (!EmitTree(cx, bce, subexpr))
-                return false;
-            if (!bce->emit1(op))
+            if (!emitTree(subexpr))
+                return false;
+            if (!emit1(op))
                 return false;
         }
         break;
       }
 
       case PNK_THROW:
       case PNK_TYPEOF:
       case PNK_VOID:
       case PNK_NOT:
       case PNK_BITNOT:
       case PNK_POS:
       case PNK_NEG:
-        ok = bce->emitUnary(pn);
+        ok = emitUnary(pn);
         break;
 
       case PNK_PREINCREMENT:
       case PNK_PREDECREMENT:
       case PNK_POSTINCREMENT:
       case PNK_POSTDECREMENT:
-        ok = bce->emitIncOrDec(pn);
+        ok = emitIncOrDec(pn);
         break;
 
       case PNK_DELETE:
-        ok = bce->emitDelete(pn);
+        ok = emitDelete(pn);
         break;
 
       case PNK_DOT:
-        ok = bce->emitPropOp(pn, JSOP_GETPROP);
+        ok = emitPropOp(pn, JSOP_GETPROP);
         break;
 
       case PNK_ELEM:
-        ok = bce->emitElemOp(pn, JSOP_GETELEM);
+        ok = emitElemOp(pn, JSOP_GETELEM);
         break;
 
       case PNK_NEW:
       case PNK_TAGGED_TEMPLATE:
       case PNK_CALL:
       case PNK_GENEXP:
-        ok = bce->emitCallOrNew(pn);
+        ok = emitCallOrNew(pn);
         break;
 
       case PNK_LEXICALSCOPE:
-        ok = EmitLexicalScope(cx, bce, pn);
+        ok = EmitLexicalScope(cx, this, pn);
         break;
 
       case PNK_LETBLOCK:
       case PNK_LETEXPR:
-        ok = EmitLet(cx, bce, pn);
+        ok = EmitLet(cx, this, pn);
         break;
 
       case PNK_CONST:
       case PNK_LET:
-        ok = bce->emitVariables(pn, InitializeVars);
+        ok = emitVariables(pn, InitializeVars);
         break;
 
       case PNK_IMPORT:
       case PNK_EXPORT:
       case PNK_EXPORT_FROM:
        // TODO: Implement emitter support for modules
-       bce->reportError(nullptr, JSMSG_MODULES_NOT_IMPLEMENTED);
+       reportError(nullptr, JSMSG_MODULES_NOT_IMPLEMENTED);
        return false;
 
       case PNK_ARRAYPUSH: {
         /*
-         * The array object's stack index is in bce->arrayCompDepth. See below
+         * The array object's stack index is in arrayCompDepth. See below
          * under the array initialiser code generator for array comprehension
          * special casing. Note that the array object is a pure stack value,
          * unaliased by blocks, so we can emitUnaliasedVarOp.
          */
-        if (!EmitTree(cx, bce, pn->pn_kid))
-            return false;
-        if (!bce->emitDupAt(bce->arrayCompDepth))
-            return false;
-        if (!bce->emit1(JSOP_ARRAYPUSH))
+        if (!emitTree(pn->pn_kid))
+            return false;
+        if (!emitDupAt(arrayCompDepth))
+            return false;
+        if (!emit1(JSOP_ARRAYPUSH))
             return false;
         break;
       }
 
       case PNK_CALLSITEOBJ:
-        ok = bce->emitCallSiteObject(pn);
+        ok = emitCallSiteObject(pn);
         break;
 
       case PNK_ARRAY:
         if (!(pn->pn_xflags & PNX_NONCONST) && pn->pn_head) {
-            if (bce->checkSingletonContext()) {
+            if (checkSingletonContext()) {
                 // Bake in the object entirely if it will only be created once.
-                ok = bce->emitSingletonInitialiser(pn);
+                ok = emitSingletonInitialiser(pn);
                 break;
             }
 
             // If the array consists entirely of primitive values, make a
             // template object with copy on write elements that can be reused
             // every time the initializer executes.
-            if (bce->emitterMode != BytecodeEmitter::SelfHosting && pn->pn_count != 0) {
+            if (emitterMode != BytecodeEmitter::SelfHosting && pn->pn_count != 0) {
                 RootedValue value(cx);
                 if (!pn->getConstantValue(cx, ParseNode::DontAllowNestedObjects, &value))
                     return false;
                 if (!value.isMagic(JS_GENERIC_MAGIC)) {
                     // Note: the group of the template object might not yet reflect
                     // that the object has copy on write elements. When the
                     // interpreter or JIT compiler fetches the template, it should
                     // use ObjectGroup::getOrFixupCopyOnWriteObject to make sure the
                     // group for the template is accurate. We don't do this here as we
                     // want to use ObjectGroup::allocationSiteGroup, which requires a
                     // finished script.
                     NativeObject *obj = &value.toObject().as<NativeObject>();
                     if (!ObjectElements::MakeElementsCopyOnWrite(cx, obj))
                         return false;
 
-                    ObjectBox *objbox = bce->parser->newObjectBox(obj);
+                    ObjectBox *objbox = parser->newObjectBox(obj);
                     if (!objbox)
                         return false;
 
-                    ok = bce->emitObjectOp(objbox, JSOP_NEWARRAY_COPYONWRITE);
+                    ok = emitObjectOp(objbox, JSOP_NEWARRAY_COPYONWRITE);
                     break;
                 }
             }
         }
 
-        ok = bce->emitArray(pn->pn_head, pn->pn_count);
+        ok = emitArray(pn->pn_head, pn->pn_count);
         break;
 
        case PNK_ARRAYCOMP:
-        ok = bce->emitArrayComp(pn);
+        ok = emitArrayComp(pn);
         break;
 
       case PNK_OBJECT:
-        ok = bce->emitObject(pn);
+        ok = emitObject(pn);
         break;
 
       case PNK_NAME:
-        if (!bce->emitNameOp(pn, false))
+        if (!emitNameOp(pn, false))
             return false;
         break;
 
       case PNK_TEMPLATE_STRING_LIST:
-        ok = bce->emitTemplateString(pn);
+        ok = emitTemplateString(pn);
         break;
 
       case PNK_TEMPLATE_STRING:
       case PNK_STRING:
-        ok = bce->emitAtomOp(pn, JSOP_STRING);
+        ok = emitAtomOp(pn, JSOP_STRING);
         break;
 
       case PNK_NUMBER:
-        ok = bce->emitNumberOp(pn->pn_dval);
+        ok = emitNumberOp(pn->pn_dval);
         break;
 
       case PNK_REGEXP:
-        ok = bce->emitRegExp(bce->regexpList.add(pn->as<RegExpLiteral>().objbox()));
+        ok = emitRegExp(regexpList.add(pn->as<RegExpLiteral>().objbox()));
         break;
 
       case PNK_TRUE:
       case PNK_FALSE:
       case PNK_THIS:
       case PNK_NULL:
-        if (!bce->emit1(pn->getOp()))
+        if (!emit1(pn->getOp()))
             return false;
         break;
 
       case PNK_DEBUGGER:
-        if (!UpdateSourceCoordNotes(cx, bce, pn->pn_pos.begin))
-            return false;
-        if (!bce->emit1(JSOP_DEBUGGER))
+        if (!updateSourceCoordNotes(pn->pn_pos.begin))
+            return false;
+        if (!emit1(JSOP_DEBUGGER))
             return false;
         break;
 
       case PNK_NOP:
         MOZ_ASSERT(pn->getArity() == PN_NULLARY);
         break;
 
       case PNK_CLASS:
-        ok = bce->emitClass(pn);
+        ok = emitClass(pn);
         break;
 
       default:
         MOZ_ASSERT(0);
     }
 
     /* bce->emitLevel == 1 means we're last on the stack, so finish up. */
-    if (ok && bce->emitLevel == 1) {
-        if (!UpdateSourceCoordNotes(cx, bce, pn->pn_pos.end))
+    if (ok && emitLevel == 1) {
+        if (!updateSourceCoordNotes(pn->pn_pos.end))
             return false;
     }
 
     return ok;
 }
 
 static int
 AllocSrcNote(ExclusiveContext *cx, SrcNotesVector &notes)
@@ -7405,50 +7398,50 @@ frontend::NewSrcNote(ExclusiveContext *c
             if (index < 0)
                 return -1;
         } while (delta >= SN_DELTA_LIMIT);
     }
 
     /*
      * Initialize type and delta, then allocate the minimum number of notes
      * needed for type's arity.  Usually, we won't need more, but if an offset
-     * does take two bytes, SetSrcNoteOffset will grow notes.
+     * does take two bytes, setSrcNoteOffset will grow notes.
      */
     SN_MAKE_NOTE(&notes[index], type, delta);
     for (int n = (int)js_SrcNoteSpec[type].arity; n > 0; n--) {
         if (NewSrcNote(cx, bce, SRC_NULL) < 0)
             return -1;
     }
     return index;
 }
 
 int
 frontend::NewSrcNote2(ExclusiveContext *cx, BytecodeEmitter *bce, SrcNoteType type, ptrdiff_t offset)
 {
     int index;
 
     index = NewSrcNote(cx, bce, type);
     if (index >= 0) {
-        if (!SetSrcNoteOffset(cx, bce, index, 0, offset))
+        if (!bce->setSrcNoteOffset(index, 0, offset))
             return -1;
     }
     return index;
 }
 
 int
 frontend::NewSrcNote3(ExclusiveContext *cx, BytecodeEmitter *bce, SrcNoteType type, ptrdiff_t offset1,
             ptrdiff_t offset2)
 {
     int index;
 
     index = NewSrcNote(cx, bce, type);
     if (index >= 0) {
-        if (!SetSrcNoteOffset(cx, bce, index, 0, offset1))
+        if (!bce->setSrcNoteOffset(index, 0, offset1))
             return -1;
-        if (!SetSrcNoteOffset(cx, bce, index, 1, offset2))
+        if (!bce->setSrcNoteOffset(index, 1, offset2))
             return -1;
     }
     return index;
 }
 
 bool
 frontend::AddToSrcNoteDelta(ExclusiveContext *cx, BytecodeEmitter *bce, jssrcnote *sn, ptrdiff_t delta)
 {
@@ -7468,26 +7461,25 @@ frontend::AddToSrcNoteDelta(ExclusiveCon
         jssrcnote xdelta;
         SN_MAKE_XDELTA(&xdelta, delta);
         if (!(sn = bce->main.notes.insert(sn, xdelta)))
             return false;
     }
     return true;
 }
 
-static bool
-SetSrcNoteOffset(ExclusiveContext *cx, BytecodeEmitter *bce, unsigned index, unsigned which,
-                 ptrdiff_t offset)
+bool
+BytecodeEmitter::setSrcNoteOffset(unsigned index, unsigned which, ptrdiff_t offset)
 {
     if (!SN_REPRESENTABLE_OFFSET(offset)) {
-        ReportStatementTooLarge(bce->parser->tokenStream, bce->topStmt);
-        return false;
-    }
-
-    SrcNotesVector &notes = bce->notes();
+        ReportStatementTooLarge(parser->tokenStream, topStmt);
+        return false;
+    }
+
+    SrcNotesVector &notes = this->notes();
 
     /* Find the offset numbered which (i.e., skip exactly which offsets). */
     jssrcnote *sn = notes.begin() + index;
     MOZ_ASSERT(SN_TYPE(sn) != SRC_XDELTA);
     MOZ_ASSERT((int) which < js_SrcNoteSpec[SN_TYPE(sn)].arity);
     for (sn++; which; sn++, which--) {
         if (*sn & SN_4BYTE_OFFSET_FLAG)
             sn += 3;
--- a/js/src/frontend/BytecodeEmitter.h
+++ b/js/src/frontend/BytecodeEmitter.h
@@ -153,17 +153,17 @@ struct BytecodeEmitter
      */
     Vector<uint32_t, 16> localsToFrameSlots_;
 
     int32_t         stackDepth;     /* current stack depth in script frame */
     uint32_t        maxStackDepth;  /* maximum stack depth so far */
 
     uint32_t        arrayCompDepth; /* stack depth of array in comprehension */
 
-    unsigned        emitLevel;      /* js::frontend::EmitTree recursion level */
+    unsigned        emitLevel;      /* emitTree recursion level */
 
     CGConstList     constList;      /* constants to be included with the script */
 
     CGObjectList    objectList;     /* list of emitted objects */
     CGObjectList    regexpList;     /* list of emitted regexp that will be
                                        cloned during execution */
     CGTryNoteList   tryNoteList;    /* list of emitted try notes */
     CGBlockScopeList blockScopeList;/* list of emitted block scope notes */
@@ -264,20 +264,37 @@ struct BytecodeEmitter
     ptrdiff_t lastNoteOffset() const { return current->lastNoteOffset; }
     unsigned currentLine() const { return current->currentLine; }
     unsigned lastColumn() const { return current->lastColumn; }
 
     bool reportError(ParseNode *pn, unsigned errorNumber, ...);
     bool reportStrictWarning(ParseNode *pn, unsigned errorNumber, ...);
     bool reportStrictModeError(ParseNode *pn, unsigned errorNumber, ...);
 
+    bool setSrcNoteOffset(unsigned index, unsigned which, ptrdiff_t offset);
+
+    void setJumpOffsetAt(ptrdiff_t off);
+
+    // Emit code for the tree rooted at pn.
+    bool emitTree(ParseNode *pn);
+
     // If op is JOF_TYPESET (see the type barriers comment in TypeInference.h),
     // reserve a type set to store its result.
     void checkTypeSet(JSOp op);
 
+    void updateDepth(ptrdiff_t target);
+    bool updateLineNumberNotes(uint32_t offset);
+    bool updateSourceCoordNotes(uint32_t offset);
+
+    bool bindNameToSlot(ParseNode *pn);
+
+    void popStatement();
+    void pushStatement(StmtInfoBCE *stmt, StmtType type, ptrdiff_t top);
+    void pushStatementInner(StmtInfoBCE *stmt, StmtType type, ptrdiff_t top);
+
     bool flushPops(int *npops);
 
     ptrdiff_t emitCheck(ptrdiff_t delta);
 
     // Emit one bytecode.
     bool emit1(JSOp op);
 
     // Emit two bytecodes, an opcode (op) with a byte of immediate operand
@@ -466,22 +483,16 @@ struct BytecodeEmitter
     // Please refer the comment above emitSpread for additional information about
     // stack convention.
     bool emitForOf(StmtType type, ParseNode *pn, ptrdiff_t top);
 
     bool emitClass(ParseNode *pn);
 };
 
 /*
- * Emit code into bce for the tree rooted at pn.
- */
-bool
-EmitTree(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn);
-
-/*
  * Emit function code using bce for the tree rooted at body.
  */
 bool
 EmitFunctionScript(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *body);
 
 /*
  * Append a new source note of the given type (and therefore size) to bce's
  * notes dynamic array, updating bce->noteCount. Return the new note's index