Bug 646599 - Constant folding should happen before deciding whether to turn obj[A] into obj.A. r=Waldo
authorTom Schuster <evilpies@gmail.com>
Sat, 21 Jul 2012 13:05:07 +0200
changeset 100026 28711b9f49cdd827451380906d9a0226a4436c47
parent 100025 c5cd832d82ef8a7c2b7c18471915909647f79166
child 100027 60b949c0eaefd84a770db89459d2825494ada42f
push id12303
push userevilpies@gmail.com
push dateSat, 21 Jul 2012 11:08:04 +0000
treeherdermozilla-inbound@60b949c0eaef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersWaldo
bugs646599
milestone17.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 646599 - Constant folding should happen before deciding whether to turn obj[A] into obj.A. r=Waldo
js/src/frontend/Parser.cpp
js/src/jit-test/tests/basic/testFoldPropertyAccess.js
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -52,16 +52,18 @@
 #endif
 
 #include "jsatominlines.h"
 #include "jsscriptinlines.h"
 
 #include "frontend/ParseMaps-inl.h"
 #include "frontend/ParseNode-inl.h"
 #include "frontend/TreeContext-inl.h"
+
+#include "vm/NumericConversions.h"
 #include "vm/RegExpObject-inl.h"
 
 using namespace js;
 using namespace js::gc;
 using namespace js::frontend;
 
 /*
  * Insist that the next token be of type tt, or report errno and return null.
@@ -5800,39 +5802,48 @@ Parser::memberExpr(bool allowCallSyntax)
             ParseNode *propExpr = expr();
             if (!propExpr)
                 return NULL;
 
             MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_IN_INDEX);
             TokenPtr begin = lhs->pn_pos.begin, end = tokenStream.currentToken().pos.end;
 
             /*
-             * Optimize property name lookups.  If the name is a PropertyName,
+             * Do folding so we don't have roundtrip changes for cases like:
+             * function (obj) { return obj["a" + "b"] }
+             */
+            if (foldConstants && !FoldConstants(context, propExpr, this))
+                return NULL;
+
+            /*
+             * Optimize property name lookups. If the name is a PropertyName,
              * then make a name-based node so the emitter will use a name-based
-             * bytecode.  Otherwise make a node using the property expression
-             * by value.  If the node is a string containing an index, convert
+             * bytecode. Otherwise make a node using the property expression
+             * by value. If the node is a string containing an index, convert
              * it to a number to save work later.
              */
             uint32_t index;
             PropertyName *name = NULL;
             if (propExpr->isKind(PNK_STRING)) {
                 JSAtom *atom = propExpr->pn_atom;
                 if (atom->isIndex(&index)) {
                     propExpr->setKind(PNK_NUMBER);
                     propExpr->setOp(JSOP_DOUBLE);
                     propExpr->pn_dval = index;
                 } else {
                     name = atom->asPropertyName();
                 }
             } else if (propExpr->isKind(PNK_NUMBER)) {
-                JSAtom *atom = ToAtom(context, NumberValue(propExpr->pn_dval));
-                if (!atom)
-                    return NULL;
-                if (!atom->isIndex(&index))
+                double number = propExpr->pn_dval;
+                if (number != ToUint32(number)) {
+                    JSAtom *atom = ToAtom(context, DoubleValue(number));
+                    if (!atom)
+                        return NULL;
                     name = atom->asPropertyName();
+                }
             }
 
             if (name)
                 nextMember = new_<PropertyAccess>(lhs, name, begin, end);
             else
                 nextMember = new_<PropertyByValue>(lhs, propExpr, begin, end);
             if (!nextMember)
                 return NULL;
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/testFoldPropertyAccess.js
@@ -0,0 +1,23 @@
+
+var cases = [
+    function (obj) {
+        return obj["ab"];
+    },
+    function (obj) {
+        return obj["a" + "b"];
+    },
+    function (obj) {
+        return obj[0 ? "cd" : "ab"];
+    },
+    function (obj) {
+        return obj[true ? "ab" : "cd"];
+    },
+    function (obj) {
+        return obj[(1 + 0) ? "ab" : "cd"];
+    }
+]
+
+for (var i = 0; i < cases.length; i++) {
+    assertEq(cases[i]({ab: 42}), 42);
+    assertEq(cases[i]({cd: 120}), undefined);
+}