Bug 1131877 - Part 2: Handlify the proto arg to NewObject functions; r=sfink
authorTerrence Cole <terrence@mozilla.com>
Fri, 13 Feb 2015 09:36:40 -0800
changeset 229175 6ff7a6801951efddae7ad8266497b39590983dcd
parent 229174 8f282d6a1d1742fb7fb16eeaa71b81f74dd0a952
child 229176 b347698b4d7b031bb11b10990b27fca6627340c5
push id28282
push usercbook@mozilla.com
push dateMon, 16 Feb 2015 15:06:35 +0000
treeherderautoland@09f4968d5f42 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfink
bugs1131877
milestone38.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 1131877 - Part 2: Handlify the proto arg to NewObject functions; r=sfink
js/src/asmjs/AsmJSModule.cpp
js/src/builtin/Intl.cpp
js/src/builtin/MapObject.cpp
js/src/builtin/Object.cpp
js/src/builtin/TestingFunctions.cpp
js/src/builtin/TypedObject.cpp
js/src/frontend/Parser.cpp
js/src/frontend/Parser.h
js/src/jit/CodeGenerator.cpp
js/src/jsapi.cpp
js/src/jsfriendapi.cpp
js/src/jsfun.cpp
js/src/jsfun.h
js/src/jsiter.cpp
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsobjinlines.h
js/src/jsscript.cpp
js/src/vm/Debugger.cpp
js/src/vm/DebuggerMemory.cpp
js/src/vm/GeneratorObject.cpp
js/src/vm/GlobalObject.cpp
js/src/vm/GlobalObject.h
js/src/vm/Interpreter.cpp
js/src/vm/NativeObject-inl.h
js/src/vm/PIC.cpp
js/src/vm/RegExpStatics.cpp
js/src/vm/SelfHosting.cpp
js/src/vm/TypedArrayObject.cpp
--- a/js/src/asmjs/AsmJSModule.cpp
+++ b/js/src/asmjs/AsmJSModule.cpp
@@ -958,17 +958,17 @@ const Class AsmJSModuleObject::class_ = 
     nullptr, /* hasInstance */
     nullptr, /* construct */
     AsmJSModuleObject_trace
 };
 
 AsmJSModuleObject *
 AsmJSModuleObject::create(ExclusiveContext *cx, ScopedJSDeletePtr<AsmJSModule> *module)
 {
-    JSObject *obj = NewObjectWithGivenProto(cx, &AsmJSModuleObject::class_, nullptr, JS::NullPtr());
+    JSObject *obj = NewObjectWithGivenProto(cx, &AsmJSModuleObject::class_, NullPtr(), NullPtr());
     if (!obj)
         return nullptr;
     AsmJSModuleObject *nobj = &obj->as<AsmJSModuleObject>();
 
     nobj->setReservedSlot(MODULE_SLOT, PrivateValue(module->forget()));
     return nobj;
 }
 
--- a/js/src/builtin/Intl.cpp
+++ b/js/src/builtin/Intl.cpp
@@ -415,17 +415,17 @@ IntlInitialize(JSContext *cx, HandleObje
     args[2].set(options);
 
     return Invoke(cx, args);
 }
 
 static bool
 CreateDefaultOptions(JSContext *cx, MutableHandleValue defaultOptions)
 {
-    RootedObject options(cx, NewObjectWithGivenProto<PlainObject>(cx, nullptr, cx->global()));
+    RootedObject options(cx, NewObjectWithGivenProto<PlainObject>(cx, NullPtr(), cx->global()));
     if (!options)
         return false;
     defaultOptions.setObject(*options);
     return true;
 }
 
 // CountAvailable and GetAvailable describe the signatures used for ICU API
 // to determine available locales for various functionality.
@@ -434,17 +434,17 @@ typedef int32_t
 
 typedef const char *
 (* GetAvailable)(int32_t localeIndex);
 
 static bool
 intl_availableLocales(JSContext *cx, CountAvailable countAvailable,
                       GetAvailable getAvailable, MutableHandleValue result)
 {
-    RootedObject locales(cx, NewObjectWithGivenProto<PlainObject>(cx, nullptr, js::NullPtr()));
+    RootedObject locales(cx, NewObjectWithGivenProto<PlainObject>(cx, NullPtr(), NullPtr()));
     if (!locales)
         return false;
 
 #if ENABLE_INTL_API
     uint32_t count = countAvailable();
     RootedValue t(cx, BooleanValue(true));
     for (uint32_t i = 0; i < count; i++) {
         const char *locale = getAvailable(i);
--- a/js/src/builtin/MapObject.cpp
+++ b/js/src/builtin/MapObject.cpp
@@ -896,17 +896,17 @@ MapIteratorObject::kind() const
     int32_t i = getSlot(KindSlot).toInt32();
     MOZ_ASSERT(i == MapObject::Keys || i == MapObject::Values || i == MapObject::Entries);
     return MapObject::IteratorKind(i);
 }
 
 bool
 GlobalObject::initMapIteratorProto(JSContext *cx, Handle<GlobalObject *> global)
 {
-    JSObject *base = GlobalObject::getOrCreateIteratorPrototype(cx, global);
+    Rooted<JSObject*> base(cx, GlobalObject::getOrCreateIteratorPrototype(cx, global));
     if (!base)
         return false;
     Rooted<MapIteratorObject *> proto(cx,
         NewObjectWithGivenProto<MapIteratorObject>(cx, base, global));
     if (!proto)
         return false;
     proto->setSlot(MapIteratorObject::RangeSlot, PrivateValue(nullptr));
     if (!JS_DefineFunctions(cx, proto, MapIteratorObject::methods))
@@ -1632,17 +1632,17 @@ SetIteratorObject::kind() const
     int32_t i = getSlot(KindSlot).toInt32();
     MOZ_ASSERT(i == SetObject::Values || i == SetObject::Entries);
     return SetObject::IteratorKind(i);
 }
 
 bool
 GlobalObject::initSetIteratorProto(JSContext *cx, Handle<GlobalObject*> global)
 {
-    JSObject *base = GlobalObject::getOrCreateIteratorPrototype(cx, global);
+    Rooted<JSObject*> base(cx, GlobalObject::getOrCreateIteratorPrototype(cx, global));
     if (!base)
         return false;
     Rooted<SetIteratorObject *> proto(cx,
         NewObjectWithGivenProto<SetIteratorObject>(cx, base, global));
     if (!proto)
         return false;
     proto->setSlot(SetIteratorObject::RangeSlot, PrivateValue(nullptr));
     if (!JS_DefineFunctions(cx, proto, SetIteratorObject::methods))
--- a/js/src/builtin/Object.cpp
+++ b/js/src/builtin/Object.cpp
@@ -1135,17 +1135,17 @@ CreateObjectPrototype(JSContext *cx, JSP
 
     MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
     MOZ_ASSERT(self->isNative());
 
     /*
      * Create |Object.prototype| first, mirroring CreateBlankProto but for the
      * prototype of the created object.
      */
-    RootedPlainObject objectProto(cx, NewObjectWithGivenProto<PlainObject>(cx, nullptr,
+    RootedPlainObject objectProto(cx, NewObjectWithGivenProto<PlainObject>(cx, NullPtr(),
                                                                            self, SingletonObject));
     if (!objectProto)
         return nullptr;
 
     /*
      * The default 'new' type of Object.prototype is required by type inference
      * to have unknown properties, to simplify handling of e.g. heterogenous
      * objects in JSON and script literals.
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -1035,17 +1035,17 @@ static const js::Class FakePromiseClass 
 static bool
 MakeFakePromise(JSContext *cx, unsigned argc, jsval *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     RootedObject scope(cx, cx->global());
     if (!scope)
         return false;
 
-    RootedObject obj(cx, NewObjectWithGivenProto(cx, &FakePromiseClass, nullptr, scope));
+    RootedObject obj(cx, NewObjectWithGivenProto(cx, &FakePromiseClass, NullPtr(), scope));
     if (!obj)
         return false;
 
     JS::dbg::onNewPromise(cx, obj);
     args.rval().setObject(*obj);
     return true;
 }
 
--- a/js/src/builtin/TypedObject.cpp
+++ b/js/src/builtin/TypedObject.cpp
@@ -483,17 +483,17 @@ SimdTypeDescr::lanes(Type t)
 static TypedProto *
 CreatePrototypeObjectForComplexTypeInstance(JSContext *cx, HandleObject ctorPrototype)
 {
     RootedObject ctorPrototypePrototype(cx, GetPrototype(cx, ctorPrototype));
     if (!ctorPrototypePrototype)
         return nullptr;
 
     return NewObjectWithProto<TypedProto>(cx,
-                                          &*ctorPrototypePrototype,
+                                          ctorPrototypePrototype,
                                           NullPtr(),
                                           TenuredObject);
 }
 
 const Class ArrayTypeDescr::class_ = {
     "ArrayType",
     JSCLASS_HAS_RESERVED_SLOTS(JS_DESCR_SLOTS) | JSCLASS_BACKGROUND_FINALIZE,
     nullptr, /* addProperty */
@@ -773,21 +773,21 @@ StructMetaTypeDescr::create(JSContext *c
     AutoValueVector fieldTypeObjs(cx); // Type descriptor of each field.
     AutoValueVector fieldOffsets(cx);  // Offset of each field field.
     RootedObject userFieldOffsets(cx); // User-exposed {f:offset} object
     RootedObject userFieldTypes(cx);   // User-exposed {f:descr} object.
     CheckedInt32 sizeSoFar(0);         // Size of struct thus far.
     int32_t alignment = 1;             // Alignment of struct.
     bool opaque = false;               // Opacity of struct.
 
-    userFieldOffsets = NewObjectWithProto<PlainObject>(cx, nullptr, NullPtr(), TenuredObject);
+    userFieldOffsets = NewObjectWithProto<PlainObject>(cx, NullPtr(), NullPtr(), TenuredObject);
     if (!userFieldOffsets)
         return nullptr;
 
-    userFieldTypes = NewObjectWithProto<PlainObject>(cx, nullptr, NullPtr(), TenuredObject);
+    userFieldTypes = NewObjectWithProto<PlainObject>(cx, NullPtr(), NullPtr(), TenuredObject);
     if (!userFieldTypes)
         return nullptr;
 
     if (!stringBuffer.append("new StructType({")) {
         js_ReportOutOfMemory(cx);
         return nullptr;
     }
 
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -1218,17 +1218,17 @@ struct BindData
         this->op = op;
         this->isConst = op == JSOP_DEFCONST;
         this->binder = Parser<ParseHandler>::bindVarOrGlobalConst;
     }
 };
 
 template <typename ParseHandler>
 JSFunction *
-Parser<ParseHandler>::newFunction(HandleAtom atom, FunctionSyntaxKind kind, JSObject *proto)
+Parser<ParseHandler>::newFunction(HandleAtom atom, FunctionSyntaxKind kind, HandleObject proto)
 {
     MOZ_ASSERT_IF(kind == Statement, atom != nullptr);
 
     RootedFunction fun(context);
     JSFunction::Flags flags = (kind == Expression)
                               ? JSFunction::INTERPRETED_LAMBDA
                               : (kind == Arrow)
                                 ? JSFunction::INTERPRETED_LAMBDA_ARROW
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -433,17 +433,17 @@ class Parser : private JS::AutoGCRooter,
     ObjectBox *newObjectBox(NativeObject *obj);
     FunctionBox *newFunctionBox(Node fn, JSFunction *fun, ParseContext<ParseHandler> *pc,
                                 Directives directives, GeneratorKind generatorKind);
 
     /*
      * Create a new function object given a name (which is optional if this is
      * a function expression).
      */
-    JSFunction *newFunction(HandleAtom atom, FunctionSyntaxKind kind, JSObject *proto = nullptr);
+    JSFunction *newFunction(HandleAtom atom, FunctionSyntaxKind kind, HandleObject proto);
 
     void trace(JSTracer *trc);
 
     bool hadAbortedSyntaxParse() {
         return abortedSyntaxParse;
     }
     void clearAbortedSyntaxParse() {
         abortedSyntaxParse = false;
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -4659,22 +4659,22 @@ CodeGenerator::visitCreateThis(LCreateTh
         pushArg(ImmGCPtr(&callee->toConstant()->toObject()));
     else
         pushArg(ToRegister(callee));
 
     callVM(CreateThisInfoCodeGen, lir);
 }
 
 static JSObject *
-CreateThisForFunctionWithProtoWrapper(JSContext *cx, js::HandleObject callee, JSObject *proto)
+CreateThisForFunctionWithProtoWrapper(JSContext *cx, js::HandleObject callee, HandleObject proto)
 {
     return CreateThisForFunctionWithProto(cx, callee, proto);
 }
 
-typedef JSObject *(*CreateThisWithProtoFn)(JSContext *cx, HandleObject callee, JSObject *proto);
+typedef JSObject *(*CreateThisWithProtoFn)(JSContext *cx, HandleObject callee, HandleObject proto);
 static const VMFunction CreateThisWithProtoInfo =
 FunctionInfo<CreateThisWithProtoFn>(CreateThisForFunctionWithProtoWrapper);
 
 void
 CodeGenerator::visitCreateThisWithProto(LCreateThisWithProto *lir)
 {
     const LAllocation *callee = lir->getCallee();
     const LAllocation *proto = lir->getPrototype();
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1864,17 +1864,17 @@ JS_NewObject(JSContext *cx, const JSClas
 
     const Class *clasp = Valueify(jsclasp);
     if (!clasp)
         clasp = &PlainObject::class_;    /* default class is Object */
 
     MOZ_ASSERT(clasp != &JSFunction::class_);
     MOZ_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL));
 
-    JSObject *obj = NewObjectWithClassProto(cx, clasp, nullptr, parent);
+    JSObject *obj = NewObjectWithClassProto(cx, clasp, NullPtr(), parent);
     MOZ_ASSERT_IF(obj, obj->getParent());
     return obj;
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_NewObjectWithGivenProto(JSContext *cx, const JSClass *jsclasp, HandleObject proto, HandleObject parent)
 {
     MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
@@ -2487,17 +2487,17 @@ JS_DefineObject(JSContext *cx, HandleObj
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
 
     const Class *clasp = Valueify(jsclasp);
     if (!clasp)
         clasp = &PlainObject::class_;    /* default class is Object */
 
-    RootedObject nobj(cx, NewObjectWithClassProto(cx, clasp, nullptr, obj));
+    RootedObject nobj(cx, NewObjectWithClassProto(cx, clasp, NullPtr(), obj));
     if (!nobj)
         return nullptr;
 
     RootedValue nobjValue(cx, ObjectValue(*nobj));
     if (!DefineProperty(cx, obj, name, nobjValue, NativeOpWrapper(nullptr), NativeOpWrapper(nullptr),
                         attrs, 0)) {
         return nullptr;
     }
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -131,17 +131,17 @@ JS_NewObjectWithUniqueType(JSContext *cx
                            HandleObject parent)
 {
     /*
      * Create our object with a null proto and then splice in the correct proto
      * after we setSingleton, so that we don't pollute the default
      * ObjectGroup attached to our proto with information about our object, since
      * we're not going to be using that ObjectGroup anyway.
      */
-    RootedObject obj(cx, NewObjectWithGivenProto(cx, (const js::Class *)clasp, nullptr,
+    RootedObject obj(cx, NewObjectWithGivenProto(cx, (const js::Class *)clasp, NullPtr(),
                                                  parent, SingletonObject));
     if (!obj)
         return nullptr;
     if (!JS_SplicePrototype(cx, obj, proto))
         return nullptr;
     return obj;
 }
 
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -379,17 +379,17 @@ ResolveInterpretedFunctionPrototype(JSCo
     MOZ_ASSERT(!obj->isBoundFunction());
 
     // Make the prototype object an instance of Object with the same parent as
     // the function object itself, unless the function is an ES6 generator.  In
     // that case, per the 15 July 2013 ES6 draft, section 15.19.3, its parent is
     // the GeneratorObjectPrototype singleton.
     bool isStarGenerator = obj->as<JSFunction>().isStarGenerator();
     Rooted<GlobalObject*> global(cx, &obj->global());
-    JSObject *objProto;
+    RootedObject objProto(cx);
     if (isStarGenerator)
         objProto = GlobalObject::getOrCreateStarGeneratorObjectPrototype(cx, global);
     else
         objProto = obj->global().getOrCreateObjectPrototype(cx);
     if (!objProto)
         return nullptr;
 
     RootedPlainObject proto(cx, NewObjectWithGivenProto<PlainObject>(cx, objProto,
@@ -584,17 +584,17 @@ js::XDRInterpretedFunction(XDRState<mode
         return false;
 
     if ((firstword & HasAtom) && !XDRAtom(xdr, &atom))
         return false;
     if (!xdr->codeUint32(&flagsword))
         return false;
 
     if (mode == XDR_DECODE) {
-        JSObject *proto = nullptr;
+        RootedObject proto(cx);
         if (firstword & IsStarGenerator) {
             proto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, cx->global());
             if (!proto)
                 return false;
         }
 
         gc::AllocKind allocKind = JSFunction::FinalizeKind;
         if (uint16_t(flagsword) & JSFunction::EXTENDED)
@@ -641,17 +641,17 @@ js::XDRInterpretedFunction(XDRState<XDR_
 
 template bool
 js::XDRInterpretedFunction(XDRState<XDR_DECODE> *, HandleObject, HandleScript, MutableHandleFunction);
 
 JSObject *
 js::CloneFunctionAndScript(JSContext *cx, HandleObject enclosingScope, HandleFunction srcFun)
 {
     /* NB: Keep this in sync with XDRInterpretedFunction. */
-    JSObject *cloneProto = nullptr;
+    RootedObject cloneProto(cx);
     if (srcFun->isStarGenerator()) {
         cloneProto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, cx->global());
         if (!cloneProto)
             return nullptr;
     }
 
     gc::AllocKind allocKind = JSFunction::FinalizeKind;
     if (srcFun->isExtended())
@@ -1897,17 +1897,17 @@ FunctionConstructor(JSContext *cx, unsig
 
     /*
      * NB: (new Function) is not lexically closed by its caller, it's just an
      * anonymous function in the top-level scope that its constructor inhabits.
      * Thus 'var x = 42; f = new Function("return x"); print(f())' prints 42,
      * and so would a call to f from another top-level's script or function.
      */
     RootedAtom anonymousAtom(cx, cx->names().anonymous);
-    JSObject *proto = nullptr;
+    RootedObject proto(cx);
     if (isStarGenerator) {
         proto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, global);
         if (!proto)
             return false;
     }
     RootedFunction fun(cx, NewFunctionWithProto(cx, js::NullPtr(), nullptr, 0,
                                                 JSFunction::INTERPRETED_LAMBDA, global,
                                                 anonymousAtom, proto,
@@ -1959,24 +1959,24 @@ JSFunction::isBuiltinFunctionConstructor
 }
 
 JSFunction *
 js::NewFunction(ExclusiveContext *cx, HandleObject funobjArg, Native native, unsigned nargs,
                 JSFunction::Flags flags, HandleObject parent, HandleAtom atom,
                 gc::AllocKind allocKind /* = JSFunction::FinalizeKind */,
                 NewObjectKind newKind /* = GenericObject */)
 {
-    return NewFunctionWithProto(cx, funobjArg, native, nargs, flags, parent, atom, nullptr,
+    return NewFunctionWithProto(cx, funobjArg, native, nargs, flags, parent, atom, NullPtr(),
                                 allocKind, newKind);
 }
 
 JSFunction *
 js::NewFunctionWithProto(ExclusiveContext *cx, HandleObject funobjArg, Native native,
                          unsigned nargs, JSFunction::Flags flags, HandleObject parent,
-                         HandleAtom atom, JSObject *proto,
+                         HandleAtom atom, HandleObject proto,
                          gc::AllocKind allocKind /* = JSFunction::FinalizeKind */,
                          NewObjectKind newKind /* = GenericObject */)
 {
     MOZ_ASSERT(allocKind == JSFunction::FinalizeKind || allocKind == JSFunction::ExtendedFinalizeKind);
     MOZ_ASSERT(sizeof(JSFunction) <= gc::Arena::thingSize(JSFunction::FinalizeKind));
     MOZ_ASSERT(sizeof(FunctionExtended) <= gc::Arena::thingSize(JSFunction::ExtendedFinalizeKind));
 
     RootedObject funobj(cx, funobjArg);
@@ -2036,17 +2036,17 @@ js::CloneFunctionObject(JSContext *cx, H
     MOZ_ASSERT(!fun->isBoundFunction());
 
     bool useSameScript = CloneFunctionObjectUseSameScript(cx->compartment(), fun);
 
     if (!useSameScript && fun->isInterpretedLazy() && !fun->getOrCreateScript(cx))
         return nullptr;
 
     NewObjectKind newKind = useSameScript ? newKindArg : SingletonObject;
-    JSObject *cloneProto = nullptr;
+    RootedObject cloneProto(cx);
     if (fun->isStarGenerator()) {
         cloneProto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, cx->global());
         if (!cloneProto)
             return nullptr;
     }
     RootedObject realParent(cx, SkipScopeParent(parent));
     JSObject *cloneobj = NewObjectWithClassProto(cx, &JSFunction::class_, cloneProto, realParent,
                                                  allocKind, newKind);
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -505,17 +505,17 @@ NewFunction(ExclusiveContext *cx, Handle
             JSFunction::Flags flags, HandleObject parent, HandleAtom atom,
             gc::AllocKind allocKind = JSFunction::FinalizeKind,
             NewObjectKind newKind = GenericObject);
 
 // If proto is nullptr, Function.prototype is used instead.
 extern JSFunction *
 NewFunctionWithProto(ExclusiveContext *cx, HandleObject funobj, JSNative native, unsigned nargs,
                      JSFunction::Flags flags, HandleObject parent, HandleAtom atom,
-                     JSObject *proto, gc::AllocKind allocKind = JSFunction::FinalizeKind,
+                     HandleObject proto, gc::AllocKind allocKind = JSFunction::FinalizeKind,
                      NewObjectKind newKind = GenericObject);
 
 extern JSAtom *
 IdToFunctionName(JSContext *cx, HandleId id);
 
 extern JSFunction *
 DefineFunction(JSContext *cx, HandleObject obj, HandleId id, JSNative native,
                unsigned nargs, unsigned flags,
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -1405,17 +1405,17 @@ GlobalObject::initIteratorClasses(JSCont
         {
             return false;
         }
     }
 
     RootedObject proto(cx);
     if (global->getSlot(ARRAY_ITERATOR_PROTO).isUndefined()) {
         const Class *cls = &ArrayIteratorPrototypeClass;
-        proto = global->createBlankPrototypeInheriting(cx, cls, *iteratorProto);
+        proto = global->createBlankPrototypeInheriting(cx, cls, iteratorProto);
         if (!proto || !DefinePropertiesAndFunctions(cx, proto, nullptr, array_iterator_methods))
             return false;
         global->setReservedSlot(ARRAY_ITERATOR_PROTO, ObjectValue(*proto));
     }
 
     if (global->getSlot(STRING_ITERATOR_PROTO).isUndefined()) {
         const Class *cls = &StringIteratorPrototypeClass;
         proto = global->createBlankPrototype(cx, cls);
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -1384,19 +1384,19 @@ FindProto(ExclusiveContext *cx, const js
         MOZ_ASSERT(JSCLASS_CACHED_PROTO_KEY(clasp) == JSProto_Null);
         return GetBuiltinPrototype(cx, JSProto_Object, proto);
     }
     return true;
 }
 
 
 JSObject *
-js::NewObjectWithClassProtoCommon(ExclusiveContext *cxArg, const Class *clasp, JSObject *protoArg,
-                                  HandleObject maybeParent, gc::AllocKind allocKind,
-                                  NewObjectKind newKind)
+js::NewObjectWithClassProtoCommon(ExclusiveContext *cxArg, const Class *clasp,
+                                  HandleObject protoArg, HandleObject maybeParent,
+                                  gc::AllocKind allocKind, NewObjectKind newKind)
 {
     if (protoArg) {
         return NewObjectWithGivenTaggedProto(cxArg, clasp, TaggedProto(protoArg), maybeParent,
                                              allocKind, newKind);
     }
 
     if (CanBeFinalizedInBackground(allocKind, clasp))
         allocKind = GetBackgroundAllocKind(allocKind);
@@ -1425,29 +1425,26 @@ js::NewObjectWithClassProtoCommon(Exclus
             clasp->isNative() &&
             !cx->compartment()->hasObjectMetadataCallback())
         {
             if (cache.lookupGlobal(clasp, &parent->as<GlobalObject>(), allocKind, &entry)) {
                 JSObject *obj = cache.newObjectFromHit<NoGC>(cx, entry, GetInitialHeap(newKind, clasp));
                 if (obj) {
                     return obj;
                 } else {
-                    RootedObject proto(cxArg, protoArg);
                     obj = cache.newObjectFromHit<CanGC>(cx, entry, GetInitialHeap(newKind, clasp));
                     MOZ_ASSERT(!obj);
-                    protoArg = proto;
                 }
             } else {
                 gcNumber = rt->gc.gcNumber();
             }
         }
     }
 
     RootedObject proto(cxArg, protoArg);
-
     if (!FindProto(cxArg, clasp, &proto))
         return nullptr;
 
     Rooted<TaggedProto> taggedProto(cxArg, TaggedProto(proto));
     ObjectGroup *group = ObjectGroup::defaultNewGroup(cxArg, clasp, taggedProto);
     if (!group)
         return nullptr;
 
@@ -1535,17 +1532,17 @@ js::NewObjectScriptedCall(JSContext *cx,
 
 JSObject*
 js::CreateThis(JSContext *cx, const Class *newclasp, HandleObject callee)
 {
     RootedValue protov(cx);
     if (!GetProperty(cx, callee, callee, cx->names().prototype, &protov))
         return nullptr;
 
-    JSObject *proto = protov.isObjectOrNull() ? protov.toObjectOrNull() : nullptr;
+    RootedObject proto(cx, protov.isObjectOrNull() ? protov.toObjectOrNull() : nullptr);
     RootedObject parent(cx, callee->getParent());
     gc::AllocKind kind = NewObjectGCKind(newclasp);
     return NewObjectWithClassProto(cx, newclasp, proto, parent, kind);
 }
 
 static inline JSObject *
 CreateThisForFunctionWithGroup(JSContext *cx, HandleObjectGroup group, JSObject *parent,
                                NewObjectKind newKind)
@@ -1600,17 +1597,17 @@ CreateThisForFunctionWithGroup(JSContext
         RootedObject parentRoot(cx, parent);
         return NewObjectWithGivenTaggedProto(cx, &PlainObject::class_, group->proto(), parentRoot,
                                              allocKind, newKind);
     }
     return NewObjectWithGroup<PlainObject>(cx, group, parent, allocKind, newKind);
 }
 
 JSObject *
-js::CreateThisForFunctionWithProto(JSContext *cx, HandleObject callee, JSObject *proto,
+js::CreateThisForFunctionWithProto(JSContext *cx, HandleObject callee, HandleObject proto,
                                    NewObjectKind newKind /* = GenericObject */)
 {
     RootedObject res(cx);
 
     if (proto) {
         RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, nullptr, TaggedProto(proto),
                                                                  &callee->as<JSFunction>()));
         if (!group)
@@ -1647,21 +1644,19 @@ js::CreateThisForFunctionWithProto(JSCon
 }
 
 JSObject *
 js::CreateThisForFunction(JSContext *cx, HandleObject callee, NewObjectKind newKind)
 {
     RootedValue protov(cx);
     if (!GetProperty(cx, callee, callee, cx->names().prototype, &protov))
         return nullptr;
-    JSObject *proto;
+    RootedObject proto(cx);
     if (protov.isObject())
         proto = &protov.toObject();
-    else
-        proto = nullptr;
     JSObject *obj = CreateThisForFunctionWithProto(cx, callee, proto, newKind);
 
     if (obj && newKind == SingletonObject) {
         RootedPlainObject nobj(cx, &obj->as<PlainObject>());
 
         /* Reshape the singleton before passing it as the 'this' value. */
         NativeObject::clear(cx, nobj);
 
@@ -1832,20 +1827,20 @@ js::DeepCloneObjectLiteral(JSContext *cx
         clone = NewDenseUnallocatedArray(cx, obj->as<ArrayObject>().length(), nullptr, newKind);
     } else {
         // Object literals are tenured by default as holded by the JSScript.
         MOZ_ASSERT(obj->isTenured());
         AllocKind kind = obj->asTenured().getAllocKind();
         RootedObjectGroup group(cx, obj->getGroup(cx));
         if (!group)
             return nullptr;
+        RootedObject proto(cx, group->proto().toObject());
         RootedObject parent(cx, obj->getParent());
-        clone = NewNativeObjectWithGivenProto(cx, &PlainObject::class_,
-                                              group->proto().toObject(),
-                                              parent, kind, newKind);
+        clone = NewNativeObjectWithGivenProto(cx, &PlainObject::class_, proto, parent, kind,
+                                              newKind);
     }
 
     // Allocate the same number of slots.
     if (!clone || !clone->ensureElements(cx, obj->getDenseCapacity()))
         return nullptr;
 
     // Recursive copy of dense element.
     uint32_t initialized = obj->getDenseInitializedLength();
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -1122,17 +1122,17 @@ GetInitialHeap(NewObjectKind newKind, co
     if (clasp->finalize && !(clasp->flags & JSCLASS_FINALIZE_FROM_NURSERY))
         return gc::TenuredHeap;
     return gc::DefaultHeap;
 }
 
 // Specialized call for constructing |this| with a known function callee,
 // and a known prototype.
 extern JSObject *
-CreateThisForFunctionWithProto(JSContext *cx, js::HandleObject callee, JSObject *proto,
+CreateThisForFunctionWithProto(JSContext *cx, js::HandleObject callee, HandleObject proto,
                                NewObjectKind newKind = GenericObject);
 
 // Specialized call for constructing |this| with a known function callee.
 extern JSObject *
 CreateThisForFunction(JSContext *cx, js::HandleObject callee, NewObjectKind newKind);
 
 // Generic call for constructing |this|.
 extern JSObject *
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -490,40 +490,40 @@ inline T *
 NewObjectWithGivenTaggedProto(ExclusiveContext *cx, TaggedProto proto, HandleObject parent,
                               NewObjectKind newKind = GenericObject)
 {
     JSObject *obj = NewObjectWithGivenTaggedProto(cx, &T::class_, proto, parent, newKind);
     return obj ? &obj->as<T>() : nullptr;
 }
 
 inline JSObject *
-NewObjectWithGivenProto(ExclusiveContext *cx, const Class *clasp, JSObject *proto,
+NewObjectWithGivenProto(ExclusiveContext *cx, const Class *clasp, HandleObject proto,
                         HandleObject parent, gc::AllocKind allocKind, NewObjectKind newKind)
 {
     return NewObjectWithGivenTaggedProto(cx, clasp, TaggedProto(proto), parent, allocKind, newKind);
 }
 
 inline JSObject *
-NewObjectWithGivenProto(ExclusiveContext *cx, const Class *clasp, JSObject *proto,
+NewObjectWithGivenProto(ExclusiveContext *cx, const Class *clasp, HandleObject proto,
                         HandleObject parent, NewObjectKind newKind = GenericObject)
 {
     return NewObjectWithGivenTaggedProto(cx, clasp, TaggedProto(proto), parent, newKind);
 }
 
 template <typename T>
 inline T *
-NewObjectWithGivenProto(ExclusiveContext *cx, JSObject *proto, HandleObject parent,
+NewObjectWithGivenProto(ExclusiveContext *cx, HandleObject proto, HandleObject parent,
                         NewObjectKind newKind = GenericObject)
 {
     return NewObjectWithGivenTaggedProto<T>(cx, TaggedProto(proto), parent, newKind);
 }
 
 template <typename T>
 inline T *
-NewObjectWithGivenProto(ExclusiveContext *cx, JSObject *proto, HandleObject parent,
+NewObjectWithGivenProto(ExclusiveContext *cx, HandleObject proto, HandleObject parent,
                         gc::AllocKind allocKind, NewObjectKind newKind = GenericObject)
 {
     JSObject *obj = NewObjectWithGivenTaggedProto(cx, &T::class_, TaggedProto(proto), parent,
                                                   allocKind, newKind);
     return obj ? &obj->as<T>() : nullptr;
 }
 
 /*
@@ -539,63 +539,63 @@ NewObjectWithGivenProto(ExclusiveContext
  * else
  *   Object.prototype.
  *
  * The class prototype will be fetched from the parent's global. If global is
  * null, the context's active global will be used, and the resulting object's
  * parent will be that global.
  */
 JSObject *
-NewObjectWithClassProtoCommon(ExclusiveContext *cx, const Class *clasp, JSObject *proto,
+NewObjectWithClassProtoCommon(ExclusiveContext *cx, const Class *clasp, HandleObject proto,
                               HandleObject parent, gc::AllocKind allocKind,
                               NewObjectKind newKind);
 
 inline JSObject *
-NewObjectWithClassProto(ExclusiveContext *cx, const Class *clasp, JSObject *proto,
+NewObjectWithClassProto(ExclusiveContext *cx, const Class *clasp, HandleObject proto,
                         HandleObject parent, gc::AllocKind allocKind,
                         NewObjectKind newKind = GenericObject)
 {
     return NewObjectWithClassProtoCommon(cx, clasp, proto, parent, allocKind, newKind);
 }
 
 inline JSObject *
-NewObjectWithClassProto(ExclusiveContext *cx, const Class *clasp, JSObject *proto,
+NewObjectWithClassProto(ExclusiveContext *cx, const Class *clasp, HandleObject proto,
                         HandleObject parent, NewObjectKind newKind = GenericObject)
 {
     gc::AllocKind allocKind = gc::GetGCObjectKind(clasp);
     return NewObjectWithClassProto(cx, clasp, proto, parent, allocKind, newKind);
 }
 
 template<typename T>
 inline T *
-NewObjectWithProto(ExclusiveContext *cx, JSObject *proto, HandleObject parent,
+NewObjectWithProto(ExclusiveContext *cx, HandleObject proto, HandleObject parent,
                    gc::AllocKind allocKind, NewObjectKind newKind = GenericObject)
 {
     JSObject *obj = NewObjectWithClassProto(cx, &T::class_, proto, parent, allocKind, newKind);
     return obj ? &obj->as<T>() : nullptr;
 }
 
 template<typename T>
 inline T *
-NewObjectWithProto(ExclusiveContext *cx, JSObject *proto, HandleObject parent,
+NewObjectWithProto(ExclusiveContext *cx, HandleObject proto, HandleObject parent,
                    NewObjectKind newKind = GenericObject)
 {
     JSObject *obj = NewObjectWithClassProto(cx, &T::class_, proto, parent, newKind);
     return obj ? &obj->as<T>() : nullptr;
 }
 
 /*
  * Create a native instance of the given class with parent and proto set
  * according to the context's active global.
  */
 inline JSObject *
 NewBuiltinClassInstance(ExclusiveContext *cx, const Class *clasp, gc::AllocKind allocKind,
                         NewObjectKind newKind = GenericObject)
 {
-    return NewObjectWithClassProto(cx, clasp, nullptr, NullPtr(), allocKind, newKind);
+    return NewObjectWithClassProto(cx, clasp, NullPtr(), NullPtr(), allocKind, newKind);
 }
 
 inline JSObject *
 NewBuiltinClassInstance(ExclusiveContext *cx, const Class *clasp, NewObjectKind newKind = GenericObject)
 {
     gc::AllocKind allocKind = gc::GetGCObjectKind(clasp);
     return NewBuiltinClassInstance(cx, clasp, allocKind, newKind);
 }
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -1351,17 +1351,17 @@ const Class ScriptSourceObject::class_ =
     nullptr, /* hasInstance */
     nullptr, /* construct */
     trace
 };
 
 ScriptSourceObject *
 ScriptSourceObject::create(ExclusiveContext *cx, ScriptSource *source)
 {
-    RootedObject object(cx, NewObjectWithGivenProto(cx, &class_, nullptr, cx->global()));
+    RootedObject object(cx, NewObjectWithGivenProto(cx, &class_, NullPtr(), cx->global()));
     if (!object)
         return nullptr;
     RootedScriptSource sourceObject(cx, &object->as<ScriptSourceObject>());
 
     source->incref();    // The matching decref is in ScriptSourceObject::finalize.
     sourceObject->initReservedSlot(SOURCE_SLOT, PrivateValue(source));
 
     // The remaining slots should eventually be populated by a call to
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -444,17 +444,17 @@ bool
 Debugger::getScriptFrameWithIter(JSContext *cx, AbstractFramePtr frame,
                                  const ScriptFrameIter *maybeIter, MutableHandleValue vp)
 {
     MOZ_ASSERT_IF(maybeIter, maybeIter->abstractFramePtr() == frame);
 
     FrameMap::AddPtr p = frames.lookupForAdd(frame);
     if (!p) {
         /* Create and populate the Debugger.Frame object. */
-        JSObject *proto = &object->getReservedSlot(JSSLOT_DEBUG_FRAME_PROTO).toObject();
+        RootedObject proto(cx, &object->getReservedSlot(JSSLOT_DEBUG_FRAME_PROTO).toObject());
         RootedNativeObject frameobj(cx, NewNativeObjectWithGivenProto(cx, &DebuggerFrame_class,
                                                                       proto, NullPtr()));
         if (!frameobj)
             return false;
 
         // Eagerly copy ScriptFrameIter data if we've already walked the
         // stack.
         if (maybeIter) {
@@ -764,17 +764,17 @@ Debugger::wrapEnvironment(JSContext *cx,
     MOZ_ASSERT(!env->is<ScopeObject>());
 
     NativeObject *envobj;
     DependentAddPtr<ObjectWeakMap> p(cx, environments, env);
     if (p) {
         envobj = &p->value()->as<NativeObject>();
     } else {
         /* Create a new Debugger.Environment for env. */
-        JSObject *proto = &object->getReservedSlot(JSSLOT_DEBUG_ENV_PROTO).toObject();
+        RootedObject proto(cx, &object->getReservedSlot(JSSLOT_DEBUG_ENV_PROTO).toObject());
         envobj = NewNativeObjectWithGivenProto(cx, &DebuggerEnv_class, proto, NullPtr(),
                                                TenuredObject);
         if (!envobj)
             return false;
         envobj->setPrivateGCThing(env);
         envobj->setReservedSlot(JSSLOT_DEBUGENV_OWNER, ObjectValue(*object));
         if (!p.add(cx, environments, env, envobj)) {
             js_ReportOutOfMemory(cx);
@@ -806,17 +806,17 @@ Debugger::wrapDebuggeeValue(JSContext *c
                 return false;
         }
 
         DependentAddPtr<ObjectWeakMap> p(cx, objects, obj);
         if (p) {
             vp.setObject(*p->value());
         } else {
             /* Create a new Debugger.Object for obj. */
-            JSObject *proto = &object->getReservedSlot(JSSLOT_DEBUG_OBJECT_PROTO).toObject();
+            RootedObject proto(cx, &object->getReservedSlot(JSSLOT_DEBUG_OBJECT_PROTO).toObject());
             NativeObject *dobj =
                 NewNativeObjectWithGivenProto(cx, &DebuggerObject_class, proto, NullPtr(),
                                               TenuredObject);
             if (!dobj)
                 return false;
             dobj->setPrivateGCThing(obj);
             dobj->setReservedSlot(JSSLOT_DEBUGOBJECT_OWNER, ObjectValue(*object));
 
@@ -3886,17 +3886,17 @@ Debugger::drainTraceLogger(JSContext *cx
     JSAtom *dataAtom = Atomize(cx, "data", strlen("data"));
     if (!dataAtom)
         return false;
     RootedId dataId(cx, AtomToId(dataAtom));
 
     /* Add all events to the array. */
     uint32_t index = 0;
     for (EventEntry *eventItem = events; eventItem < events + num; eventItem++, index++) {
-        RootedObject item(cx, NewObjectWithGivenProto(cx, &PlainObject::class_, nullptr,
+        RootedObject item(cx, NewObjectWithGivenProto(cx, &PlainObject::class_, NullPtr(),
                                                       GlobalObject::upcast(cx->global())));
         if (!item)
             return false;
 
         const char *eventText = logger->eventText(eventItem->textId);
         if (!DefineProperty(cx, item, dataId, eventText, strlen(eventText)))
             return false;
 
@@ -3985,17 +3985,18 @@ Debugger::drainTraceLoggerScriptCalls(JS
     JSAtom *logTypeAtom = Atomize(cx, "logType", strlen("logType"));
     if (!logTypeAtom)
         return false;
     RootedId logTypeId(cx, AtomToId(logTypeAtom));
 
     /* Add all events to the array. */
     uint32_t index = 0;
     for (EventEntry *eventItem = events; eventItem < events + num; eventItem++) {
-        RootedObject item(cx, NewObjectWithGivenProto(cx, &PlainObject::class_, nullptr, cx->global()));
+        RootedObject item(cx, NewObjectWithGivenProto(cx, &PlainObject::class_, NullPtr(),
+                                                      cx->global()));
         if (!item)
             return false;
 
         uint32_t textId = eventItem->textId;
         if (textId != TraceLogger_Stop && !logger->textIdIsScriptEvent(textId))
             continue;
 
         const char *type = (textId == TraceLogger_Stop) ? "Stop" : "Script";
@@ -4108,17 +4109,17 @@ const Class DebuggerScript_class = {
     DebuggerScript_trace
 };
 
 JSObject *
 Debugger::newDebuggerScript(JSContext *cx, HandleScript script)
 {
     assertSameCompartment(cx, object.get());
 
-    JSObject *proto = &object->getReservedSlot(JSSLOT_DEBUG_SCRIPT_PROTO).toObject();
+    RootedObject proto(cx, &object->getReservedSlot(JSSLOT_DEBUG_SCRIPT_PROTO).toObject());
     MOZ_ASSERT(proto);
     NativeObject *scriptobj = NewNativeObjectWithGivenProto(cx, &DebuggerScript_class,
                                                             proto, NullPtr(), TenuredObject);
     if (!scriptobj)
         return nullptr;
     scriptobj->setReservedSlot(JSSLOT_DEBUGSCRIPT_OWNER, ObjectValue(*object));
     scriptobj->setPrivateGCThing(script);
 
@@ -5130,17 +5131,17 @@ const Class DebuggerSource_class = {
     DebuggerSource_trace
 };
 
 JSObject *
 Debugger::newDebuggerSource(JSContext *cx, HandleScriptSource source)
 {
     assertSameCompartment(cx, object.get());
 
-    JSObject *proto = &object->getReservedSlot(JSSLOT_DEBUG_SOURCE_PROTO).toObject();
+    RootedObject proto(cx, &object->getReservedSlot(JSSLOT_DEBUG_SOURCE_PROTO).toObject());
     MOZ_ASSERT(proto);
     NativeObject *sourceobj = NewNativeObjectWithGivenProto(cx, &DebuggerSource_class,
                                                             proto, NullPtr(), TenuredObject);
     if (!sourceobj)
         return nullptr;
     sourceobj->setReservedSlot(JSSLOT_DEBUGSOURCE_OWNER, ObjectValue(*object));
     sourceobj->setPrivateGCThing(source);
 
@@ -5770,17 +5771,17 @@ DebuggerFrame_getArguments(JSContext *cx
         args.rval().set(argumentsv);
         return true;
     }
 
     RootedNativeObject argsobj(cx);
     if (frame.hasArgs()) {
         /* Create an arguments object. */
         Rooted<GlobalObject*> global(cx, &args.callee().global());
-        JSObject *proto = GlobalObject::getOrCreateArrayPrototype(cx, global);
+        RootedObject proto(cx, GlobalObject::getOrCreateArrayPrototype(cx, global));
         if (!proto)
             return false;
         argsobj = NewNativeObjectWithGivenProto(cx, &DebuggerArguments_class, proto,
                                                 GlobalObject::upcast(global));
         if (!argsobj)
             return false;
         SetReservedSlot(argsobj, JSSLOT_DEBUGARGUMENTS_FRAME, ObjectValue(*thisobj));
 
@@ -6107,17 +6108,17 @@ DebuggerGenericEval(JSContext *cx, const
             return false;
         thisv = ObjectValue(*thisObj);
         env = scope;
     }
 
     /* If evalWithBindings, create the inner environment. */
     if (evalWithBindings) {
         /* TODO - This should probably be a Call object, like ES5 strict eval. */
-        RootedPlainObject nenv(cx, NewObjectWithGivenProto<PlainObject>(cx, nullptr, env));
+        RootedPlainObject nenv(cx, NewObjectWithGivenProto<PlainObject>(cx, NullPtr(), env));
         if (!nenv)
             return false;
         RootedId id(cx);
         for (size_t i = 0; i < keys.length(); i++) {
             id = keys[i];
             MutableHandleValue val = values[i];
             if (!cx->compartment()->wrap(cx, val) ||
                 !NativeDefineProperty(cx, nenv, id, val, nullptr, nullptr, 0))
--- a/js/src/vm/DebuggerMemory.cpp
+++ b/js/src/vm/DebuggerMemory.cpp
@@ -34,20 +34,19 @@ using JS::ubi::Node;
 
 using mozilla::Maybe;
 using mozilla::Move;
 using mozilla::Nothing;
 
 /* static */ DebuggerMemory *
 DebuggerMemory::create(JSContext *cx, Debugger *dbg)
 {
-
-    Value memoryProto = dbg->object->getReservedSlot(Debugger::JSSLOT_DEBUG_MEMORY_PROTO);
-    RootedNativeObject memory(cx, NewNativeObjectWithGivenProto(cx, &class_,
-                                                                &memoryProto.toObject(),
+    Value memoryProtoValue = dbg->object->getReservedSlot(Debugger::JSSLOT_DEBUG_MEMORY_PROTO);
+    RootedObject memoryProto(cx, &memoryProtoValue.toObject());
+    RootedNativeObject memory(cx, NewNativeObjectWithGivenProto(cx, &class_, memoryProto,
                                                                 NullPtr()));
     if (!memory)
         return nullptr;
 
     dbg->object->setReservedSlot(Debugger::JSSLOT_DEBUG_MEMORY_INSTANCE, ObjectValue(*memory));
     memory->setReservedSlot(JSSLOT_DEBUGGER, ObjectValue(*dbg->object));
 
     return &memory->as<DebuggerMemory>();
--- a/js/src/vm/GeneratorObject.cpp
+++ b/js/src/vm/GeneratorObject.cpp
@@ -24,26 +24,26 @@ GeneratorObject::create(JSContext *cx, A
     RootedNativeObject obj(cx);
     if (frame.script()->isStarGenerator()) {
         RootedValue pval(cx);
         RootedObject fun(cx, frame.fun());
         // FIXME: This would be faster if we could avoid doing a lookup to get
         // the prototype for the instance.  Bug 906600.
         if (!GetProperty(cx, fun, fun, cx->names().prototype, &pval))
             return nullptr;
-        JSObject *proto = pval.isObject() ? &pval.toObject() : nullptr;
+        RootedObject proto(cx, pval.isObject() ? &pval.toObject() : nullptr);
         if (!proto) {
             proto = GlobalObject::getOrCreateStarGeneratorObjectPrototype(cx, global);
             if (!proto)
                 return nullptr;
         }
         obj = NewNativeObjectWithGivenProto(cx, &StarGeneratorObject::class_, proto, global);
     } else {
         MOZ_ASSERT(frame.script()->isLegacyGenerator());
-        JSObject *proto = GlobalObject::getOrCreateLegacyGeneratorObjectPrototype(cx, global);
+        RootedObject proto(cx, GlobalObject::getOrCreateLegacyGeneratorObjectPrototype(cx, global));
         if (!proto)
             return nullptr;
         obj = NewNativeObjectWithGivenProto(cx, &LegacyGeneratorObject::class_, proto, global);
     }
     if (!obj)
         return nullptr;
 
     GeneratorObject *genObj = &obj->as<GeneratorObject>();
@@ -263,26 +263,26 @@ static const JSFunctionSpec legacy_gener
     JS_FS_END
 };
 
 #undef JSPROP_ROPERM
 
 static JSObject*
 NewSingletonObjectWithObjectPrototype(JSContext *cx, Handle<GlobalObject *> global)
 {
-    JSObject *proto = global->getOrCreateObjectPrototype(cx);
+    RootedObject proto(cx, global->getOrCreateObjectPrototype(cx));
     if (!proto)
         return nullptr;
     return NewObjectWithGivenProto<PlainObject>(cx, proto, global, SingletonObject);
 }
 
 static JSObject*
 NewSingletonObjectWithFunctionPrototype(JSContext *cx, Handle<GlobalObject *> global)
 {
-    JSObject *proto = global->getOrCreateFunctionPrototype(cx);
+    RootedObject proto(cx, global->getOrCreateFunctionPrototype(cx));
     if (!proto)
         return nullptr;
     return NewObjectWithGivenProto<PlainObject>(cx, proto, global, SingletonObject);
 }
 
 /* static */ bool
 GlobalObject::initGeneratorClasses(JSContext *cx, Handle<GlobalObject *> global)
 {
@@ -304,20 +304,21 @@ GlobalObject::initGeneratorClasses(JSCon
         if (!genFunctionProto)
             return false;
         if (!LinkConstructorAndPrototype(cx, genFunctionProto, genObjectProto))
             return false;
 
         RootedValue function(cx, global->getConstructor(JSProto_Function));
         if (!function.toObjectOrNull())
             return false;
+        RootedObject proto(cx, &function.toObject());
         RootedAtom name(cx, cx->names().GeneratorFunction);
         RootedObject genFunction(cx, NewFunctionWithProto(cx, NullPtr(), Generator, 1,
                                                           JSFunction::NATIVE_CTOR, global, name,
-                                                          &function.toObject()));
+                                                          proto));
         if (!genFunction)
             return false;
         if (!LinkConstructorAndPrototype(cx, genFunction, genFunctionProto))
             return false;
 
         global->setSlot(STAR_GENERATOR_OBJECT_PROTO, ObjectValue(*genObjectProto));
         global->setConstructor(JSProto_GeneratorFunction, ObjectValue(*genFunction));
         global->setPrototype(JSProto_GeneratorFunction, ObjectValue(*genFunctionProto));
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -229,17 +229,17 @@ GlobalObject::initBuiltinConstructor(JSC
 }
 
 GlobalObject *
 GlobalObject::createInternal(JSContext *cx, const Class *clasp)
 {
     MOZ_ASSERT(clasp->flags & JSCLASS_IS_GLOBAL);
     MOZ_ASSERT(clasp->trace == JS_GlobalObjectTraceHook);
 
-    JSObject *obj = NewObjectWithGivenProto(cx, clasp, nullptr, NullPtr(), SingletonObject);
+    JSObject *obj = NewObjectWithGivenProto(cx, clasp, NullPtr(), NullPtr(), SingletonObject);
     if (!obj)
         return nullptr;
 
     Rooted<GlobalObject *> global(cx, &obj->as<GlobalObject>());
 
     // Initialize the private slot to null if present, as GC can call class
     // hooks before the caller gets to set this to a non-garbage value.
     if (clasp->flags & JSCLASS_HAS_PRIVATE)
@@ -430,41 +430,41 @@ GlobalObject::createConstructor(JSContex
                                 gc::AllocKind kind)
 {
     RootedAtom name(cx, nameArg);
     RootedObject self(cx, this);
     return NewFunction(cx, NullPtr(), ctor, length, JSFunction::NATIVE_CTOR, self, name, kind);
 }
 
 static NativeObject *
-CreateBlankProto(JSContext *cx, const Class *clasp, JSObject &proto, HandleObject global)
+CreateBlankProto(JSContext *cx, const Class *clasp, HandleObject proto, HandleObject global)
 {
     MOZ_ASSERT(clasp != &JSFunction::class_);
 
-    RootedNativeObject blankProto(cx, NewNativeObjectWithGivenProto(cx, clasp, &proto, global,
+    RootedNativeObject blankProto(cx, NewNativeObjectWithGivenProto(cx, clasp, proto, global,
                                                                     SingletonObject));
     if (!blankProto || !blankProto->setDelegate(cx))
         return nullptr;
 
     return blankProto;
 }
 
 NativeObject *
 GlobalObject::createBlankPrototype(JSContext *cx, const Class *clasp)
 {
     Rooted<GlobalObject*> self(cx, this);
-    JSObject *objectProto = getOrCreateObjectPrototype(cx);
+    RootedObject objectProto(cx, getOrCreateObjectPrototype(cx));
     if (!objectProto)
         return nullptr;
 
-    return CreateBlankProto(cx, clasp, *objectProto, self);
+    return CreateBlankProto(cx, clasp, objectProto, self);
 }
 
 NativeObject *
-GlobalObject::createBlankPrototypeInheriting(JSContext *cx, const Class *clasp, JSObject &proto)
+GlobalObject::createBlankPrototypeInheriting(JSContext *cx, const Class *clasp, HandleObject proto)
 {
     Rooted<GlobalObject*> self(cx, this);
     return CreateBlankProto(cx, clasp, proto, self);
 }
 
 bool
 js::LinkConstructorAndPrototype(JSContext *cx, JSObject *ctor_, JSObject *proto_)
 {
@@ -516,17 +516,18 @@ GlobalObject::getDebuggers()
 /* static */ GlobalObject::DebuggerVector *
 GlobalObject::getOrCreateDebuggers(JSContext *cx, Handle<GlobalObject*> global)
 {
     assertSameCompartment(cx, global);
     DebuggerVector *debuggers = global->getDebuggers();
     if (debuggers)
         return debuggers;
 
-    NativeObject *obj = NewNativeObjectWithGivenProto(cx, &GlobalDebuggees_class, nullptr, global);
+    NativeObject *obj = NewNativeObjectWithGivenProto(cx, &GlobalDebuggees_class, NullPtr(),
+                                                      global);
     if (!obj)
         return nullptr;
     debuggers = cx->new_<DebuggerVector>();
     if (!debuggers)
         return nullptr;
     obj->setPrivate(debuggers);
     global->setReservedSlot(DEBUGGERS, ObjectValue(*obj));
     return debuggers;
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -305,17 +305,18 @@ class GlobalObject : public NativeObject
      * touch.
      */
     NativeObject *createBlankPrototype(JSContext *cx, const js::Class *clasp);
 
     /*
      * Identical to createBlankPrototype, but uses proto as the [[Prototype]]
      * of the returned blank prototype.
      */
-    NativeObject *createBlankPrototypeInheriting(JSContext *cx, const js::Class *clasp, JSObject &proto);
+    NativeObject *createBlankPrototypeInheriting(JSContext *cx, const js::Class *clasp,
+                                                 HandleObject proto);
 
     template <typename T>
     T *createBlankPrototype(JSContext *cx) {
         NativeObject *res = createBlankPrototype(cx, &T::class_);
         return res ? &res->template as<T>() : nullptr;
     }
 
     NativeObject *getOrCreateObjectPrototype(JSContext *cx) {
@@ -869,18 +870,18 @@ GenericCreateConstructor(JSContext *cx, 
 inline JSObject *
 GenericCreatePrototype(JSContext *cx, JSProtoKey key)
 {
     MOZ_ASSERT(key != JSProto_Object);
     const Class *clasp = ProtoKeyToClass(key);
     JSProtoKey parentKey = ParentKeyForStandardClass(key);
     if (!GlobalObject::ensureConstructor(cx, cx->global(), parentKey))
         return nullptr;
-    JSObject *parentProto = &cx->global()->getPrototype(parentKey).toObject();
-    return cx->global()->createBlankPrototypeInheriting(cx, clasp, *parentProto);
+    RootedObject parentProto(cx, &cx->global()->getPrototype(parentKey).toObject());
+    return cx->global()->createBlankPrototypeInheriting(cx, clasp, parentProto);
 }
 
 inline JSProtoKey
 StandardProtoKeyOrNull(const JSObject *obj)
 {
     JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(obj->getClass());
     if (key == JSProto_Error)
         return GetExceptionProtoKey(obj->as<ErrorObject>().type());
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -161,17 +161,17 @@ js::OnUnknownMethod(JSContext *cx, Handl
 {
     RootedValue idval(cx, idval_);
 
     RootedValue value(cx);
     if (!GetProperty(cx, obj, obj, cx->names().noSuchMethod, &value))
         return false;
 
     if (value.isObject()) {
-        NativeObject *obj = NewNativeObjectWithClassProto(cx, &js_NoSuchMethodClass, nullptr,
+        NativeObject *obj = NewNativeObjectWithClassProto(cx, &js_NoSuchMethodClass, NullPtr(),
                                                           NullPtr());
         if (!obj)
             return false;
 
         obj->setSlot(JSSLOT_FOUND_FUNCTION, value);
         obj->setSlot(JSSLOT_SAVED_ID, idval);
         vp.setObject(*obj);
     }
--- a/js/src/vm/NativeObject-inl.h
+++ b/js/src/vm/NativeObject-inl.h
@@ -358,40 +358,40 @@ NewNativeObjectWithGivenTaggedProto(Excl
                                     TaggedProto proto, HandleObject parent,
                                     NewObjectKind newKind = GenericObject)
 {
     return MaybeNativeObject(NewObjectWithGivenTaggedProto(cx, clasp, proto, parent, newKind));
 }
 
 inline NativeObject *
 NewNativeObjectWithGivenProto(ExclusiveContext *cx, const Class *clasp,
-                              JSObject *proto, HandleObject parent,
+                              HandleObject proto, HandleObject parent,
                               gc::AllocKind allocKind, NewObjectKind newKind)
 {
     return MaybeNativeObject(NewObjectWithGivenProto(cx, clasp, proto, parent, allocKind, newKind));
 }
 
 inline NativeObject *
 NewNativeObjectWithGivenProto(ExclusiveContext *cx, const Class *clasp,
-                              JSObject *proto, HandleObject parent,
+                              HandleObject proto, HandleObject parent,
                               NewObjectKind newKind = GenericObject)
 {
     return MaybeNativeObject(NewObjectWithGivenProto(cx, clasp, proto, parent, newKind));
 }
 
 inline NativeObject *
-NewNativeObjectWithClassProto(ExclusiveContext *cx, const Class *clasp, JSObject *proto,
+NewNativeObjectWithClassProto(ExclusiveContext *cx, const Class *clasp, HandleObject proto,
                               HandleObject parent, gc::AllocKind allocKind,
                               NewObjectKind newKind = GenericObject)
 {
     return MaybeNativeObject(NewObjectWithClassProto(cx, clasp, proto, parent, allocKind, newKind));
 }
 
 inline NativeObject *
-NewNativeObjectWithClassProto(ExclusiveContext *cx, const Class *clasp, JSObject *proto,
+NewNativeObjectWithClassProto(ExclusiveContext *cx, const Class *clasp, HandleObject proto,
                               HandleObject parent, NewObjectKind newKind = GenericObject)
 {
     return MaybeNativeObject(NewObjectWithClassProto(cx, clasp, proto, parent, newKind));
 }
 
 /*
  * Call obj's resolve hook.
  *
--- a/js/src/vm/PIC.cpp
+++ b/js/src/vm/PIC.cpp
@@ -303,17 +303,17 @@ const Class ForOfPIC::jsclass = {
     nullptr,              /* construct   */
     ForOfPIC_traceObject
 };
 
 /* static */ NativeObject *
 js::ForOfPIC::createForOfPICObject(JSContext *cx, Handle<GlobalObject*> global)
 {
     assertSameCompartment(cx, global);
-    NativeObject *obj = NewNativeObjectWithGivenProto(cx, &ForOfPIC::jsclass, nullptr, global);
+    NativeObject *obj = NewNativeObjectWithGivenProto(cx, &ForOfPIC::jsclass, NullPtr(), global);
     if (!obj)
         return nullptr;
     ForOfPIC::Chain *chain = cx->new_<ForOfPIC::Chain>();
     if (!chain)
         return nullptr;
     obj->setPrivate(chain);
     return obj;
 }
--- a/js/src/vm/RegExpStatics.cpp
+++ b/js/src/vm/RegExpStatics.cpp
@@ -50,17 +50,17 @@ const Class RegExpStaticsObject::class_ 
     nullptr, /* hasInstance */
     nullptr, /* construct */
     resc_trace
 };
 
 RegExpStaticsObject *
 RegExpStatics::create(ExclusiveContext *cx, Handle<GlobalObject*> parent)
 {
-    RegExpStaticsObject *obj = NewObjectWithGivenProto<RegExpStaticsObject>(cx, nullptr,
+    RegExpStaticsObject *obj = NewObjectWithGivenProto<RegExpStaticsObject>(cx, NullPtr(),
         GlobalObject::upcast(parent));
     if (!obj)
         return nullptr;
     RegExpStatics *res = cx->new_<RegExpStatics>();
     if (!res)
         return nullptr;
     obj->setPrivate(static_cast<void *>(res));
     return obj;
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -1252,17 +1252,17 @@ CloneObject(JSContext *cx, HandleNativeO
         RootedString str(cx, CloneString(cx, &selfHostedString->asFlat()));
         if (!str)
             return nullptr;
         clone = StringObject::create(cx, str);
     } else if (selfHostedObject->is<ArrayObject>()) {
         clone = NewDenseEmptyArray(cx, nullptr, TenuredObject);
     } else {
         MOZ_ASSERT(selfHostedObject->isNative());
-        clone = NewObjectWithGivenProto(cx, selfHostedObject->getClass(), nullptr, cx->global(),
+        clone = NewObjectWithGivenProto(cx, selfHostedObject->getClass(), NullPtr(), cx->global(),
                                         selfHostedObject->asTenured().getAllocKind(),
                                         SingletonObject);
     }
     if (!clone)
         return nullptr;
     if (!CloneProperties(cx, selfHostedObject, clone))
         return nullptr;
     return clone;
--- a/js/src/vm/TypedArrayObject.cpp
+++ b/js/src/vm/TypedArrayObject.cpp
@@ -212,17 +212,17 @@ class TypedArrayObjectTemplate : public 
     createPrototype(JSContext *cx, JSProtoKey key)
     {
         Handle<GlobalObject*> global = cx->global();
         RootedObject typedArrayProto(cx, GlobalObject::getOrCreateTypedArrayPrototype(cx, global));
         if (!typedArrayProto)
             return nullptr;
 
         const Class *clasp = TypedArrayObject::protoClassForType(ArrayTypeID());
-        return global->createBlankPrototypeInheriting(cx, clasp, *typedArrayProto);
+        return global->createBlankPrototypeInheriting(cx, clasp, typedArrayProto);
     }
 
     static JSObject *
     createConstructor(JSContext *cx, JSProtoKey key)
     {
         Handle<GlobalObject*> global = cx->global();
         RootedFunction ctorProto(cx, GlobalObject::getOrCreateTypedArrayConstructor(cx, global));
         if (!ctorProto)