Bug 1202048 - Root JSONParser explicitly; r=sfink
☠☠ backed out by f14ff4e13b88 ☠ ☠
authorTerrence Cole <terrence@mozilla.com>
Thu, 20 Aug 2015 12:26:45 -0700
changeset 294670 13654c18b57f9ba82875fc5741e619e469b757b0
parent 294669 28fe9b60f5d5dbd1b91b5e30effa8a8cb7e9148c
child 294671 148cab7775e5d4229e30bd4c1c55e5b193756aef
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [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 */