Bug 799252 - Remove SkipRoots in jsstr.cpp; r=Waldo
authorTerrence Cole <terrence@mozilla.com>
Tue, 16 Oct 2012 16:30:02 -0700
changeset 118116 ad453c39bd03affb3026276381cdb0f445d4efed
parent 118115 76c487071a91dc859ea1bc815cf9cdf8cf02fd2e
child 118117 86e85b93cad1d4791aa46e5085536a23b39fc85d
push id24150
push userryanvm@gmail.com
push dateWed, 09 Jan 2013 01:07:17 +0000
treeherdermozilla-central@564336aa34f6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersWaldo
bugs799252
milestone21.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 799252 - Remove SkipRoots in jsstr.cpp; r=Waldo
js/src/jsstr.cpp
mfbt/RangedPtr.h
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -1127,117 +1127,120 @@ RopeMatch(JSContext *cx, JSString *texts
 
         pos += len;
     }
 
     *match = -1;
     return true;
 }
 
-/* ES6 20120708 draft 15.5.4.24. */
+/* ES6 20121026 draft 15.5.4.24. */
 static JSBool
 str_contains(JSContext *cx, unsigned argc, Value *vp)
 {
+    AssertCanGC();
     CallArgs args = CallArgsFromVp(argc, vp);
 
-    // Steps 1 and 2
+    // Steps 1, 2, and 3
     RootedString str(cx, ThisToStringForStringProto(cx, args));
     if (!str)
         return false;
 
-    // Step 3
-    Rooted<JSLinearString *> patstr(cx, ArgToRootedString(cx, args, 0));
-    if (!patstr)
+    // Steps 4 and 5
+    Rooted<JSLinearString*> searchStr(cx, ArgToRootedString(cx, args, 0));
+    if (!searchStr)
         return false;
 
-    // Step 5
-    uint32_t textlen = str->length();
-    const jschar *text = str->getChars(cx);
-    if (!text)
-        return false;
-
-    // XXX fix for moving GC.
-    SkipRoot skip(cx, &text);
-
+    // Steps 6 and 7
+    uint32_t pos = 0;
     if (args.hasDefined(1)) {
-        // Step 4
-        double posDouble;
-        if (!ToInteger(cx, args[1], &posDouble))
-            return false;
-
-        // Step 6
-        uint32_t delta = uint32_t(Min(double(textlen), Max(0.0, posDouble)));
-        text += delta;
-        textlen -= delta;
-    }
-
-    // Step 7
-    uint32_t patlen = patstr->length();
-    const jschar *pat = patstr->chars();
-
-    // Step 8
-    args.rval().setBoolean(StringMatch(text, textlen, pat, patlen) >= 0);
-    return true;
-}
-
-static JSBool
-str_indexOf(JSContext *cx, unsigned argc, Value *vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    RootedString str(cx, ThisToStringForStringProto(cx, args));
-    if (!str)
-        return false;
-
-    JSLinearString *patstr = ArgToRootedString(cx, args, 0);
-    if (!patstr)
-        return false;
-
-    uint32_t textlen = str->length();
-    const jschar *text = str->getChars(cx);
-    if (!text)
-        return false;
-
-    uint32_t patlen = patstr->length();
-    const jschar *pat = patstr->chars();
-    SkipRoot skipPat(cx, &pat);
-
-    uint32_t start;
-    if (args.length() > 1) {
         if (args[1].isInt32()) {
             int i = args[1].toInt32();
-            if (i <= 0) {
-                start = 0;
-            } else if (uint32_t(i) > textlen) {
-                start = textlen;
-                textlen = 0;
-            } else {
-                start = i;
-                text += start;
-                textlen -= start;
-            }
+            pos = (i < 0) ? 0U : uint32_t(i);
         } else {
             double d;
             if (!ToInteger(cx, args[1], &d))
                 return false;
-            if (d <= 0) {
-                start = 0;
-            } else if (d > textlen) {
-                start = textlen;
-                textlen = 0;
-            } else {
-                start = (int)d;
-                text += start;
-                textlen -= start;
-            }
+            pos = uint32_t(Min(Max(d, 0.0), double(UINT32_MAX)));
         }
-    } else {
-        start = 0;
     }
 
-    int match = StringMatch(text, textlen, pat, patlen);
+    AutoAssertNoGC nogc;
+
+    // Step 8
+    uint32_t textLen = str->length();
+    const jschar *textChars = str->getChars(cx);
+    if (!textChars)
+        return false;
+
+    // Step 9
+    uint32_t start = Min(Max(pos, 0U), textLen);
+
+    // Step 10
+    uint32_t searchLen = searchStr->length();
+    const jschar *searchChars = searchStr->chars();
+
+    // Step 11
+    textChars += start;
+    textLen -= start;
+    int match = StringMatch(textChars, textLen, searchChars, searchLen);
+    args.rval().setBoolean(match != -1);
+    return true;
+}
+
+/* ES6 20120927 draft 15.5.4.7. */
+static JSBool
+str_indexOf(JSContext *cx, unsigned argc, Value *vp)
+{
+    AssertCanGC();
+    CallArgs args = CallArgsFromVp(argc, vp);
+
+    // Steps 1, 2, and 3
+    RootedString str(cx, ThisToStringForStringProto(cx, args));
+    if (!str)
+        return false;
+
+    // Steps 4 and 5
+    Rooted<JSLinearString*> searchStr(cx, ArgToRootedString(cx, args, 0));
+    if (!searchStr)
+        return false;
+
+    // Steps 6 and 7
+    uint32_t pos = 0;
+    if (args.hasDefined(1)) {
+        if (args[1].isInt32()) {
+            int i = args[1].toInt32();
+            pos = (i < 0) ? 0U : uint32_t(i);
+        } else {
+            double d;
+            if (!ToInteger(cx, args[1], &d))
+                return false;
+            pos = uint32_t(Min(Max(d, 0.0), double(UINT32_MAX)));
+        }
+    }
+
+    AutoAssertNoGC nogc;
+
+    // Step 8
+    uint32_t textLen = str->length();
+    const jschar *textChars = str->getChars(cx);
+    if (!textChars)
+        return false;
+
+    // Step 9
+    uint32_t start = Min(Max(pos, 0U), textLen);
+
+    // Step 10
+    uint32_t searchLen = searchStr->length();
+    const jschar *searchChars = searchStr->chars();
+
+    // Step 11
+    textChars += start;
+    textLen -= start;
+    int match = StringMatch(textChars, textLen, searchChars, searchLen);
     args.rval().setInt32((match == -1) ? -1 : start + match);
     return true;
 }
 
 static JSBool
 str_lastIndexOf(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
@@ -1309,103 +1312,132 @@ str_lastIndexOf(JSContext *cx, unsigned 
         }
       break_continue:;
     }
 
     args.rval().setInt32(-1);
     return true;
 }
 
-/* ES6 20120708 draft 15.5.4.22. */
+/* ES6 20120927 draft 15.5.4.22. */
 static JSBool
 str_startsWith(JSContext *cx, unsigned argc, Value *vp)
 {
+    AssertCanGC();
     CallArgs args = CallArgsFromVp(argc, vp);
 
-    // Steps 1 and 2
+    // Steps 1, 2, and 3
     RootedString str(cx, ThisToStringForStringProto(cx, args));
     if (!str)
         return false;
 
-    // Step 3
-    Rooted<JSLinearString *> patstr(cx, ArgToRootedString(cx, args, 0));
-    if (!patstr)
+    // Steps 4 and 5
+    Rooted<JSLinearString*> searchStr(cx, ArgToRootedString(cx, args, 0));
+    if (!searchStr)
         return false;
 
-    // Step 5
-    uint32_t textlen = str->length();
-    const jschar *text = str->getChars(cx);
-    if (!text)
-        return false;
-
-    // XXX fix for moving GC.
-    SkipRoot skip(cx, &text);
-
+    // Steps 6 and 7
+    uint32_t pos = 0;
     if (args.hasDefined(1)) {
-        // Step 4
-        double posDouble;
-        if (!ToInteger(cx, args[1], &posDouble))
-            return false;
-
-        // Step 6
-        uint32_t position = Min(double(textlen), Max(0.0, posDouble));
-        text += position;
-        textlen -= position;
+        if (args[1].isInt32()) {
+            int i = args[1].toInt32();
+            pos = (i < 0) ? 0U : uint32_t(i);
+        } else {
+            double d;
+            if (!ToInteger(cx, args[1], &d))
+                return false;
+            pos = uint32_t(Min(Max(d, 0.0), double(UINT32_MAX)));
+        }
     }
 
-    // Step 7
-    uint32_t patlen = patstr->length();
-    const jschar *pat = patstr->chars();
-
-    // Steps 8, 9, and 10.
-    args.rval().setBoolean(textlen >= patlen && PodEqual(text, pat, patlen));
+    AutoAssertNoGC nogc;
+
+    // Step 8
+    uint32_t textLen = str->length();
+    const jschar *textChars = str->getChars(cx);
+    if (!textChars)
+        return false;
+
+    // Step 9
+    uint32_t start = Min(Max(pos, 0U), textLen);
+
+    // Step 10
+    uint32_t searchLen = searchStr->length();
+    const jschar *searchChars = searchStr->chars();
+
+    // Step 11
+    if (searchLen + start < searchLen || searchLen + start > textLen) {
+        args.rval().setBoolean(false);
+        return true;
+    }
+
+    // Steps 12 and 13
+    args.rval().setBoolean(PodEqual(textChars + start, searchChars, searchLen));
     return true;
 }
 
 /* ES6 20120708 draft 15.5.4.23. */
 static JSBool
 str_endsWith(JSContext *cx, unsigned argc, Value *vp)
 {
+    AssertCanGC();
     CallArgs args = CallArgsFromVp(argc, vp);
 
-    // Steps 1 and 2
+    // Steps 1, 2, and 3
     RootedString str(cx, ThisToStringForStringProto(cx, args));
     if (!str)
         return false;
 
-    // Step 3
-    Rooted<JSLinearString *> patstr(cx, ArgToRootedString(cx, args, 0));
-    if (!patstr)
+    // Steps 4 and 5
+    Rooted<JSLinearString *> searchStr(cx, ArgToRootedString(cx, args, 0));
+    if (!searchStr)
         return false;
 
-    // Step 4
-    uint32_t textlen = str->length();
-    const jschar *text = str->getChars(cx);
-    if (!text)
-        return false;
-
-    // XXX fix for moving GC.
-    SkipRoot skip(cx, &text);
-
+    // Step 6
+    uint32_t textLen = str->length();
+
+    // Steps 7 and 8
+    uint32_t pos = textLen;
     if (args.hasDefined(1)) {
-        // Step 5
-        double endPosDouble;
-        if (!ToInteger(cx, args[1], &endPosDouble))
-            return false;
-
-        // Step 6
-        textlen = Min(double(textlen), Max(0.0, endPosDouble));
+        if (args[1].isInt32()) {
+            int i = args[1].toInt32();
+            pos = (i < 0) ? 0U : uint32_t(i);
+        } else {
+            double d;
+            if (!ToInteger(cx, args[1], &d))
+                return false;
+            pos = uint32_t(Min(Max(d, 0.0), double(UINT32_MAX)));
+        }
     }
 
-    // Step 7
-    uint32_t patlen = patstr->length();
-    const jschar *pat = patstr->chars();
-
-    // Steps 8-11
-    args.rval().setBoolean(textlen >= patlen && PodEqual(text + textlen - patlen, pat, patlen));
+    AutoAssertNoGC nogc;
+
+    // Step 6
+    const jschar *textChars = str->getChars(cx);
+    if (!textChars)
+        return false;
+
+    // Step 9
+    uint32_t end = Min(Max(pos, 0U), textLen);
+
+    // Step 10
+    uint32_t searchLen = searchStr->length();
+    const jschar *searchChars = searchStr->chars();
+
+    // Step 12
+    if (searchLen > end) {
+        args.rval().setBoolean(false);
+        return true;
+    }
+
+    // Step 11
+    uint32_t start = end - searchLen;
+
+    // Steps 13 and 14
+    args.rval().setBoolean(PodEqual(textChars + start, searchChars, searchLen));
     return true;
 }
 
 static JSBool
 js_TrimString(JSContext *cx, Value *vp, JSBool trimLeft, JSBool trimRight)
 {
     CallReceiver call = CallReceiverFromVp(vp);
     JSString *str = ThisToStringForStringProto(cx, call);
--- a/mfbt/RangedPtr.h
+++ b/mfbt/RangedPtr.h
@@ -55,16 +55,18 @@ class RangedPtr
     RangedPtr<T> create(T *ptr) const {
 #ifdef DEBUG
       return RangedPtr<T>(ptr, rangeStart, rangeEnd);
 #else
       return RangedPtr<T>(ptr, NULL, size_t(0));
 #endif
     }
 
+    uintptr_t asUintptr() const { return uintptr_t(ptr); }
+
   public:
     RangedPtr(T* p, T* start, T* end)
       : ptr(p)
 #ifdef DEBUG
       , rangeStart(start), rangeEnd(end)
 #endif
     {
       MOZ_ASSERT(rangeStart <= rangeEnd);
@@ -123,23 +125,23 @@ class RangedPtr
       MOZ_ASSERT(rangeEnd == other.rangeEnd);
       ptr = other.ptr;
       checkSanity();
       return *this;
     }
 
     RangedPtr<T> operator+(size_t inc) {
       MOZ_ASSERT(inc <= size_t(-1) / sizeof(T));
-      MOZ_ASSERT(ptr + inc >= ptr);
+      MOZ_ASSERT(asUintptr() + inc * sizeof(T) >= asUintptr());
       return create(ptr + inc);
     }
 
     RangedPtr<T> operator-(size_t dec) {
       MOZ_ASSERT(dec <= size_t(-1) / sizeof(T));
-      MOZ_ASSERT(ptr - dec <= ptr);
+      MOZ_ASSERT(asUintptr() - dec * sizeof(T) <= asUintptr());
       return create(ptr - dec);
     }
 
     /*
      * You can assign a raw pointer into a RangedPtr if the raw pointer is
      * within the range specified at creation.
      */
     template <typename U>