Bug 932216 - Remove code conditional on JS_HAS_CONST, JS_HAS_BLOCK_SCOPE. r=jorendorff
authorAndy Wingo <wingo@igalia.com>
Tue, 29 Oct 2013 11:23:51 +0100
changeset 152978 13bd430455d43197995da6bc99d0f5c0f1c5dfbc
parent 152977 ed35c291d57ed85b5394775e163aeb8d96f6b1ee
child 152979 428bea088d2b5a6c281473881b6e543aea126923
push id35649
push userryanvm@gmail.com
push dateFri, 01 Nov 2013 03:04:18 +0000
treeherdermozilla-inbound@13bd430455d4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs932216
milestone28.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 932216 - Remove code conditional on JS_HAS_CONST, JS_HAS_BLOCK_SCOPE. r=jorendorff
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/Parser.cpp
js/src/frontend/Parser.h
js/src/frontend/TokenStream.h
js/src/vm/Keywords.h
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -2288,62 +2288,54 @@ EmitSwitch(ExclusiveContext *cx, Bytecod
     StmtInfoBCE stmtInfo(cx);
 
     /* Try for most optimal, fall back if not dense ints. */
     switchOp = JSOP_TABLESWITCH;
     hasDefault = false;
     defaultOffset = -1;
 
     pn2 = pn->pn_right;
-#if JS_HAS_BLOCK_SCOPE
     /*
      * If there are hoisted let declarations, their stack slots go under the
      * discriminant's value so push their slots now and enter the block later.
      */
     uint32_t blockObjCount = 0;
     if (pn2->isKind(PNK_LEXICALSCOPE)) {
         blockObjCount = pn2->pn_objbox->object->as<StaticBlockObject>().slotCount();
         for (uint32_t i = 0; i < blockObjCount; ++i) {
             if (Emit1(cx, bce, JSOP_UNDEFINED) < 0)
                 return false;
         }
     }
-#endif
 
     /* Push the discriminant. */
     if (!EmitTree(cx, bce, pn->pn_left))
         return false;
 
-#if JS_HAS_BLOCK_SCOPE
     if (pn2->isKind(PNK_LEXICALSCOPE)) {
         PushBlockScopeBCE(bce, &stmtInfo, pn2->pn_objbox->object->as<StaticBlockObject>(), -1);
         stmtInfo.type = STMT_SWITCH;
         if (!EmitEnterBlock(cx, bce, pn2, JSOP_ENTERLET1))
             return false;
     }
-#endif
 
     /* Switch bytecodes run from here till end of final case. */
     top = bce->offset();
-#if !JS_HAS_BLOCK_SCOPE
-    PushStatementBCE(bce, &stmtInfo, STMT_SWITCH, top);
-#else
     if (pn2->isKind(PNK_STATEMENTLIST)) {
         PushStatementBCE(bce, &stmtInfo, STMT_SWITCH, top);
     } else {
         /*
          * Set the statement info record's idea of top. Reset top too, since
          * repushBlock emits code.
          */
         stmtInfo.update = top = bce->offset();
 
         /* Advance pn2 to refer to the switch case list. */
         pn2 = pn2->expr();
     }
-#endif
 
     uint32_t caseCount = pn2->pn_count;
     uint32_t tableLength = 0;
     ScopedJSFreePtr<ParseNode*> table(nullptr);
 
     if (caseCount > JS_BIT(16)) {
         bce->parser->tokenStream.reportError(JSMSG_TOO_MANY_CASES);
         return false;
@@ -2609,20 +2601,18 @@ EmitSwitch(ExclusiveContext *cx, Bytecod
             SET_JUMP_OFFSET(pc, off);
             pc += JUMP_OFFSET_LEN;
         }
     }
 
     if (!PopStatementBCE(cx, bce))
         return false;
 
-#if JS_HAS_BLOCK_SCOPE
     if (pn->pn_right->isKind(PNK_LEXICALSCOPE))
         EMIT_UINT16_IMM_OP(JSOP_LEAVEBLOCK, blockObjCount);
-#endif
 
     return true;
 }
 
 bool
 BytecodeEmitter::isRunOnceLambda()
 {
     // The run once lambda flags set by the parser are approximate, and we look
@@ -4150,17 +4140,16 @@ EmitIf(ExclusiveContext *cx, BytecodeEmi
             return false;
     } else {
         /* No else part, fixup the branch-if-false to come here. */
         SetJumpOffsetAt(bce, beq);
     }
     return PopStatementBCE(cx, bce);
 }
 
-#if JS_HAS_BLOCK_SCOPE
 /*
  * pnLet represents one of:
  *
  *   let-expression:   (let (x = y) EXPR)
  *   let-statement:    let (x = y) { ... }
  *
  * For a let-expression 'let (x = a, [y,z] = b) e', EmitLet produces:
  *
@@ -4223,17 +4212,16 @@ EmitLet(ExclusiveContext *cx, BytecodeEm
     JS_ASSERT(leaveOp == JSOP_LEAVEBLOCK || leaveOp == JSOP_LEAVEBLOCKEXPR);
     EMIT_UINT16_IMM_OP(leaveOp, blockObj->slotCount());
 
     DebugOnly<ptrdiff_t> bodyEnd = bce->offset();
     JS_ASSERT(bodyEnd > bodyBegin);
 
     return PopStatementBCE(cx, bce);
 }
-#endif
 
 /*
  * Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
  * the comment on EmitSwitch.
  */
 MOZ_NEVER_INLINE static bool
 EmitLexicalScope(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
 {
@@ -6450,23 +6438,22 @@ frontend::EmitTree(ExclusiveContext *cx,
       case PNK_GENEXP:
         ok = EmitCallOrNew(cx, bce, pn);
         break;
 
       case PNK_LEXICALSCOPE:
         ok = EmitLexicalScope(cx, bce, pn);
         break;
 
-#if JS_HAS_BLOCK_SCOPE
       case PNK_LET:
         ok = pn->isArity(PN_BINARY)
              ? EmitLet(cx, bce, pn)
              : EmitVariables(cx, bce, pn, InitializeVars);
         break;
-#endif /* JS_HAS_BLOCK_SCOPE */
+
       case PNK_ARRAYPUSH: {
         int slot;
 
         /*
          * The array object's stack index is in bce->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.
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -3273,18 +3273,16 @@ Parser<ParseHandler>::pushLexicalScope(S
 {
     RootedStaticBlockObject blockObj(context, StaticBlockObject::create(context));
     if (!blockObj)
         return null();
 
     return pushLexicalScope(blockObj, stmt);
 }
 
-#if JS_HAS_BLOCK_SCOPE
-
 struct AddLetDecl
 {
     uint32_t blockid;
 
     AddLetDecl(uint32_t blockid) : blockid(blockid) {}
 
     bool operator()(TokenStream &ts, ParseContext<FullParseHandler> *pc,
                     HandleStaticBlockObject blockObj, const Shape &shape, JSAtom *)
@@ -3403,18 +3401,16 @@ Parser<ParseHandler>::letBlock(LetContex
     if (needExprStmt) {
         if (!MatchOrInsertSemicolon(tokenStream))
             return null();
         return handler.newExprStatement(pnlet, pos().end);
     }
     return pnlet;
 }
 
-#endif /* JS_HAS_BLOCK_SCOPE */
-
 template <typename ParseHandler>
 static bool
 PushBlocklikeStatement(TokenStream &ts, StmtInfoPC *stmt, StmtType type,
                        ParseContext<ParseHandler> *pc)
 {
     PushStatementPC(pc, stmt, type);
     return GenerateBlockId(ts, pc, stmt->blockid);
 }
@@ -3585,17 +3581,16 @@ Parser<ParseHandler>::variables(ParseNod
             if (!handler.finishInitializerAssignment(pn2, init, data.op))
                 return null();
         }
     } while (tokenStream.matchToken(TOK_COMMA));
 
     return pn;
 }
 
-#if JS_HAS_BLOCK_SCOPE
 template <>
 ParseNode *
 Parser<FullParseHandler>::letStatement()
 {
     handler.disableSyntaxParser();
 
     ParseNode *pn;
     do {
@@ -3707,18 +3702,16 @@ Parser<FullParseHandler>::letStatement()
 template <>
 SyntaxParseHandler::Node
 Parser<SyntaxParseHandler>::letStatement()
 {
     JS_ALWAYS_FALSE(abortIfSyntaxParser());
     return SyntaxParseHandler::NodeFailure;
 }
 
-#endif // JS_HAS_BLOCK_SCOPE
-
 template <typename ParseHandler>
 typename ParseHandler::Node
 Parser<ParseHandler>::expressionStatement()
 {
     tokenStream.ungetToken();
     Node pnexpr = expr();
     if (!pnexpr)
         return null();
@@ -3931,31 +3924,29 @@ Parser<FullParseHandler>::forStatement()
              * clause of an ordinary for loop.
              */
             pc->parsingForInit = true;
             if (tt == TOK_VAR || tt == TOK_CONST) {
                 isForDecl = true;
                 tokenStream.consumeKnownToken(tt);
                 pn1 = variables(tt == TOK_VAR ? PNK_VAR : PNK_CONST);
             }
-#if JS_HAS_BLOCK_SCOPE
             else if (tt == TOK_LET) {
                 handler.disableSyntaxParser();
                 (void) tokenStream.getToken();
                 if (tokenStream.peekToken() == TOK_LP) {
                     pn1 = letBlock(LetExpresion);
                 } else {
                     isForDecl = true;
                     blockObj = StaticBlockObject::create(context);
                     if (!blockObj)
                         return null();
                     pn1 = variables(PNK_LET, nullptr, blockObj, DontHoistVars);
                 }
             }
-#endif
             else {
                 pn1 = expr();
             }
             pc->parsingForInit = false;
             if (!pn1)
                 return null();
         }
     }
@@ -4183,20 +4174,18 @@ Parser<FullParseHandler>::forStatement()
     if (!forHead)
         return null();
 
     /* Parse the loop body. */
     ParseNode *body = statement();
     if (!body)
         return null();
 
-#if JS_HAS_BLOCK_SCOPE
     if (blockObj)
         PopStatementPC(tokenStream, pc);
-#endif
     PopStatementPC(tokenStream, pc);
 
     ParseNode *forLoop = handler.newForStatement(begin, forHead, body, iflags);
     if (!forLoop)
         return null();
 
     if (hoistedVar) {
         ParseNode *pnseq = handler.newList(PNK_SEQ, hoistedVar);
@@ -4260,22 +4249,20 @@ Parser<SyntaxParseHandler>::forStatement
         } else {
             /* Set lhsNode to a var list or an initializing expression. */
             pc->parsingForInit = true;
             if (tt == TOK_VAR) {
                 isForDecl = true;
                 tokenStream.consumeKnownToken(tt);
                 lhsNode = variables(tt == TOK_VAR ? PNK_VAR : PNK_CONST, &simpleForDecl);
             }
-#if JS_HAS_BLOCK_SCOPE
             else if (tt == TOK_CONST || tt == TOK_LET) {
                 JS_ALWAYS_FALSE(abortIfSyntaxParser());
                 return null();
             }
-#endif
             else {
                 lhsNode = expr();
             }
             if (!lhsNode)
                 return null();
             pc->parsingForInit = false;
         }
     }
@@ -4992,21 +4979,18 @@ Parser<ParseHandler>::statement(bool can
         // Tell js_EmitTree to generate a final POP.
         handler.setListFlag(pn, PNX_POPVAR);
 
         if (!MatchOrInsertSemicolon(tokenStream))
             return null();
         return pn;
       }
 
-#if JS_HAS_BLOCK_SCOPE
       case TOK_LET:
         return letStatement();
-#endif
-
       case TOK_SEMI:
         return handler.newEmptyStatement(pos());
       case TOK_IF:
         return ifStatement();
       case TOK_DO:
         return doWhileStatement();
       case TOK_WHILE:
         return whileStatement();
@@ -6804,20 +6788,18 @@ Parser<ParseHandler>::primaryExpr(TokenK
         return functionExpr();
 
       case TOK_LB:
         return arrayInitializer();
 
       case TOK_LC:
         return objectLiteral();
 
-#if JS_HAS_BLOCK_SCOPE
       case TOK_LET:
         return letBlock(LetExpresion);
-#endif
 
       case TOK_LP:
       {
         bool genexp;
         Node pn = parenExpr(&genexp);
         if (!pn)
             return null();
         pn = handler.setInParens(pn);
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -508,19 +508,17 @@ class Parser : private AutoGCRooter, pub
     Node breakStatement();
     Node returnStatement();
     Node withStatement();
     Node labeledStatement();
     Node throwStatement();
     Node tryStatement();
     Node debuggerStatement();
 
-#if JS_HAS_BLOCK_SCOPE
     Node letStatement();
-#endif
     Node expressionStatement();
     Node variables(ParseNodeKind kind, bool *psimple = nullptr,
                    StaticBlockObject *blockObj = nullptr,
                    VarContext varContext = HoistVars);
     Node expr();
     Node assignExpr();
     Node assignExprWithoutYield(unsigned err);
     Node yieldExpression();
--- a/js/src/frontend/TokenStream.h
+++ b/js/src/frontend/TokenStream.h
@@ -177,21 +177,17 @@ inline bool
 TokenKindIsAssignment(TokenKind tt)
 {
     return TOK_ASSIGNMENT_START <= tt && tt <= TOK_ASSIGNMENT_LAST;
 }
 
 inline bool
 TokenKindIsDecl(TokenKind tt)
 {
-#if JS_HAS_BLOCK_SCOPE
     return tt == TOK_VAR || tt == TOK_LET;
-#else
-    return tt == TOK_VAR;
-#endif
 }
 
 struct TokenPos {
     uint32_t    begin;  // Offset of the token's first char.
     uint32_t    end;    // Offset of 1 past the token's last char.
 
     TokenPos() {}
     TokenPos(uint32_t begin, uint32_t end) : begin(begin), end(end) {}
--- a/js/src/vm/Keywords.h
+++ b/js/src/vm/Keywords.h
@@ -4,39 +4,25 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* A higher-order macro for enumerating keyword tokens. */
 
 #ifndef vm_Keywords_h
 #define vm_Keywords_h
 
-#if JS_HAS_CONST
-#  define FOR_CONST_KEYWORD(macro) \
-      macro(const, const_, TOK_CONST, JSVERSION_DEFAULT)
-#else
-#  define FOR_CONST_KEYWORD(macro) \
-      macro(const, const_, TOK_RESERVED, JSVERSION_DEFAULT)
-#endif
-#if JS_HAS_BLOCK_SCOPE
-#  define FOR_LET_KEYWORD(macro) \
-      macro(let, let, TOK_LET, JSVERSION_1_7)
-#else
-#  define FOR_LET_KEYWORD(macro) \
-      macro(let, let, TOK_STRICT_RESERVED, JSVERSION_1_7)
-#endif
-
 #define FOR_EACH_JAVASCRIPT_KEYWORD(macro) \
     macro(false, false_, TOK_FALSE, JSVERSION_DEFAULT) \
     macro(true, true_, TOK_TRUE, JSVERSION_DEFAULT) \
     macro(null, null, TOK_NULL, JSVERSION_DEFAULT) \
-    /* ES5 Keywords. */ \
+    /* Keywords. */ \
     macro(break, break_, TOK_BREAK, JSVERSION_DEFAULT) \
     macro(case, case_, TOK_CASE, JSVERSION_DEFAULT) \
     macro(catch, catch_, TOK_CATCH, JSVERSION_DEFAULT) \
+    macro(const, const_, TOK_CONST, JSVERSION_DEFAULT) \
     macro(continue, continue_, TOK_CONTINUE, JSVERSION_DEFAULT) \
     macro(debugger, debugger, TOK_DEBUGGER, JSVERSION_DEFAULT) \
     macro(default, default_, TOK_DEFAULT, JSVERSION_DEFAULT) \
     macro(delete, delete_, TOK_DELETE, JSVERSION_DEFAULT) \
     macro(do, do_, TOK_DO, JSVERSION_DEFAULT) \
     macro(else, else_, TOK_ELSE, JSVERSION_DEFAULT) \
     macro(finally, finally_, TOK_FINALLY, JSVERSION_DEFAULT) \
     macro(for, for_, TOK_FOR, JSVERSION_DEFAULT) \
@@ -50,34 +36,36 @@
     macro(this, this_, TOK_THIS, JSVERSION_DEFAULT) \
     macro(throw, throw_, TOK_THROW, JSVERSION_DEFAULT) \
     macro(try, try_, TOK_TRY, JSVERSION_DEFAULT) \
     macro(typeof, typeof, TOK_TYPEOF, JSVERSION_DEFAULT) \
     macro(var, var, TOK_VAR, JSVERSION_DEFAULT) \
     macro(void, void_, TOK_VOID, JSVERSION_DEFAULT) \
     macro(while, while_, TOK_WHILE, JSVERSION_DEFAULT) \
     macro(with, with, TOK_WITH, JSVERSION_DEFAULT) \
-    /* ES5 reserved keywords reserved in all code. */ \
+    /* Reserved keywords. */ \
     macro(class, class_, TOK_RESERVED, JSVERSION_DEFAULT) \
     macro(enum, enum_, TOK_RESERVED, JSVERSION_DEFAULT) \
     macro(export, export, TOK_RESERVED, JSVERSION_DEFAULT) \
     macro(extends, extends, TOK_RESERVED, JSVERSION_DEFAULT) \
     macro(import, import, TOK_RESERVED, JSVERSION_DEFAULT) \
     macro(super, super, TOK_RESERVED, JSVERSION_DEFAULT) \
-    /* ES5 future reserved keywords in strict mode. */ \
+    /* Future reserved keywords, but only in strict mode. */ \
     macro(implements, implements, TOK_STRICT_RESERVED, JSVERSION_DEFAULT) \
     macro(interface, interface, TOK_STRICT_RESERVED, JSVERSION_DEFAULT) \
     macro(package, package, TOK_STRICT_RESERVED, JSVERSION_DEFAULT) \
     macro(private, private_, TOK_STRICT_RESERVED, JSVERSION_DEFAULT) \
     macro(protected, protected_, TOK_STRICT_RESERVED, JSVERSION_DEFAULT) \
     macro(public, public_, TOK_STRICT_RESERVED, JSVERSION_DEFAULT) \
     macro(static, static_, TOK_STRICT_RESERVED, JSVERSION_DEFAULT) \
     /* \
-     * ES5 future reserved keyword in strict mode, keyword in JS1.7 even when \
-     * not strict, keyword inside function* in all versions.  Punt logic to \
-     * parser. \
+     * Yield is a token inside function*.  Outside of a function*, it is a \
+     * future reserved keyword in strict mode, but a keyword in JS1.7 even \
+     * when strict.  Punt logic to parser. \
      */ \
     macro(yield, yield, TOK_YIELD, JSVERSION_DEFAULT) \
-    /* Various conditional keywords. */ \
-    FOR_CONST_KEYWORD(macro) \
-    FOR_LET_KEYWORD(macro)
+    /* \
+     * Let is a future reserved keyword in strict mode, and a keyword in \
+     * JS1.7. \
+     */ \
+    macro(let, let, TOK_LET, JSVERSION_1_7)
 
 #endif /* vm_Keywords_h */