Bug 867341 - Remove AutoObjectRooter, replace with RootedObject where needed. r=terrence
authorSteve Fink <sfink@mozilla.com>
Thu, 02 May 2013 13:55:54 -0700
changeset 130683 e2dc6cdc1c02a124c0afe27a6123580b486a2cad
parent 130682 e728bef882df351c8f5e7b2705c98bb4d558a2de
child 130684 898891617618b587075590f003ac28ef554a3a9a
push id27488
push usersfink@mozilla.com
push dateThu, 02 May 2013 23:23:57 +0000
treeherdermozilla-inbound@e2dc6cdc1c02 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence
bugs867341
milestone23.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 867341 - Remove AutoObjectRooter, replace with RootedObject where needed. r=terrence
js/ipc/ObjectWrapperChild.cpp
js/src/ctypes/CTypes.cpp
js/src/gc/RootMarking.cpp
js/src/jsapi.h
js/src/jsiter.cpp
--- a/js/ipc/ObjectWrapperChild.cpp
+++ b/js/ipc/ObjectWrapperChild.cpp
@@ -411,20 +411,19 @@ ObjectWrapperChild::AnswerNewEnumerateIn
 {
     *idp = 0;
 
     JSContext* cx = Manager()->GetContext();
     AutoContextPusher acp(cx);
     AutoCheckOperation aco(this, status);
 
     JSClass* clasp = const_cast<JSClass*>(&sCPOW_NewEnumerateState_JSClass);
-    JSObject* state = JS_NewObjectWithGivenProto(cx, clasp, NULL, NULL);
+    JS::Rooted<JSObject*> state(cx, JS_NewObjectWithGivenProto(cx, clasp, NULL, NULL));
     if (!state)
         return false;
-    AutoObjectRooter tvr(cx, state);
 
     for (JSObject* proto = mObj; proto; ) {
         AutoIdArray ids(cx, JS_Enumerate(cx, proto));
         for (size_t i = 0; i < ids.length(); ++i)
             JS_DefinePropertyById(cx, state, ids[i], JSVAL_VOID,
                                   NULL, NULL, JSPROP_ENUMERATE | JSPROP_SHARED);
 
         if (!JS_GetPrototype(cx, proto, &proto))
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -4329,19 +4329,16 @@ ArrayType::ConstructData(JSContext* cx,
     }
 
     // Construct a new ArrayType of defined length, for the new CData object.
     obj = CreateInternal(cx, baseType, length, true);
     if (!obj)
       return JS_FALSE;
   }
 
-  // Root the CType object, in case we created one above.
-  js::AutoObjectRooter root(cx, obj);
-
   JSObject* result = CData::Create(cx, obj, NullPtr(), NULL, true);
   if (!result)
     return JS_FALSE;
 
   args.rval().setObject(*result);
 
   if (convertObject) {
     if (!ExplicitConvert(cx, args.handleAt(0), obj, CData::GetData(result)))
@@ -4615,17 +4612,16 @@ ExtractStructField(JSContext* cx, jsval 
     JS_ReportError(cx, "struct field descriptors require a valid name and type");
     return NULL;
   }
 
   RootedObject obj(cx, JSVAL_TO_OBJECT(val));
   RootedObject iter(cx, JS_NewPropertyIterator(cx, obj));
   if (!iter)
     return NULL;
-  js::AutoObjectRooter iterroot(cx, iter);
 
   RootedId nameid(cx);
   if (!JS_NextProperty(cx, iter, nameid.address()))
     return NULL;
   if (JSID_IS_VOID(nameid)) {
     JS_ReportError(cx, "struct field descriptors require a valid name and type");
     return NULL;
   }
@@ -4643,26 +4639,25 @@ ExtractStructField(JSContext* cx, jsval 
     JS_ReportError(cx, "struct field descriptors must contain one property");
     return NULL;
   }
 
   RootedValue propVal(cx);
   if (!JS_GetPropertyById(cx, obj, nameid, propVal.address()))
     return NULL;
 
-  if (propVal.isPrimitive() ||
-      !CType::IsCType(propVal.toObjectOrNull())) {
+  if (propVal.isPrimitive() || !CType::IsCType(&propVal.toObject())) {
     JS_ReportError(cx, "struct field descriptors require a valid name and type");
     return NULL;
   }
 
   // Undefined size or zero size struct members are illegal.
   // (Zero-size arrays are legal as struct members in C++, but libffi will
   // choke on a zero-size struct, so we disallow them.)
-  *typeObj = propVal.toObjectOrNull();
+  *typeObj = &propVal.toObject();
   size_t size;
   if (!CType::GetSafeSize(*typeObj, &size) || size == 0) {
     JS_ReportError(cx, "struct field types must have defined and nonzero size");
     return NULL;
   }
 
   return JSID_TO_FLAT_STRING(nameid);
 }
@@ -5615,17 +5610,16 @@ FunctionType::CreateInternal(JSContext* 
   if (!dataProto)
     return NULL;
 
   // Create a new CType object with the common properties and slots.
   JSObject* typeObj = CType::Create(cx, typeProto, dataProto, TYPE_function,
                         NULL, JSVAL_VOID, JSVAL_VOID, NULL);
   if (!typeObj)
     return NULL;
-  js::AutoObjectRooter root(cx, typeObj);
 
   // Stash the FunctionInfo in a reserved slot.
   JS_SetReservedSlot(typeObj, SLOT_FNINFO, PRIVATE_TO_JSVAL(fninfo.forget()));
 
   return typeObj;
 }
 
 // Construct a function pointer to a JS function (see CClosure::Create()).
@@ -5649,20 +5643,19 @@ FunctionType::ConstructData(JSContext* c
     return JS_FALSE;
   }
   if (GetABICode(fninfo->mABI) == ABI_WINAPI) {
     JS_ReportError(cx, "Can't declare a ctypes.winapi_abi callback function, "
                    "use ctypes.stdcall_abi instead");
     return JS_FALSE;
   }
 
-  JSObject* closureObj = CClosure::Create(cx, typeObj, fnObj, thisObj, errVal, data);
+  RootedObject closureObj(cx, CClosure::Create(cx, typeObj, fnObj, thisObj, errVal, data));
   if (!closureObj)
     return JS_FALSE;
-  js::AutoObjectRooter root(cx, closureObj);
 
   // Set the closure object as the referent of the new CData object.
   JS_SetReservedSlot(dataObj, SLOT_REFERENT, OBJECT_TO_JSVAL(closureObj));
 
   // Seal the CData object, to prevent modification of the function pointer.
   // This permanently associates this object with the closure, and avoids
   // having to do things like reset SLOT_REFERENT when someone tries to
   // change the pointer value.
@@ -6152,19 +6145,16 @@ CClosure::ClosureStub(ffi_cif* cif, void
       rvSize = Align(rvSize, sizeof(ffi_arg));
       break;
     default:
       break;
     }
     memset(result, 0, rvSize);
   }
 
-  // Get a death grip on 'closureObj'.
-  js::AutoObjectRooter root(cx, cinfo->closureObj);
-
   // Set up an array for converted arguments.
   Array<jsval, 16> argv;
   if (!argv.appendN(JSVAL_VOID, cif->nargs)) {
     JS_ReportOutOfMemory(cx);
     return;
   }
 
   js::AutoArrayRooter roots(cx, argv.length(), argv.begin());
--- a/js/src/gc/RootMarking.cpp
+++ b/js/src/gc/RootMarking.cpp
@@ -411,22 +411,16 @@ AutoGCRooter::trace(JSTracer *trc)
       }
 
       case DESCRIPTOR : {
         PropertyDescriptor &desc = *static_cast<AutoPropertyDescriptorRooter *>(this);
         desc.trace(trc);
         return;
       }
 
-      case OBJECT:
-        if (static_cast<AutoObjectRooter *>(this)->obj_)
-            MarkObjectRoot(trc, &static_cast<AutoObjectRooter *>(this)->obj_,
-                           "JS::AutoObjectRooter.obj_");
-        return;
-
       case ID:
         MarkIdRoot(trc, &static_cast<AutoIdRooter *>(this)->id_, "JS::AutoIdRooter.id_");
         return;
 
       case VALVECTOR: {
         AutoValueVector::VectorImpl &vector = static_cast<AutoValueVector *>(this)->vector;
         MarkValueRootRange(trc, vector.length(), vector.begin(), "js::AutoValueVector.vector");
         return;
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -112,17 +112,16 @@ class JS_PUBLIC_API(AutoGCRooter) {
     ptrdiff_t tag_;
 
     enum {
         VALARRAY =     -2, /* js::AutoValueArray */
         PARSER =       -3, /* js::frontend::Parser */
         SHAPEVECTOR =  -4, /* js::AutoShapeVector */
         IDARRAY =      -6, /* js::AutoIdArray */
         DESCRIPTORS =  -7, /* js::AutoPropDescArrayRooter */
-        OBJECT =       -8, /* js::AutoObjectRooter */
         ID =           -9, /* js::AutoIdRooter */
         VALVECTOR =   -10, /* js::AutoValueVector */
         DESCRIPTOR =  -11, /* js::AutoPropertyDescriptorRooter */
         STRING =      -12, /* js::AutoStringRooter */
         IDVECTOR =    -13, /* js::AutoIdVector */
         OBJVECTOR =   -14, /* js::AutoObjectVector */
         STRINGVECTOR =-15, /* js::AutoStringVector */
         SCRIPTVECTOR =-16, /* js::AutoScriptVector */
@@ -142,45 +141,16 @@ class JS_PUBLIC_API(AutoGCRooter) {
   private:
     AutoGCRooter ** const stackTop;
 
     /* No copy or assignment semantics. */
     AutoGCRooter(AutoGCRooter &ida) MOZ_DELETE;
     void operator=(AutoGCRooter &ida) MOZ_DELETE;
 };
 
-class AutoObjectRooter : private AutoGCRooter
-{
-  public:
-    AutoObjectRooter(JSContext *cx, JSObject *obj = NULL
-                     MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
-      : AutoGCRooter(cx, OBJECT), obj_(obj)
-    {
-        MOZ_GUARD_OBJECT_NOTIFIER_INIT;
-    }
-
-    void setObject(JSObject *obj) {
-        obj_ = obj;
-    }
-
-    JSObject * object() const {
-        return obj_;
-    }
-
-    JSObject ** addr() {
-        return &obj_;
-    }
-
-    friend void AutoGCRooter::trace(JSTracer *trc);
-
-  private:
-    JSObject *obj_;
-    MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
-};
-
 class AutoStringRooter : private AutoGCRooter {
   public:
     AutoStringRooter(JSContext *cx, JSString *str = NULL
                      MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
       : AutoGCRooter(cx, STRING), str_(str)
     {
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     }
@@ -5050,17 +5020,16 @@ using JS::TwoByteChars;
 using JS::Latin1CharsZ;
 
 using JS::AutoIdVector;
 using JS::AutoValueVector;
 using JS::AutoScriptVector;
 using JS::AutoIdArray;
 
 using JS::AutoGCRooter;
-using JS::AutoObjectRooter;
 using JS::AutoArrayRooter;
 using JS::AutoVectorRooter;
 using JS::AutoHashMapRooter;
 using JS::AutoHashSetRooter;
 
 using JS::CallArgs;
 using JS::IsAcceptableThis;
 using JS::NativeImpl;
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -52,16 +52,21 @@ static const gc::AllocKind ITERATOR_FINA
 
 void
 NativeIterator::mark(JSTracer *trc)
 {
     for (HeapPtr<JSFlatString> *str = begin(); str < end(); str++)
         MarkString(trc, str, "prop");
     if (obj)
         MarkObject(trc, &obj, "obj");
+
+    // The SuppressDeletedPropertyHelper loop can GC, so make sure that if the
+    // GC removes any elements from the list, it won't remove this one.
+    if (iterObj_)
+        MarkObjectUnbarriered(trc, &iterObj_, "iterObj");
 }
 
 struct IdHashPolicy {
     typedef jsid Lookup;
     static HashNumber hash(jsid id) {
         return JSID_BITS(id);
     }
     static bool match(jsid id1, jsid id2) {
@@ -1064,29 +1069,23 @@ template<typename StringPredicate>
 static bool
 SuppressDeletedPropertyHelper(JSContext *cx, HandleObject obj, StringPredicate predicate)
 {
     NativeIterator *enumeratorList = cx->compartment->enumerators;
     NativeIterator *ni = enumeratorList->next();
 
     while (ni != enumeratorList) {
       again:
-        /* This only works for identified surpressed keys, not values. */
+        /* This only works for identified suppressed keys, not values. */
         if (ni->isKeyIter() && ni->obj == obj && ni->props_cursor < ni->props_end) {
             /* Check whether id is still to come. */
             HeapPtr<JSFlatString> *props_cursor = ni->current();
             HeapPtr<JSFlatString> *props_end = ni->end();
             for (HeapPtr<JSFlatString> *idp = props_cursor; idp < props_end; ++idp) {
                 if (predicate(*idp)) {
-                     /*
-                     * Root the iterobj. This loop can GC, so we want to make sure that if
-                     * the GC removes any elements from the list, it won't remove this one.
-                     */
-                    AutoObjectRooter iterRoot(cx, ni->iterObj());
-
                     /*
                      * Check whether another property along the prototype chain
                      * became visible as a result of this deletion.
                      */
                     RootedObject proto(cx);
                     if (!JSObject::getProto(cx, obj, &proto))
                         return false;
                     if (proto) {