From c3325c6297e37a6a3320bca2861a97f239c7b36f Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Tue, 16 Oct 2012 16:30:02 -0700 Subject: [PATCH] Bug 799252 - Remove SkipRoots in jsstr.cpp; r=Waldo --- js/src/jsstr.cpp | 296 ++++++++++++++++++++++++++--------------------- mfbt/RangedPtr.h | 6 +- 2 files changed, 168 insertions(+), 134 deletions(-) diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index a72e04d268dc..b98449d73d82 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -1132,107 +1132,110 @@ RopeMatch(JSContext *cx, JSString *textstr, const jschar *pat, uint32_t patlen, 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 patstr(cx, ArgToRootedString(cx, args, 0)); - if (!patstr) + // Steps 4 and 5 + Rooted 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 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; } @@ -1314,49 +1317,60 @@ str_lastIndexOf(JSContext *cx, unsigned argc, Value *vp) 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 patstr(cx, ArgToRootedString(cx, args, 0)); - if (!patstr) + // Steps 4 and 5 + Rooted 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(); + AutoAssertNoGC nogc; - // Steps 8, 9, and 10. - args.rval().setBoolean(textlen >= patlen && PodEqual(text, pat, patlen)); + // 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; } @@ -1364,43 +1378,61 @@ str_startsWith(JSContext *cx, unsigned argc, Value *vp) 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 patstr(cx, ArgToRootedString(cx, args, 0)); - if (!patstr) + // Steps 4 and 5 + Rooted 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(); + AutoAssertNoGC nogc; - // Steps 8-11 - args.rval().setBoolean(textlen >= patlen && PodEqual(text + textlen - patlen, pat, patlen)); + // 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; } diff --git a/mfbt/RangedPtr.h b/mfbt/RangedPtr.h index adecf7c1a097..ecc8063410e6 100644 --- a/mfbt/RangedPtr.h +++ b/mfbt/RangedPtr.h @@ -60,6 +60,8 @@ class RangedPtr #endif } + uintptr_t asUintptr() const { return uintptr_t(ptr); } + public: RangedPtr(T* p, T* start, T* end) : ptr(p) @@ -128,13 +130,13 @@ class RangedPtr RangedPtr 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 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); }