Bug 645417, part 26 - Update jsid sorting for JS_MORE_DETERMINISTIC. r=luke.
authorJason Orendorff <jorendorff@mozilla.com>
Mon, 23 Jun 2014 10:57:03 -0500
changeset 190293 4a04ca5ed7d316f63648a99579575b45d3434a66
parent 190292 c763de6a2fde3ef9741a4960574ebe72f4af1b81
child 190294 dfefe211d083191c0ca99f865958d0839cbdc31e
push id27004
push useremorley@mozilla.com
push dateTue, 24 Jun 2014 15:52:34 +0000
treeherdermozilla-central@7b174d47f3cc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs645417
milestone33.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 645417, part 26 - Update jsid sorting for JS_MORE_DETERMINISTIC. r=luke. Unfortunately, with symbols, the original goal of this code is apparently impossible. For two unique symbols with the same description, short of doing extra bookkeeping at run time, there's no ordering that's sure to be consistent across runs. The new code orders all other symbols.
js/src/jsiter.cpp
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -196,23 +196,63 @@ struct SortComparatorIds
 {
     JSContext   *const cx;
 
     SortComparatorIds(JSContext *cx)
       : cx(cx) {}
 
     bool operator()(jsid a, jsid b, bool *lessOrEqualp)
     {
-        /* Pick an arbitrary total order on jsids that is stable across executions. */
-        RootedString astr(cx, IdToString(cx, a));
-	if (!astr)
-	    return false;
-        RootedString bstr(cx, IdToString(cx, b));
-        if (!bstr)
-            return false;
+        // Pick an arbitrary order on jsids that is as stable as possible
+        // across executions.
+        if (a == b) {
+            *lessOrEqualp = true;
+            return true;
+        }
+
+        size_t ta = JSID_BITS(a) & JSID_TYPE_MASK;
+        size_t tb = JSID_BITS(b) & JSID_TYPE_MASK;
+        if (ta != tb) {
+            *lessOrEqualp = (ta <= tb);
+            return true;
+        }
+
+        if (JSID_IS_INT(a)) {
+            *lessOrEqualp = (JSID_TO_INT(a) <= JSID_TO_INT(b));
+            return true;
+        }
+
+        RootedString astr(cx), bstr(cx);
+        if (JSID_IS_SYMBOL(a)) {
+            MOZ_ASSERT(JSID_IS_SYMBOL(b));
+            JS::SymbolCode ca = JSID_TO_SYMBOL(a)->code();
+            JS::SymbolCode cb = JSID_TO_SYMBOL(b)->code();
+            if (ca != cb) {
+                *lessOrEqualp = uint32_t(ca) <= uint32_t(cb);
+                return true;
+            }
+            JS_ASSERT(ca == JS::SymbolCode::InSymbolRegistry || ca == JS::SymbolCode::Unique);
+            astr = JSID_TO_SYMBOL(a)->description();
+            bstr = JSID_TO_SYMBOL(b)->description();
+            if (!astr || !bstr) {
+                *lessOrEqualp = !astr;
+                return true;
+            }
+
+            // Fall through to string comparison on the descriptions. The sort
+            // order is nondeterministic if two different unique symbols have
+            // the same description.
+        } else {
+            astr = IdToString(cx, a);
+            if (!astr)
+                return false;
+            bstr = IdToString(cx, b);
+            if (!bstr)
+                return false;
+        }
 
         int32_t result;
         if (!CompareStrings(cx, astr, bstr, &result))
             return false;
 
         *lessOrEqualp = (result <= 0);
         return true;
     }