Bug 1202048 - Root JSONParser explicitly; r=sfink
authorTerrence Cole <terrence@mozilla.com>
Thu, 20 Aug 2015 12:26:45 -0700
changeset 296963 033130a2b1be3eda63aa0cc3d9f2d93b7010e58d
parent 296962 380817d573cdfbfc4a4b4a4647cf1a53bb52c3b9
child 296964 b33de7c40755ddac916c71dfc6eedbc117287d72
push id962
push userjlund@mozilla.com
push dateFri, 04 Dec 2015 23:28:54 +0000
treeherdermozilla-release@23a2d286e80f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfink
bugs1202048
milestone43.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 1202048 - Root JSONParser explicitly; r=sfink
js/src/builtin/Eval.cpp
js/src/gc/RootMarking.cpp
js/src/json.cpp
js/src/jspubtd.h
js/src/vm/JSONParser.h
--- a/js/src/builtin/Eval.cpp
+++ b/js/src/builtin/Eval.cpp
@@ -178,17 +178,17 @@ ParseEvalStringAsJSON(JSContext* cx, con
     size_t len = chars.length();
     MOZ_ASSERT((chars[0] == '(' && chars[len - 1] == ')') ||
                (chars[0] == '[' && chars[len - 1] == ']'));
 
     auto jsonChars = (chars[0] == '[')
                      ? chars
                      : mozilla::Range<const CharT>(chars.start().get() + 1U, len - 2);
 
-    JSONParser<CharT> parser(cx, jsonChars, JSONParserBase::NoError);
+    Rooted<JSONParser<CharT>> parser(cx, JSONParser<CharT>(cx, jsonChars, JSONParserBase::NoError));
     if (!parser.parse(rval))
         return EvalJSON_Failure;
 
     return rval.isUndefined() ? EvalJSON_NotJSON : EvalJSON_Success;
 }
 
 static EvalJSONResult
 TryEvalJSON(JSContext* cx, JSLinearString* str, MutableHandleValue rval)
--- a/js/src/gc/RootMarking.cpp
+++ b/js/src/gc/RootMarking.cpp
@@ -141,20 +141,16 @@ AutoGCRooter::trace(JSTracer* trc)
          * wrapper roots in every slice. This is because of some rule-breaking
          * in RemapAllWrappersForObject; see comment there.
          */
         for (WrapperValue* p = vector.begin(); p < vector.end(); p++)
             TraceManuallyBarrieredEdge(trc, &p->get(), "js::AutoWrapperVector.vector");
         return;
       }
 
-      case JSONPARSER:
-        static_cast<js::JSONParserBase*>(this)->trace(trc);
-        return;
-
       case CUSTOM:
         static_cast<JS::CustomAutoRooter*>(this)->trace(trc);
         return;
     }
 
     MOZ_ASSERT(tag_ >= 0);
     if (Value* vp = static_cast<AutoArrayRooter*>(this)->array)
         TraceRootRange(trc, tag_, vp, "JS::AutoArrayRooter.array");
--- a/js/src/json.cpp
+++ b/js/src/json.cpp
@@ -817,17 +817,17 @@ Revive(JSContext* cx, HandleValue revive
 }
 
 template <typename CharT>
 bool
 js::ParseJSONWithReviver(JSContext* cx, const mozilla::Range<const CharT> chars, HandleValue reviver,
                          MutableHandleValue vp)
 {
     /* 15.12.2 steps 2-3. */
-    JSONParser<CharT> parser(cx, chars);
+    Rooted<JSONParser<CharT>> parser(cx, JSONParser<CharT>(cx, chars));
     if (!parser.parse(vp))
         return false;
 
     /* 15.12.2 steps 4-5. */
     if (IsCallable(reviver))
         return Revive(cx, reviver, vp);
     return true;
 }
--- a/js/src/jspubtd.h
+++ b/js/src/jspubtd.h
@@ -219,17 +219,16 @@ class JS_PUBLIC_API(AutoGCRooter)
         VALARRAY =     -2, /* js::AutoValueArray */
         PARSER =       -3, /* js::frontend::Parser */
         VALVECTOR =   -10, /* js::AutoValueVector */
         IDVECTOR =    -11, /* js::AutoIdVector */
         OBJVECTOR =   -14, /* js::AutoObjectVector */
         IONMASM =     -19, /* js::jit::MacroAssembler */
         WRAPVECTOR =  -20, /* js::AutoWrapperVector */
         WRAPPER =     -21, /* js::AutoWrapperRooter */
-        JSONPARSER =  -25, /* js::JSONParser */
         CUSTOM =      -26  /* js::CustomAutoRooter */
     };
 
     static ptrdiff_t GetTag(const Value& value) { return VALVECTOR; }
     static ptrdiff_t GetTag(const jsid& id) { return IDVECTOR; }
     static ptrdiff_t GetTag(JSObject* obj) { return OBJVECTOR; }
 
   private:
--- a/js/src/vm/JSONParser.h
+++ b/js/src/vm/JSONParser.h
@@ -15,17 +15,17 @@
 #include "ds/IdValuePair.h"
 #include "vm/String.h"
 
 namespace js {
 
 // JSONParser base class. JSONParser is templatized to work on either Latin1
 // or TwoByte input strings, JSONParserBase holds all state and methods that
 // can be shared between the two encodings.
-class MOZ_STACK_CLASS JSONParserBase : private JS::AutoGCRooter
+class MOZ_STACK_CLASS JSONParserBase
 {
   public:
     enum ErrorHandling { RaiseError, NoError };
 
   private:
     /* Data members */
     Value v;
 
@@ -103,28 +103,41 @@ class MOZ_STACK_CLASS JSONParserBase : p
     Vector<ElementVector*, 5> freeElements;
     Vector<PropertyVector*, 5> freeProperties;
 
 #ifdef DEBUG
     Token lastToken;
 #endif
 
     JSONParserBase(JSContext* cx, ErrorHandling errorHandling)
-      : JS::AutoGCRooter(cx, JSONPARSER),
-        cx(cx),
+      : cx(cx),
         errorHandling(errorHandling),
         stack(cx),
         freeElements(cx),
         freeProperties(cx)
 #ifdef DEBUG
       , lastToken(Error)
 #endif
     {}
     ~JSONParserBase();
 
+    // Allow move construction for use with Rooted.
+    JSONParserBase(JSONParserBase&& other)
+      : v(other.v),
+        cx(other.cx),
+        errorHandling(other.errorHandling),
+        stack(mozilla::Move(other.stack)),
+        freeElements(mozilla::Move(other.freeElements)),
+        freeProperties(mozilla::Move(other.freeProperties))
+#ifdef DEBUG
+      , lastToken(mozilla::Move(other.lastToken))
+#endif
+    {}
+
+
     Value numberValue() const {
         MOZ_ASSERT(lastToken == Number);
         MOZ_ASSERT(v.isNumber());
         return v;
     }
 
     Value stringValue() const {
         MOZ_ASSERT(lastToken == String);
@@ -164,26 +177,26 @@ class MOZ_STACK_CLASS JSONParserBase : p
 
     enum StringType { PropertyName, LiteralValue };
 
     bool errorReturn();
 
     bool finishObject(MutableHandleValue vp, PropertyVector& properties);
     bool finishArray(MutableHandleValue vp, ElementVector& elements);
 
-  private:
-    friend void AutoGCRooter::trace(JSTracer* trc);
     void trace(JSTracer* trc);
 
+  private:
     JSONParserBase(const JSONParserBase& other) = delete;
     void operator=(const JSONParserBase& other) = delete;
 };
 
 template <typename CharT>
-class MOZ_STACK_CLASS JSONParser : public JSONParserBase
+class MOZ_STACK_CLASS JSONParser : public JSONParserBase,
+                                   public JS::Traceable
 {
   private:
     typedef mozilla::RangedPtr<const CharT> CharPtr;
 
     CharPtr current;
     const CharPtr begin, end;
 
   public:
@@ -195,28 +208,39 @@ class MOZ_STACK_CLASS JSONParser : publi
       : JSONParserBase(cx, errorHandling),
         current(data.start()),
         begin(current),
         end(data.end())
     {
         MOZ_ASSERT(current <= end);
     }
 
+    /* Allow move construction for use with Rooted. */
+    JSONParser(JSONParser&& other)
+      : JSONParserBase(mozilla::Forward<JSONParser>(other)),
+        current(other.current),
+        begin(other.begin),
+        end(other.end)
+    {}
+
     /*
      * Parse the JSON data specified at construction time.  If it parses
      * successfully, store the prescribed value in *vp and return true.  If an
      * internal error (e.g. OOM) occurs during parsing, return false.
      * Otherwise, if invalid input was specifed but no internal error occurred,
      * behavior depends upon the error handling specified at construction: if
      * error handling is RaiseError then throw a SyntaxError and return false,
      * otherwise return true and set *vp to |undefined|.  (JSON syntax can't
      * represent |undefined|, so the JSON data couldn't have specified it.)
      */
     bool parse(MutableHandleValue vp);
 
+    static void trace(JSONParser<CharT>* parser, JSTracer* trc) { parser->trace(trc); }
+    void trace(JSTracer* trc) { JSONParserBase::trace(trc); }
+
   private:
     template<StringType ST> Token readString();
 
     Token readNumber();
 
     Token advance();
     Token advancePropertyName();
     Token advancePropertyColon();
@@ -228,11 +252,18 @@ class MOZ_STACK_CLASS JSONParser : publi
 
     void getTextPosition(uint32_t* column, uint32_t* line);
 
   private:
     JSONParser(const JSONParser& other) = delete;
     void operator=(const JSONParser& other) = delete;
 };
 
+template <typename CharT>
+struct RootedBase<JSONParser<CharT>> {
+    bool parse(MutableHandleValue vp) {
+        return static_cast<Rooted<JSONParser<CharT>>*>(this)->get().parse(vp);
+    }
+};
+
 } /* namespace js */
 
 #endif /* vm_JSONParser_h */