Bug 1130811 - Actually use PNK_CATCHLIST so that PNK_CATCH isn't used for multiple arities and situations in practice. r=shu
authorJeff Walden <jwalden@mit.edu>
Mon, 09 Feb 2015 16:07:45 -0800
changeset 228536 2fa5eafb19ee14002c7eb05e1881cefae494ac2e
parent 228535 f37bded46028812a125ee184d1ca9a46bc9c05cb
child 228537 079473f453ed0927d032020fd3054a64591a931a
push id28264
push usercbook@mozilla.com
push dateWed, 11 Feb 2015 13:58:35 +0000
treeherdermozilla-central@38058cb42a0e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersshu
bugs1130811
milestone38.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 1130811 - Actually use PNK_CATCHLIST so that PNK_CATCH isn't used for multiple arities and situations in practice. r=shu
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/FullParseHandler.h
js/src/frontend/ParseNode.h
js/src/frontend/Parser.cpp
js/src/frontend/SyntaxParseHandler.h
js/src/jsreflect.cpp
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -4570,17 +4570,20 @@ EmitTry(ExclusiveContext *cx, BytecodeEm
     // Emit jump over catch and/or finally.
     ptrdiff_t catchJump = -1;
     if (EmitBackPatchOp(cx, bce, &catchJump) < 0)
         return false;
 
     ptrdiff_t tryEnd = bce->offset();
 
     // If this try has a catch block, emit it.
-    if (ParseNode *pn2 = pn->pn_kid2) {
+    ParseNode *catchList = pn->pn_kid2;
+    if (catchList) {
+        MOZ_ASSERT(catchList->isKind(PNK_CATCHLIST));
+
         // The emitted code for a catch block looks like:
         //
         // [pushblockscope]             only if any local aliased
         // exception
         // if there is a catchguard:
         //   dup
         // setlocal 0; pop              assign or possibly destructure exception
         // if there is a catchguard:
@@ -4596,17 +4599,17 @@ EmitTry(ExclusiveContext *cx, BytecodeEm
         // [popblockscope]              only if any local aliased
         // goto <end of catch blocks>   non-local; finally applies
         //
         // If there's no catch block without a catchguard, the last <next catch
         // block> points to rethrow code.  This code will [gosub] to the finally
         // code if appropriate, and is also used for the catch-all trynote for
         // capturing exceptions thrown from catch{} blocks.
         //
-        for (ParseNode *pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
+        for (ParseNode *pn3 = catchList->pn_head; pn3; pn3 = pn3->pn_next) {
             MOZ_ASSERT(bce->stackDepth == depth);
 
             // Emit the lexical scope and catch body.
             MOZ_ASSERT(pn3->isKind(PNK_LEXICALSCOPE));
             if (!EmitTree(cx, bce, pn3))
                 return false;
 
             // gosub <finally>, if required.
@@ -4671,17 +4674,17 @@ EmitTry(ExclusiveContext *cx, BytecodeEm
         return false;
 
     // Fix up the end-of-try/catch jumps to come here.
     if (!BackPatch(cx, bce, catchJump, bce->code().end(), JSOP_GOTO))
         return false;
 
     // Add the try note last, to let post-order give us the right ordering
     // (first to last for a given nesting level, inner to outer by level).
-    if (pn->pn_kid2 && !bce->tryNoteList.append(JSTRY_CATCH, depth, tryStart, tryEnd))
+    if (catchList && !bce->tryNoteList.append(JSTRY_CATCH, depth, tryStart, tryEnd))
         return false;
 
     // If we've got a finally, mark try+catch region with additional
     // trynote to catch exceptions (re)thrown from a catch block or
     // for the try{}finally{} case.
     if (pn->pn_kid3 && !bce->tryNoteList.append(JSTRY_FINALLY, depth, tryStart, finallyStart))
         return false;
 
--- a/js/src/frontend/FullParseHandler.h
+++ b/js/src/frontend/FullParseHandler.h
@@ -595,16 +595,19 @@ class FullParseHandler
         return new_<ListNode>(kind, op, pos());
     }
 
     /* New list with one initial child node. kid must be non-null. */
     ParseNode *newList(ParseNodeKind kind, ParseNode *kid, JSOp op = JSOP_NOP) {
         return new_<ListNode>(kind, op, kid);
     }
 
+    ParseNode *newCatchList() {
+        return new_<ListNode>(PNK_CATCHLIST, JSOP_NOP, pos());
+    }
 
     ParseNode *newCommaExpressionList(ParseNode *kid) {
         return newList(PNK_COMMA, kid, JSOP_NOP);
     }
 
     void addList(ParseNode *list, ParseNode *kid) {
         list->append(kid);
     }
--- a/js/src/frontend/ParseNode.h
+++ b/js/src/frontend/ParseNode.h
@@ -281,20 +281,21 @@ enum ParseNodeKind
  *                            to left of 'of'; if pn_kid1, then this
  *                            is a clone of pn_kid1->pn_head
  *                          pn_kid3: expr to right of 'of'
  * PNK_FORHEAD  ternary     pn_kid1:  init expr before first ';' or nullptr
  *                          pn_kid2:  cond expr before second ';' or nullptr
  *                          pn_kid3:  update expr after second ';' or nullptr
  * PNK_THROW    unary       pn_op: JSOP_THROW, pn_kid: exception
  * PNK_TRY      ternary     pn_kid1: try block
- *                          pn_kid2: null or PNK_CATCHLIST list of
- *                          PNK_LEXICALSCOPE nodes, each with pn_expr pointing
- *                          to a PNK_CATCH node
+ *                          pn_kid2: null or PNK_CATCHLIST list
  *                          pn_kid3: null or finally block
+ * PNK_CATCHLIST list       pn_head: list of PNK_LEXICALSCOPE nodes, one per
+ *                                   catch-block, each with pn_expr pointing
+ *                                   to a PNK_CATCH node
  * PNK_CATCH    ternary     pn_kid1: PNK_NAME, PNK_ARRAY, or PNK_OBJECT catch var node
  *                                   (PNK_ARRAY or PNK_OBJECT if destructuring)
  *                          pn_kid2: null or the catch guard expression
  *                          pn_kid3: catch block statements
  * PNK_BREAK    name        pn_atom: label or null
  * PNK_CONTINUE name        pn_atom: label or null
  * PNK_WITH     binary-obj  pn_left: head expr; pn_right: body; pn_binary_obj: StaticWithObject
  * PNK_VAR,     list        pn_head: list of PNK_NAME or PNK_ASSIGN nodes
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -5624,17 +5624,17 @@ Parser<ParseHandler>::tryStatement()
     PopStatementPC(tokenStream, pc);
 
     bool hasUnconditionalCatch = false;
     Node catchList = null();
     TokenKind tt;
     if (!tokenStream.getToken(&tt))
         return null();
     if (tt == TOK_CATCH) {
-        catchList = handler.newList(PNK_CATCH);
+        catchList = handler.newCatchList();
         if (!catchList)
             return null();
 
         do {
             Node pnblock;
             BindData<ParseHandler> data(context);
 
             /* Check for another catch after unconditional catch. */
--- a/js/src/frontend/SyntaxParseHandler.h
+++ b/js/src/frontend/SyntaxParseHandler.h
@@ -262,16 +262,20 @@ class SyntaxParseHandler
 
     Node newList(ParseNodeKind kind, JSOp op = JSOP_NOP) {
         return NodeGeneric;
     }
     Node newList(ParseNodeKind kind, Node kid, JSOp op = JSOP_NOP) {
         return NodeGeneric;
     }
 
+    Node newCatchList() {
+        return newList(PNK_CATCHLIST, JSOP_NOP);
+    }
+
     Node newCommaExpressionList(Node kid) {
         return NodeUnparenthesizedCommaExpr;
     }
 
     void addList(Node list, Node kid) {
         MOZ_ASSERT(list == NodeGeneric || list == NodeUnparenthesizedCommaExpr);
     }
 
--- a/js/src/jsreflect.cpp
+++ b/js/src/jsreflect.cpp
@@ -2297,21 +2297,21 @@ ASTSerializer::tryStatement(ParseNode *p
 
     RootedValue body(cx);
     if (!statement(pn->pn_kid1, &body))
         return false;
 
     NodeVector guarded(cx);
     RootedValue unguarded(cx, NullValue());
 
-    if (pn->pn_kid2) {
-        if (!guarded.reserve(pn->pn_kid2->pn_count))
+    if (ParseNode *catchList = pn->pn_kid2) {
+        if (!guarded.reserve(catchList->pn_count))
             return false;
 
-        for (ParseNode *next = pn->pn_kid2->pn_head; next; next = next->pn_next) {
+        for (ParseNode *next = catchList->pn_head; next; next = next->pn_next) {
             RootedValue clause(cx);
             bool isGuarded;
             if (!catchClause(next->pn_expr, &isGuarded, &clause))
                 return false;
             if (isGuarded)
                 guarded.infallibleAppend(clause);
             else
                 unguarded = clause;