Bug 1025174 - Add RootedLinearString and HandleLinearString typedefs. r=terrence
authorJan de Mooij <jdemooij@mozilla.com>
Sat, 14 Jun 2014 10:51:49 +0200
changeset 188750 c4ed75d98fe37e1234643e434bcca283bef67a06
parent 188749 8d99f061ec3599cf8ca3563fa9e1edaa06470ad7
child 188751 c1d28cf0b805b8d2601e4621baa9acd1f16e22c3
push id44904
push userjandemooij@gmail.com
push dateSat, 14 Jun 2014 08:53:24 +0000
treeherdermozilla-inbound@c4ed75d98fe3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence
bugs1025174
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 1025174 - Add RootedLinearString and HandleLinearString typedefs. r=terrence
js/src/builtin/Eval.cpp
js/src/builtin/Object.cpp
js/src/builtin/RegExp.cpp
js/src/builtin/RegExp.h
js/src/gc/Rooting.h
js/src/jsopcode.cpp
js/src/jsstr.cpp
js/src/vm/Runtime.h
js/src/vm/String-inl.h
--- a/js/src/builtin/Eval.cpp
+++ b/js/src/builtin/Eval.cpp
@@ -84,17 +84,17 @@ class EvalScriptGuard
 {
     JSContext *cx_;
     Rooted<JSScript*> script_;
 
     /* These fields are only valid if lookup_.str is non-nullptr. */
     EvalCacheLookup lookup_;
     EvalCache::AddPtr p_;
 
-    Rooted<JSLinearString*> lookupStr_;
+    RootedLinearString lookupStr_;
 
   public:
     explicit EvalScriptGuard(JSContext *cx)
         : cx_(cx), script_(cx), lookup_(cx), lookupStr_(cx) {}
 
     ~EvalScriptGuard() {
         if (script_) {
             CallDestroyScriptHook(cx_->runtime()->defaultFreeOp(), script_);
--- a/js/src/builtin/Object.cpp
+++ b/js/src/builtin/Object.cpp
@@ -168,17 +168,18 @@ js::ObjectToSource(JSContext *cx, Handle
             }
         }
 
         /* Convert id to a linear string. */
         RootedValue idv(cx, IdToValue(id));
         JSString *s = ToString<CanGC>(cx, idv);
         if (!s)
             return nullptr;
-        Rooted<JSLinearString*> idstr(cx, s->ensureLinear(cx));
+
+        RootedLinearString idstr(cx, s->ensureLinear(cx));
         if (!idstr)
             return nullptr;
 
         /*
          * If id is a string that's not an identifier, or if it's a negative
          * integer, then it must be quoted.
          */
         if (JSID_IS_ATOM(id)
--- a/js/src/builtin/RegExp.cpp
+++ b/js/src/builtin/RegExp.cpp
@@ -86,17 +86,17 @@ js::CreateRegExpMatchResult(JSContext *c
 #endif
 
     rval.setObject(*arr);
     return true;
 }
 
 static RegExpRunStatus
 ExecuteRegExpImpl(JSContext *cx, RegExpStatics *res, RegExpShared &re,
-                  Handle<JSLinearString*> input, const jschar *chars, size_t length,
+                  HandleLinearString input, const jschar *chars, size_t length,
                   size_t *lastIndex, MatchConduit &matches)
 {
     RegExpRunStatus status;
 
     /* Switch between MatchOnly and IncludeSubpatterns modes. */
     if (matches.isPair) {
 #ifdef JS_YARR
         size_t lastIndex_orig = *lastIndex;
@@ -116,17 +116,17 @@ ExecuteRegExpImpl(JSContext *cx, RegExpS
         }
     }
     return status;
 }
 
 /* Legacy ExecuteRegExp behavior is baked into the JSAPI. */
 bool
 js::ExecuteRegExpLegacy(JSContext *cx, RegExpStatics *res, RegExpObject &reobj,
-                        Handle<JSLinearString*> input_, const jschar *chars, size_t length,
+                        HandleLinearString input_, const jschar *chars, size_t length,
                         size_t *lastIndex, bool test, MutableHandleValue rval)
 {
     RegExpGuard shared(cx);
     if (!reobj.getShared(cx, &shared))
         return false;
 
     ScopedMatchPairs matches(&cx->tempLifoAlloc());
     MatchConduit conduit(&matches);
@@ -557,17 +557,17 @@ js::ExecuteRegExp(JSContext *cx, HandleO
         res = cx->global()->getRegExpStatics(cx);
         if (!res)
             return RegExpRunStatus_Error;
     } else {
         res = nullptr;
     }
 
     /* Step 3. */
-    Rooted<JSLinearString*> input(cx, string->ensureLinear(cx));
+    RootedLinearString input(cx, string->ensureLinear(cx));
     if (!input)
         return RegExpRunStatus_Error;
 
     /* Step 4. */
     RootedValue lastIndex(cx, reobj->getLastIndex());
     size_t length = input->length();
 
     /* Step 5. */
--- a/js/src/builtin/RegExp.h
+++ b/js/src/builtin/RegExp.h
@@ -33,17 +33,17 @@ ExecuteRegExp(JSContext *cx, HandleObjec
  * Legacy behavior of ExecuteRegExp(), which is baked into the JSAPI.
  *
  * |res| may be nullptr if the RegExpStatics are not to be updated.
  * |input| may be nullptr if there is no JSString corresponding to
  * |chars| and |length|.
  */
 bool
 ExecuteRegExpLegacy(JSContext *cx, RegExpStatics *res, RegExpObject &reobj,
-                    Handle<JSLinearString*> input, const jschar *chars, size_t length,
+                    HandleLinearString input, const jschar *chars, size_t length,
                     size_t *lastIndex, bool test, MutableHandleValue rval);
 
 /* Translation from MatchPairs to a JS array in regexp_exec()'s output format. */
 bool
 CreateRegExpMatchResult(JSContext *cx, HandleString input, const MatchPairs &matches,
                         MutableHandleValue rval);
 
 extern bool
--- a/js/src/gc/Rooting.h
+++ b/js/src/gc/Rooting.h
@@ -5,36 +5,39 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef gc_Rooting_h
 #define gc_Rooting_h
 
 #include "js/RootingAPI.h"
 
 class JSAtom;
+class JSLinearString;
 
 namespace js {
 
 class PropertyName;
 class Shape;
 
 namespace types { struct TypeObject; }
 
 // These are internal counterparts to the public types such as HandleObject.
 
 typedef JS::Handle<Shape*>             HandleShape;
 typedef JS::Handle<types::TypeObject*> HandleTypeObject;
 typedef JS::Handle<JSAtom*>            HandleAtom;
+typedef JS::Handle<JSLinearString*>    HandleLinearString;
 typedef JS::Handle<PropertyName*>      HandlePropertyName;
 typedef JS::Handle<js::ScriptSourceObject*> HandleScriptSource;
 
 typedef JS::MutableHandle<Shape*>      MutableHandleShape;
 typedef JS::MutableHandle<JSAtom*>     MutableHandleAtom;
 
 typedef JS::Rooted<Shape*>             RootedShape;
 typedef JS::Rooted<types::TypeObject*> RootedTypeObject;
 typedef JS::Rooted<JSAtom*>            RootedAtom;
+typedef JS::Rooted<JSLinearString*>    RootedLinearString;
 typedef JS::Rooted<PropertyName*>      RootedPropertyName;
 typedef JS::Rooted<js::ScriptSourceObject*> RootedScriptSource;
 
 } /* namespace js */
 
 #endif /* gc_Rooting_h */
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -1800,17 +1800,17 @@ js::DecompileValueGenerator(JSContext *c
     if (!fallback) {
         if (v.isUndefined())
             return JS_strdup(cx, js_undefined_str); // Prevent users from seeing "(void 0)"
         fallback = ValueToSource(cx, v);
         if (!fallback)
             return nullptr;
     }
 
-    Rooted<JSLinearString *> linear(cx, fallback->ensureLinear(cx));
+    RootedLinearString linear(cx, fallback->ensureLinear(cx));
     if (!linear)
         return nullptr;
     TwoByteChars tbchars(linear->chars(), linear->length());
     return LossyTwoByteCharsToNewLatin1CharsZ(cx, tbchars).c_str();
 }
 
 static bool
 DecompileArgumentFromStack(JSContext *cx, int formalIndex, char **res)
@@ -1887,17 +1887,17 @@ js::DecompileArgument(JSContext *cx, int
         }
     }
     if (v.isUndefined())
         return JS_strdup(cx, js_undefined_str); // Prevent users from seeing "(void 0)"
     RootedString fallback(cx, ValueToSource(cx, v));
     if (!fallback)
         return nullptr;
 
-    Rooted<JSLinearString *> linear(cx, fallback->ensureLinear(cx));
+    RootedLinearString linear(cx, fallback->ensureLinear(cx));
     if (!linear)
         return nullptr;
     return LossyTwoByteCharsToNewLatin1CharsZ(cx, linear->range()).c_str();
 }
 
 bool
 js::CallResultEscapes(jsbytecode *pc)
 {
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -72,18 +72,16 @@ using mozilla::IsNegativeZero;
 using mozilla::IsSame;
 using mozilla::PodCopy;
 using mozilla::PodEqual;
 using mozilla::Range;
 using mozilla::SafeCast;
 
 using JS::AutoCheckCannotGC;
 
-typedef Handle<JSLinearString*> HandleLinearString;
-
 static JSLinearString *
 ArgToRootedString(JSContext *cx, CallArgs &args, unsigned argno)
 {
     if (argno >= args.length())
         return cx->names().undefined;
 
     JSString *str = ToString<CanGC>(cx, args[argno]);
     if (!str)
@@ -895,17 +893,17 @@ str_normalize(JSContext *cx, unsigned ar
         return false;
 
     // Step 4.
     UNormalizationMode form;
     if (!args.hasDefined(0)) {
         form = UNORM_NFC;
     } else {
         // Steps 5-6.
-        Rooted<JSLinearString*> formStr(cx, ArgToRootedString(cx, args, 0));
+        RootedLinearString formStr(cx, ArgToRootedString(cx, args, 0));
         if (!formStr)
             return false;
 
         // Step 7.
         if (formStr == cx->names().NFC) {
             form = UNORM_NFC;
         } else if (formStr == cx->names().NFD) {
             form = UNORM_NFD;
@@ -1335,17 +1333,17 @@ js::StringFindPattern(const jschar *text
 // When an algorithm does not need a string represented as a single linear
 // array of characters, this range utility may be used to traverse the string a
 // sequence of linear arrays of characters. This avoids flattening ropes.
 class StringSegmentRange
 {
     // If malloc() shows up in any profiles from this vector, we can add a new
     // StackAllocPolicy which stashes a reusable freed-at-gc buffer in the cx.
     AutoStringVector stack;
-    Rooted<JSLinearString*> cur;
+    RootedLinearString cur;
 
     bool settle(JSString *str) {
         while (str->isRope()) {
             JSRope &rope = str->asRope();
             if (!stack.append(rope.rightChild()))
                 return false;
             str = rope.leftChild();
         }
@@ -1522,17 +1520,17 @@ str_contains(JSContext *cx, unsigned arg
     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));
+    RootedLinearString 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();
@@ -1567,17 +1565,17 @@ str_indexOf(JSContext *cx, unsigned argc
     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));
+    RootedLinearString 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();
@@ -1637,17 +1635,17 @@ LastIndexOfImpl(const TextChar *text, si
 static bool
 str_lastIndexOf(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     RootedString textstr(cx, ThisToStringForStringProto(cx, args));
     if (!textstr)
         return false;
 
-    Rooted<JSLinearString*> pat(cx, ArgToRootedString(cx, args, 0));
+    RootedLinearString pat(cx, ArgToRootedString(cx, args, 0));
     if (!pat)
         return false;
 
     size_t textLen = textstr->length();
     size_t patLen = pat->length();
     int start = textLen - patLen; // Start searching here
     if (start < 0) {
         args.rval().setInt32(-1);
@@ -1741,17 +1739,17 @@ str_startsWith(JSContext *cx, unsigned a
     // Step 4
     if (args.get(0).isObject() && IsObjectWithClass(args[0], ESClass_RegExp, cx)) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_INVALID_ARG_TYPE,
                              "first", "", "Regular Expression");
         return false;
     }
 
     // Steps 5 and 6
-    Rooted<JSLinearString*> searchStr(cx, ArgToRootedString(cx, args, 0));
+    RootedLinearString searchStr(cx, ArgToRootedString(cx, args, 0));
     if (!searchStr)
         return false;
 
     // Steps 7 and 8
     uint32_t pos = 0;
     if (args.hasDefined(1)) {
         if (args[1].isInt32()) {
             int i = args[1].toInt32();
@@ -1802,17 +1800,17 @@ str_endsWith(JSContext *cx, unsigned arg
     // Step 4
     if (args.get(0).isObject() && IsObjectWithClass(args[0], ESClass_RegExp, cx)) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_INVALID_ARG_TYPE,
                              "first", "", "Regular Expression");
         return false;
     }
 
     // Steps 5 and 6
-    Rooted<JSLinearString *> searchStr(cx, ArgToRootedString(cx, args, 0));
+    RootedLinearString searchStr(cx, ArgToRootedString(cx, args, 0));
     if (!searchStr)
         return false;
 
     // Step 7
     uint32_t textLen = str->length();
 
     // Steps 8 and 9
     uint32_t pos = textLen;
@@ -2171,17 +2169,17 @@ class MOZ_STACK_CLASS StringRegExpGuard
   private:
     StringRegExpGuard(const StringRegExpGuard &) MOZ_DELETE;
     void operator=(const StringRegExpGuard &) MOZ_DELETE;
 };
 
 } /* anonymous namespace */
 
 static bool
-DoMatchLocal(JSContext *cx, CallArgs args, RegExpStatics *res, Handle<JSLinearString*> input,
+DoMatchLocal(JSContext *cx, CallArgs args, RegExpStatics *res, HandleLinearString input,
              RegExpShared &re)
 {
     size_t charsLen = input->length();
     const jschar *chars = input->chars();
 
     size_t i = 0;
     ScopedMatchPairs matches(&cx->tempLifoAlloc());
     RegExpRunStatus status = re.execute(cx, chars, charsLen, &i, matches);
@@ -2201,17 +2199,17 @@ DoMatchLocal(JSContext *cx, CallArgs arg
         return false;
 
     args.rval().set(rval);
     return true;
 }
 
 /* ES5 15.5.4.10 step 8. */
 static bool
-DoMatchGlobal(JSContext *cx, CallArgs args, RegExpStatics *res, Handle<JSLinearString*> input,
+DoMatchGlobal(JSContext *cx, CallArgs args, RegExpStatics *res, HandleLinearString input,
               StringRegExpGuard &g)
 {
     // Step 8a.
     //
     // This single zeroing of "lastIndex" covers all "lastIndex" changes in the
     // rest of String.prototype.match, particularly in steps 8f(i) and
     // 8f(iii)(2)(a).  Here's why.
     //
@@ -2374,17 +2372,17 @@ js::str_match(JSContext *cx, unsigned ar
     /* Create regular-expression internals as needed to perform the match. */
     if (!g.normalizeRegExp(cx, false, 1, args))
         return false;
 
     RegExpStatics *res = cx->global()->getRegExpStatics(cx);
     if (!res)
         return false;
 
-    Rooted<JSLinearString*> linearStr(cx, str->ensureLinear(cx));
+    RootedLinearString linearStr(cx, str->ensureLinear(cx));
     if (!linearStr)
         return false;
 
     /* Steps 5-6, 7. */
     if (!g.regExp().global())
         return DoMatchLocal(cx, args, res, linearStr, g.regExp());
 
     /* Steps 6, 8. */
@@ -2408,17 +2406,17 @@ js::str_search(JSContext *cx, unsigned a
     }
 
     if (cx->isExceptionPending())  /* from tryFlatMatch */
         return false;
 
     if (!g.normalizeRegExp(cx, false, 1, args))
         return false;
 
-    Rooted<JSLinearString*> linearStr(cx, str->ensureLinear(cx));
+    RootedLinearString linearStr(cx, str->ensureLinear(cx));
     if (!linearStr)
         return false;
 
     const jschar *chars = linearStr->chars();
     size_t length = linearStr->length();
     RegExpStatics *res = cx->global()->getRegExpStatics(cx);
     if (!res)
         return false;
@@ -2501,32 +2499,32 @@ struct ReplaceData
         repstr = nullptr;
         dollarIndex = UINT32_MAX;
     }
 
     RootedString       str;            /* 'this' parameter object as a string */
     StringRegExpGuard  g;              /* regexp parameter object and private data */
     RootedObject       lambda;         /* replacement function object or null */
     RootedObject       elembase;       /* object for function(a){return b[a]} replace */
-    Rooted<JSLinearString*> repstr;    /* replacement string */
+    RootedLinearString repstr;         /* replacement string */
     uint32_t           dollarIndex;    /* index of first $ in repstr, or UINT32_MAX */
     int                leftIndex;      /* left context index in str->chars */
     JSSubString        dollarStr;      /* for "$$" InterpretDollar result */
     bool               calledBack;     /* record whether callback has been called */
     FastInvokeGuard    fig;            /* used for lambda calls, also holds arguments */
     StringBuffer       sb;             /* buffer built during DoMatch */
 };
 
 } /* anonymous namespace */
 
 static bool
 ReplaceRegExp(JSContext *cx, RegExpStatics *res, ReplaceData &rdata);
 
 static bool
-DoMatchForReplaceLocal(JSContext *cx, RegExpStatics *res, Handle<JSLinearString*> linearStr,
+DoMatchForReplaceLocal(JSContext *cx, RegExpStatics *res, HandleLinearString linearStr,
                        RegExpShared &re, ReplaceData &rdata)
 {
     size_t charsLen = linearStr->length();
     size_t i = 0;
     ScopedMatchPairs matches(&cx->tempLifoAlloc());
     RegExpRunStatus status = re.execute(cx, linearStr->chars(), charsLen, &i, matches);
     if (status == RegExpRunStatus_Error)
         return false;
@@ -2536,17 +2534,17 @@ DoMatchForReplaceLocal(JSContext *cx, Re
 
     if (!res->updateFromMatchPairs(cx, linearStr, matches))
         return false;
 
     return ReplaceRegExp(cx, res, rdata);
 }
 
 static bool
-DoMatchForReplaceGlobal(JSContext *cx, RegExpStatics *res, Handle<JSLinearString*> linearStr,
+DoMatchForReplaceGlobal(JSContext *cx, RegExpStatics *res, HandleLinearString linearStr,
                         RegExpShared &re, ReplaceData &rdata)
 {
     size_t charsLen = linearStr->length();
     ScopedMatchPairs matches(&cx->tempLifoAlloc());
     for (size_t count = 0, i = 0; i <= charsLen; ++count) {
         if (!CheckForInterrupt(cx))
             return false;
 
@@ -2921,17 +2919,17 @@ BuildFlatReplacement(JSContext *cx, Hand
  * constructing a result string that looks like:
  *
  *      newstring = string[:matchStart] + dollarSub(replaceValue) + string[matchLimit:]
  */
 static inline bool
 BuildDollarReplacement(JSContext *cx, JSString *textstrArg, JSLinearString *repstr,
                        uint32_t firstDollarIndex, const FlatMatch &fm, MutableHandleValue rval)
 {
-    Rooted<JSLinearString*> textstr(cx, textstrArg->ensureLinear(cx));
+    RootedLinearString textstr(cx, textstrArg->ensureLinear(cx));
     if (!textstr)
         return false;
 
     size_t matchStart = fm.match();
     size_t matchLimit = matchStart + fm.patternLength();
 
     /*
      * Most probably:
@@ -3210,17 +3208,17 @@ StrReplaceRegExp(JSContext *cx, ReplaceD
         return false;
 
     /* Optimize removal. */
     if (rdata.repstr && rdata.repstr->length() == 0) {
         JS_ASSERT(!rdata.lambda && !rdata.elembase && rdata.dollarIndex == UINT32_MAX);
         return StrReplaceRegexpRemove(cx, rdata.str, re, rval);
     }
 
-    Rooted<JSLinearString*> linearStr(cx, rdata.str->ensureLinear(cx));
+    RootedLinearString linearStr(cx, rdata.str->ensureLinear(cx));
     if (!linearStr)
         return false;
 
     if (re.global()) {
         if (!DoMatchForReplaceGlobal(cx, res, linearStr, re, rdata))
             return false;
     } else {
         if (!DoMatchForReplaceLocal(cx, res, linearStr, re, rdata))
@@ -3519,17 +3517,17 @@ class SplitMatchResult {
         endIndex_ = endIndex;
     }
 };
 
 } /* anonymous namespace */
 
 template<class Matcher>
 static ArrayObject *
-SplitHelper(JSContext *cx, Handle<JSLinearString*> str, uint32_t limit, const Matcher &splitMatch,
+SplitHelper(JSContext *cx, HandleLinearString str, uint32_t limit, const Matcher &splitMatch,
             Handle<TypeObject*> type)
 {
     size_t strLength = str->length();
     SplitMatchResult result;
 
     /* Step 11. */
     if (strLength == 0) {
         if (!splitMatch(cx, str, 0, &result))
@@ -3650,17 +3648,17 @@ SplitHelper(JSContext *cx, Handle<JSLine
         return nullptr;
 
     /* Step 16. */
     return NewDenseCopiedArray(cx, splits.length(), splits.begin());
 }
 
 // Fast-path for splitting a string into a character array via split("").
 static ArrayObject *
-CharSplitHelper(JSContext *cx, Handle<JSLinearString*> str, uint32_t limit)
+CharSplitHelper(JSContext *cx, HandleLinearString str, uint32_t limit)
 {
     size_t strLength = str->length();
     if (strLength == 0)
         return NewDenseEmptyArray(cx);
 
     js::StaticStrings &staticStrings = cx->staticStrings();
     uint32_t resultlen = (limit < strLength ? limit : strLength);
 
@@ -3692,17 +3690,17 @@ class SplitRegExpMatcher
     RegExpShared &re;
     RegExpStatics *res;
 
   public:
     SplitRegExpMatcher(RegExpShared &re, RegExpStatics *res) : re(re), res(res) {}
 
     static const bool returnsCaptures = true;
 
-    bool operator()(JSContext *cx, Handle<JSLinearString*> str, size_t index,
+    bool operator()(JSContext *cx, HandleLinearString str, size_t index,
                     SplitMatchResult *result) const
     {
         const jschar *chars = str->chars();
         size_t length = str->length();
 
         ScopedMatchPairs matches(&cx->tempLifoAlloc());
         RegExpRunStatus status = re.execute(cx, chars, length, &index, matches);
         if (status == RegExpRunStatus_Error)
@@ -3721,17 +3719,17 @@ class SplitRegExpMatcher
 
         result->setResult(sep.length, index);
         return true;
     }
 };
 
 class SplitStringMatcher
 {
-    Rooted<JSLinearString*> sep;
+    RootedLinearString sep;
 
   public:
     SplitStringMatcher(JSContext *cx, HandleLinearString sep)
       : sep(cx, sep)
     {}
 
     static const bool returnsCaptures = false;
 
@@ -3809,17 +3807,17 @@ js::str_split(JSContext *cx, unsigned ar
         RootedValue v(cx, StringValue(str));
         JSObject *aobj = NewDenseCopiedArray(cx, 1, v.address());
         if (!aobj)
             return false;
         aobj->setType(type);
         args.rval().setObject(*aobj);
         return true;
     }
-    Rooted<JSLinearString*> linearStr(cx, str->ensureLinear(cx));
+    RootedLinearString linearStr(cx, str->ensureLinear(cx));
     if (!linearStr)
         return false;
 
     /* Steps 11-15. */
     RootedObject aobj(cx);
     if (!re.initialized()) {
         if (sepstr->length() == 0) {
             aobj = CharSplitHelper(cx, linearStr, limit);
@@ -3841,21 +3839,21 @@ js::str_split(JSContext *cx, unsigned ar
     aobj->setType(type);
     args.rval().setObject(*aobj);
     return true;
 }
 
 JSObject *
 js::str_split_string(JSContext *cx, HandleTypeObject type, HandleString str, HandleString sep)
 {
-    Rooted<JSLinearString*> linearStr(cx, str->ensureLinear(cx));
+    RootedLinearString linearStr(cx, str->ensureLinear(cx));
     if (!linearStr)
         return nullptr;
 
-    Rooted<JSLinearString*> linearSep(cx, sep->ensureLinear(cx));
+    RootedLinearString linearSep(cx, sep->ensureLinear(cx));
     if (!linearSep)
         return nullptr;
 
     uint32_t limit = UINT32_MAX;
 
     RootedObject aobj(cx);
     if (linearSep->length() == 0) {
         aobj = CharSplitHelper(cx, linearStr, limit);
@@ -4849,17 +4847,17 @@ TransferBufferToString(StringBuffer &sb,
 /*
  * ECMA 3, 15.1.3 URI Handling Function Properties
  *
  * The following are implementations of the algorithms
  * given in the ECMA specification for the hidden functions
  * 'Encode' and 'Decode'.
  */
 static bool
-Encode(JSContext *cx, Handle<JSLinearString*> str, const bool *unescapedSet,
+Encode(JSContext *cx, HandleLinearString str, const bool *unescapedSet,
        const bool *unescapedSet2, MutableHandleValue rval)
 {
     static const char HexDigits[] = "0123456789ABCDEF"; /* NB: uppercase */
 
     size_t length = str->length();
     if (length == 0) {
         rval.setString(cx->runtime()->emptyString);
         return true;
@@ -4910,17 +4908,17 @@ Encode(JSContext *cx, Handle<JSLinearStr
             }
         }
     }
 
     return TransferBufferToString(sb, rval);
 }
 
 static bool
-Decode(JSContext *cx, Handle<JSLinearString*> str, const bool *reservedSet, MutableHandleValue rval)
+Decode(JSContext *cx, HandleLinearString str, const bool *reservedSet, MutableHandleValue rval)
 {
     size_t length = str->length();
     if (length == 0) {
         rval.setString(cx->runtime()->emptyString);
         return true;
     }
 
     const jschar *chars = str->chars();
@@ -4993,50 +4991,50 @@ Decode(JSContext *cx, Handle<JSLinearStr
 
     return false;
 }
 
 static bool
 str_decodeURI(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    Rooted<JSLinearString*> str(cx, ArgToRootedString(cx, args, 0));
+    RootedLinearString str(cx, ArgToRootedString(cx, args, 0));
     if (!str)
         return false;
 
     return Decode(cx, str, js_isUriReservedPlusPound, args.rval());
 }
 
 static bool
 str_decodeURI_Component(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    Rooted<JSLinearString*> str(cx, ArgToRootedString(cx, args, 0));
+    RootedLinearString str(cx, ArgToRootedString(cx, args, 0));
     if (!str)
         return false;
 
     return Decode(cx, str, nullptr, args.rval());
 }
 
 static bool
 str_encodeURI(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    Rooted<JSLinearString*> str(cx, ArgToRootedString(cx, args, 0));
+    RootedLinearString str(cx, ArgToRootedString(cx, args, 0));
     if (!str)
         return false;
 
     return Encode(cx, str, js_isUriUnescaped, js_isUriReservedPlusPound, args.rval());
 }
 
 static bool
 str_encodeURI_Component(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    Rooted<JSLinearString*> str(cx, ArgToRootedString(cx, args, 0));
+    RootedLinearString str(cx, ArgToRootedString(cx, args, 0));
     if (!str)
         return false;
 
     return Encode(cx, str, js_isUriUnescaped, nullptr, args.rval());
 }
 
 /*
  * Convert one UCS-4 char and write it into a UTF-8 buffer, which must be at
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -76,18 +76,16 @@ js_ReportOverRecursed(js::ThreadSafeCont
 namespace JSC { class ExecutableAllocator; }
 
 #ifdef JS_YARR
 namespace WTF { class BumpPointerAllocator; }
 #endif
 
 namespace js {
 
-typedef Rooted<JSLinearString*> RootedLinearString;
-
 class Activation;
 class ActivationIterator;
 class AsmJSActivation;
 class MathCache;
 
 namespace jit {
 class JitRuntime;
 class JitActivation;
--- a/js/src/vm/String-inl.h
+++ b/js/src/vm/String-inl.h
@@ -86,17 +86,17 @@ NewFatInlineString(ThreadSafeContext *cx
 
     mozilla::PodCopy(storage, chars.start().get(), len);
     storage[len] = 0;
     return str;
 }
 
 template <typename CharT>
 static MOZ_ALWAYS_INLINE JSInlineString *
-NewFatInlineString(ExclusiveContext *cx, Handle<JSLinearString*> base, size_t start, size_t length)
+NewFatInlineString(ExclusiveContext *cx, HandleLinearString base, size_t start, size_t length)
 {
     MOZ_ASSERT(JSFatInlineString::lengthFits<CharT>(length));
 
     CharT *chars;
     JSInlineString *s = AllocateFatInlineString<CanGC>(cx, length, &chars);
     if (!s)
         return nullptr;
 
@@ -201,29 +201,29 @@ JSDependentString::new_(js::ExclusiveCon
      * Do not create a string dependent on inline chars from another string,
      * both to avoid the awkward moving-GC hazard this introduces and because it
      * is more efficient to immediately undepend here.
      */
     bool useFatInline = baseArg->hasTwoByteChars()
                         ? JSFatInlineString::twoByteLengthFits(length)
                         : JSFatInlineString::latin1LengthFits(length);
     if (useFatInline) {
-        JS::Rooted<JSLinearString*> base(cx, baseArg);
+        js::RootedLinearString base(cx, baseArg);
         if (baseArg->hasLatin1Chars())
             return js::NewFatInlineString<JS::Latin1Char>(cx, base, start, length);
         return js::NewFatInlineString<jschar>(cx, base, start, length);
     }
 
     JSDependentString *str = (JSDependentString *)js_NewGCString<js::NoGC>(cx);
     if (str) {
         str->init(cx, baseArg, start, length);
         return str;
     }
 
-    JS::Rooted<JSLinearString*> base(cx, baseArg);
+    js::RootedLinearString base(cx, baseArg);
 
     str = (JSDependentString *)js_NewGCString<js::CanGC>(cx);
     if (!str)
         return nullptr;
     str->init(cx, base, start, length);
     return str;
 }