Bug 697000 - Do kind-checking in Token's setters. r=till.
authorNicholas Nethercote <nnethercote@mozilla.com>
Sun, 04 Aug 2013 15:44:11 -0700
changeset 153622 786c0737415445df8681c177477af003e75db0d8
parent 153621 4ab85b5ed58948ff56087ffcc475a5752e29f4bb
child 153623 92259ea31bb4adf77eff05d4947d6cbc6bffb6d6
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstill
bugs697000
milestone25.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 697000 - Do kind-checking in Token's setters. r=till.
js/src/frontend/TokenStream.cpp
js/src/frontend/TokenStream.h
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -1010,30 +1010,29 @@ static const uint8_t firstCharKinds[] = 
 #undef _______
 
 static_assert(LastCharKind < (1 << (sizeof(firstCharKinds[0]) * 8)),
               "Elements of firstCharKinds[] are too small");
 
 TokenKind
 TokenStream::getTokenInternal(Modifier modifier)
 {
-    TokenKind tt;
     int c, qc;
     Token *tp;
     FirstCharKind c1kind;
     const jschar *numStart;
     bool hasExp;
     DecimalPoint decimalPoint;
     const jschar *identStart;
     bool hadUnicodeEscape;
 
   retry:
     if (JS_UNLIKELY(!userbuf.hasRawChars())) {
         tp = newToken(0);
-        tt = TOK_EOF;
+        tp->type = TOK_EOF;
         flags.isEOF = true;
         goto out;
     }
 
     c = userbuf.getRawChar();
     JS_ASSERT(c != EOF);
 
     // Chars not in the range 0..127 are rare.  Getting them out of the way
@@ -1082,17 +1081,17 @@ TokenStream::getTokenInternal(Modifier m
     // be worth adding extra values to FirstCharKind.
     //
     c1kind = FirstCharKind(firstCharKinds[c]);
 
     // Look for an unambiguous single-char token.
     //
     if (c1kind < OneChar_Max) {
         tp = newToken(-1);
-        tt = TokenKind(c1kind);
+        tp->type = TokenKind(c1kind);
         goto out;
     }
 
     // Skip over non-EOL whitespace chars.
     //
     if (c1kind == Space)
         goto retry;
 
@@ -1129,28 +1128,28 @@ TokenStream::getTokenInternal(Modifier m
             length = tokenbuf.length();
         } else {
             chars = identStart;
             length = userbuf.addressOfNextRawChar() - identStart;
         }
 
         // Check for keywords unless the parser told us not to.
         if (modifier != KeywordIsName) {
-            tt = TOK_NAME;
-            if (!checkForKeyword(chars, length, &tt))
+            tp->type = TOK_NAME;
+            if (!checkForKeyword(chars, length, &tp->type))
                 goto error;
-            if (tt != TOK_NAME)
+            if (tp->type != TOK_NAME)
                 goto out;
         }
 
         JSAtom *atom = AtomizeChars<CanGC>(cx, chars, length);
         if (!atom)
             goto error;
+        tp->type = TOK_NAME;
         tp->setName(atom->asPropertyName());
-        tt = TOK_NAME;
         goto out;
     }
 
     // Look for a decimal number.
     //
     if (c1kind == Dec) {
         tp = newToken(-1);
         numStart = userbuf.addressOfNextRawChar() - 1;
@@ -1196,18 +1195,18 @@ TokenStream::getTokenInternal(Modifier m
         if (!((decimalPoint == HasDecimal) || hasExp)) {
             if (!GetDecimalInteger(cx, numStart, userbuf.addressOfNextRawChar(), &dval))
                 goto error;
         } else {
             const jschar *dummy;
             if (!js_strtod(cx, numStart, userbuf.addressOfNextRawChar(), &dummy, &dval))
                 goto error;
         }
+        tp->type = TOK_NUMBER;
         tp->setNumber(dval, decimalPoint);
-        tt = TOK_NUMBER;
         goto out;
     }
 
     // Look for a string.
     //
     if (c1kind == String) {
         tp = newToken(-1);
         qc = c;
@@ -1295,18 +1294,18 @@ TokenStream::getTokenInternal(Modifier m
                 }
             }
             if (!tokenbuf.append(c))
                 goto error;
         }
         JSAtom *atom = atomize(cx, tokenbuf);
         if (!atom)
             goto error;
+        tp->type = TOK_STRING;
         tp->setAtom(atom);
-        tt = TOK_STRING;
         goto out;
     }
 
     // Skip over EOL chars, updating line state along the way.
     //
     if (c1kind == EOL) {
         // If it's a \r\n sequence: treat as a single EOL, skip over the \n.
         if (c == '\r' && userbuf.hasRawChars())
@@ -1386,18 +1385,18 @@ TokenStream::getTokenInternal(Modifier m
             reportError(JSMSG_IDSTART_AFTER_NUMBER);
             goto error;
         }
 
         double dval;
         const jschar *dummy;
         if (!GetPrefixInteger(cx, numStart, userbuf.addressOfNextRawChar(), radix, &dummy, &dval))
             goto error;
+        tp->type = TOK_NUMBER;
         tp->setNumber(dval, NoDecimal);
-        tt = TOK_NUMBER;
         goto out;
     }
 
     // This handles everything else.
     //
     JS_ASSERT(c1kind == Other);
     tp = newToken(-1);
     switch (c) {
@@ -1406,103 +1405,103 @@ TokenStream::getTokenInternal(Modifier m
         if (JS7_ISDEC(c)) {
             numStart = userbuf.addressOfNextRawChar() - 2;
             decimalPoint = HasDecimal;
             hasExp = false;
             goto decimal_dot;
         }
         if (c == '.') {
             if (matchChar('.')) {
-                tt = TOK_TRIPLEDOT;
+                tp->type = TOK_TRIPLEDOT;
                 goto out;
             }
         }
         ungetCharIgnoreEOL(c);
-        tt = TOK_DOT;
+        tp->type = TOK_DOT;
         goto out;
 
       case '=':
         if (matchChar('='))
-            tt = matchChar('=') ? TOK_STRICTEQ : TOK_EQ;
+            tp->type = matchChar('=') ? TOK_STRICTEQ : TOK_EQ;
         else if (matchChar('>'))
-            tt = TOK_ARROW;
+            tp->type = TOK_ARROW;
         else
-            tt = TOK_ASSIGN;
+            tp->type = TOK_ASSIGN;
         goto out;
 
       case '+':
         if (matchChar('+'))
-            tt = TOK_INC;
+            tp->type = TOK_INC;
         else
-            tt = matchChar('=') ? TOK_ADDASSIGN : TOK_ADD;
+            tp->type = matchChar('=') ? TOK_ADDASSIGN : TOK_ADD;
         goto out;
 
       case '\\':
         hadUnicodeEscape = matchUnicodeEscapeIdStart(&qc);
         if (hadUnicodeEscape) {
             identStart = userbuf.addressOfNextRawChar() - 6;
             goto identifier;
         }
         goto badchar;
 
       case '|':
         if (matchChar('|'))
-            tt = TOK_OR;
+            tp->type = TOK_OR;
         else
-            tt = matchChar('=') ? TOK_BITORASSIGN : TOK_BITOR;
+            tp->type = matchChar('=') ? TOK_BITORASSIGN : TOK_BITOR;
         goto out;
 
       case '^':
-        tt = matchChar('=') ? TOK_BITXORASSIGN : TOK_BITXOR;
+        tp->type = matchChar('=') ? TOK_BITXORASSIGN : TOK_BITXOR;
         goto out;
 
       case '&':
         if (matchChar('&'))
-            tt = TOK_AND;
+            tp->type = TOK_AND;
         else
-            tt = matchChar('=') ? TOK_BITANDASSIGN : TOK_BITAND;
+            tp->type = matchChar('=') ? TOK_BITANDASSIGN : TOK_BITAND;
         goto out;
 
       case '!':
         if (matchChar('='))
-            tt = matchChar('=') ? TOK_STRICTNE : TOK_NE;
+            tp->type = matchChar('=') ? TOK_STRICTNE : TOK_NE;
         else
-            tt = TOK_NOT;
+            tp->type = TOK_NOT;
         goto out;
 
       case '<':
         // NB: treat HTML begin-comment as comment-till-end-of-line.
         if (matchChar('!')) {
             if (matchChar('-')) {
                 if (matchChar('-'))
                     goto skipline;
                 ungetChar('-');
             }
             ungetChar('!');
         }
         if (matchChar('<')) {
-            tt = matchChar('=') ? TOK_LSHASSIGN : TOK_LSH;
+            tp->type = matchChar('=') ? TOK_LSHASSIGN : TOK_LSH;
         } else {
-            tt = matchChar('=') ? TOK_LE : TOK_LT;
+            tp->type = matchChar('=') ? TOK_LE : TOK_LT;
         }
         goto out;
 
       case '>':
         if (matchChar('>')) {
             if (matchChar('>'))
-                tt = matchChar('=') ? TOK_URSHASSIGN : TOK_URSH;
+                tp->type = matchChar('=') ? TOK_URSHASSIGN : TOK_URSH;
             else
-                tt = matchChar('=') ? TOK_RSHASSIGN : TOK_RSH;
+                tp->type = matchChar('=') ? TOK_RSHASSIGN : TOK_RSH;
         } else {
-            tt = matchChar('=') ? TOK_GE : TOK_GT;
+            tp->type = matchChar('=') ? TOK_GE : TOK_GT;
         }
         goto out;
 
       case '*':
-        tt = matchChar('=') ? TOK_MULASSIGN : TOK_MUL;
+        tp->type = matchChar('=') ? TOK_MULASSIGN : TOK_MUL;
         goto out;
 
       case '/':
         // Look for a single-line comment.
         if (matchChar('/')) {
             c = peekChar();
             if (c == '@' || c == '#') {
                 if (!getSourceMappingURL(false, getChar() == '@'))
@@ -1587,52 +1586,51 @@ TokenStream::getTokenInternal(Modifier m
             if (JS7_ISLET(c)) {
                 char buf[2] = { '\0', '\0' };
                 tp->pos.begin += length + 1;
                 buf[0] = char(c);
                 reportError(JSMSG_BAD_REGEXP_FLAG, buf);
                 (void) getChar();
                 goto error;
             }
+            tp->type = TOK_REGEXP;
             tp->setRegExpFlags(reflags);
-            tt = TOK_REGEXP;
             goto out;
         }
 
-        tt = matchChar('=') ? TOK_DIVASSIGN : TOK_DIV;
+        tp->type = matchChar('=') ? TOK_DIVASSIGN : TOK_DIV;
         goto out;
 
       case '%':
-        tt = matchChar('=') ? TOK_MODASSIGN : TOK_MOD;
+        tp->type = matchChar('=') ? TOK_MODASSIGN : TOK_MOD;
         goto out;
 
       case '-':
         if (matchChar('-')) {
             if (peekChar() == '>' && !flags.isDirtyLine)
                 goto skipline;
-            tt = TOK_DEC;
+            tp->type = TOK_DEC;
         } else {
-            tt = matchChar('=') ? TOK_SUBASSIGN : TOK_SUB;
+            tp->type = matchChar('=') ? TOK_SUBASSIGN : TOK_SUB;
         }
         goto out;
 
       badchar:
       default:
         reportError(JSMSG_ILLEGAL_CHARACTER);
         goto error;
     }
 
     MOZ_ASSUME_UNREACHABLE("should have jumped to |out| or |error|");
 
   out:
     flags.isDirtyLine = true;
     tp->pos.end = userbuf.addressOfNextRawChar() - userbuf.base();
-    tp->type = tt;
     JS_ASSERT(IsTokenSane(tp));
-    return tt;
+    return tp->type;
 
   error:
     flags.isDirtyLine = true;
     tp->pos.end = userbuf.addressOfNextRawChar() - userbuf.base();
     tp->type = TOK_ERROR;
     JS_ASSERT(IsTokenSane(tp));
     onError();
     return TOK_ERROR;
--- a/js/src/frontend/TokenStream.h
+++ b/js/src/frontend/TokenStream.h
@@ -250,35 +250,36 @@ struct Token {
             DecimalPoint decimalPoint;  // literal contains '.'
         } number;
         RegExpFlag      reflags;        // regexp flags; use tokenbuf to access
                                         //   regexp chars
     } u;
 
     // Mutators
 
-    // FIXME: Init type early enough such that all mutators can assert
-    //        type-safety.  See bug 697000.
-
     void setName(PropertyName *name) {
+        JS_ASSERT(type == TOK_NAME);
         JS_ASSERT(!IsPoisonedPtr(name));
         u.name = name;
     }
 
     void setAtom(JSAtom *atom) {
+        JS_ASSERT(type == TOK_STRING);
         JS_ASSERT(!IsPoisonedPtr(atom));
         u.atom = atom;
     }
 
     void setRegExpFlags(js::RegExpFlag flags) {
+        JS_ASSERT(type == TOK_REGEXP);
         JS_ASSERT((flags & AllFlags) == flags);
         u.reflags = flags;
     }
 
     void setNumber(double n, DecimalPoint decimalPoint) {
+        JS_ASSERT(type == TOK_NUMBER);
         u.number.value = n;
         u.number.decimalPoint = decimalPoint;
     }
 
     // Type-safe accessors
 
     PropertyName *name() const {
         JS_ASSERT(type == TOK_NAME);