Bug 770795 - add NullPtr and associated Handle constructor (r=billm)
authorLuke Wagner <luke@mozilla.com>
Sun, 08 Jul 2012 03:00:11 -0700
changeset 98705 a3c416843da08a87cbcac8a3559b0c6863d21d23
parent 98704 034afcc038c925e2d8f7c066e7cb59c06824a5f8
child 98706 5645ad3abc2c7b19e6304993753286655ca51811
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersbillm
bugs770795
milestone16.0a1
Bug 770795 - add NullPtr and associated Handle constructor (r=billm)
js/public/TemplateLib.h
js/src/frontend/BytecodeCompiler.cpp
js/src/frontend/BytecodeEmitter.cpp
js/src/gc/Marking.cpp
js/src/gc/Root.h
js/src/jsarray.cpp
js/src/jsbool.cpp
js/src/jscompartment.cpp
js/src/jsdate.cpp
js/src/jsexn.cpp
js/src/jsfriendapi.cpp
js/src/jsfun.cpp
js/src/jsinfer.cpp
js/src/jsiter.cpp
js/src/jsnum.cpp
js/src/jsobj.cpp
js/src/jsscope.cpp
js/src/jsscript.cpp
js/src/jsstr.cpp
js/src/jstypedarray.cpp
js/src/jsweakmap.cpp
js/src/vm/ArgumentsObject.cpp
js/src/vm/GlobalObject.cpp
js/src/vm/ScopeObject.cpp
--- a/js/public/TemplateLib.h
+++ b/js/public/TemplateLib.h
@@ -136,16 +136,19 @@ template <> struct IsPodType<bool>      
 template <> struct IsPodType<float>                 { static const bool result = true; };
 template <> struct IsPodType<double>                { static const bool result = true; };
 template <> struct IsPodType<wchar_t>               { static const bool result = true; };
 template <typename T> struct IsPodType<T *>         { static const bool result = true; };
 
 template <bool cond, typename T, T v1, T v2> struct If        { static const T result = v1; };
 template <typename T, T v1, T v2> struct If<false, T, v1, v2> { static const T result = v2; };
 
+template <class T> struct IsPointerType             { static const bool result = false; };
+template <class T> struct IsPointerType<T *>        { static const bool result = true; };
+
 /*
  * Traits class for identifying types that are implicitly barriered.
  */
 template <class T> struct IsRelocatableHeapType { static const bool result = true; };
 
 } /* namespace tl */
 } /* namespace js */
 
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -104,19 +104,25 @@ frontend::CompileScript(JSContext *cx, H
     SharedContext sc(cx, scopeChain, /* fun = */ NULL, /* funbox = */ NULL);
 
     TreeContext tc(&parser, &sc, staticLevel, /* bodyid = */ 0);
     if (!tc.init())
         return NULL;
 
     bool savedCallerFun = compileAndGo && callerFrame && callerFrame->isFunctionFrame();
     GlobalObject *globalObject = needScriptGlobal ? GetCurrentGlobal(cx) : NULL;
-    Rooted<JSScript*> script(cx);
-    script = JSScript::Create(cx, savedCallerFun, principals, originPrincipals, compileAndGo,
-                              noScriptRval, globalObject, version, staticLevel);
+    Rooted<JSScript*> script(cx, JSScript::Create(cx,
+                                                  savedCallerFun,
+                                                  principals,
+                                                  originPrincipals,
+                                                  compileAndGo,
+                                                  noScriptRval,
+                                                  globalObject,
+                                                  version,
+                                                  staticLevel));
     if (!script)
         return NULL;
 
     // We can specialize a bit for the given scope chain if that scope chain is the global object.
     JSObject *globalScope = scopeChain && scopeChain == &scopeChain->global() ? (JSObject*) scopeChain : NULL;
     JS_ASSERT_IF(globalScope, globalScope->isNative());
     JS_ASSERT_IF(globalScope, JSCLASS_HAS_GLOBAL_FLAG_AND_SLOTS(globalScope->getClass()));
 
@@ -262,20 +268,25 @@ frontend::CompileFunctionBody(JSContext 
     fun->setArgCount(funsc.bindings.numArgs());
 
     unsigned staticLevel = 0;
     TreeContext funtc(&parser, &funsc, staticLevel, /* bodyid = */ 0);
     if (!funtc.init())
         return false;
 
     GlobalObject *globalObject = fun->getParent() ? &fun->getParent()->global() : NULL;
-    Rooted<JSScript*> script(cx);
-    script = JSScript::Create(cx, /* savedCallerFun = */ false, principals, originPrincipals,
-                              /* compileAndGo = */ false, /* noScriptRval = */ false,
-                              globalObject, version, staticLevel);
+    Rooted<JSScript*> script(cx, JSScript::Create(cx,
+                                                  /* savedCallerFun = */ false,
+                                                  principals,
+                                                  originPrincipals,
+                                                  /* compileAndGo = */ false,
+                                                  /* noScriptRval = */ false,
+                                                  globalObject,
+                                                  version,
+                                                  staticLevel));
     if (!script)
         return false;
 
     StackFrame *nullCallerFrame = NULL;
     BytecodeEmitter funbce(/* parent = */ NULL, &parser, &funsc, script, nullCallerFrame,
                            /* hasGlobalScope = */ false, lineno);
     if (!funbce.init())
         return false;
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -4819,27 +4819,26 @@ EmitFunc(JSContext *cx, BytecodeEmitter 
         SharedContext sc(cx, /* scopeChain = */ NULL, fun, funbox);
         sc.cxFlags = funbox->cxFlags;
         if (bce->sc->funMightAliasLocals())
             sc.setFunMightAliasLocals();  // inherit funMightAliasLocals from parent
         sc.bindings.transfer(&funbox->bindings);
 
         // Inherit most things (principals, version, etc) from the parent.
         GlobalObject *globalObject = fun->getParent() ? &fun->getParent()->global() : NULL;
-        Rooted<JSScript*> script(cx);
         Rooted<JSScript*> parent(cx, bce->script);
-        script = JSScript::Create(cx,
-                                  /* savedCallerFun = */ false,
-                                  parent->principals,
-                                  parent->originPrincipals,
-                                  parent->compileAndGo,
-                                  /* noScriptRval = */ false,
-                                  globalObject,
-                                  parent->getVersion(),
-                                  parent->staticLevel + 1);
+        Rooted<JSScript*> script(cx, JSScript::Create(cx,
+                                                      /* savedCallerFun = */ false,
+                                                      parent->principals,
+                                                      parent->originPrincipals,
+                                                      parent->compileAndGo,
+                                                      /* noScriptRval = */ false,
+                                                      globalObject,
+                                                      parent->getVersion(),
+                                                      parent->staticLevel + 1));
         if (!script)
             return false;
 
         BytecodeEmitter bce2(bce, bce->parser, &sc, script, bce->callerFrame, bce->hasGlobalScope,
                              pn->pn_pos.begin.lineno);
         if (!bce2.init())
             return false;
 
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -12,16 +12,18 @@
 #include "gc/Marking.h"
 #include "methodjit/MethodJIT.h"
 
 #include "jsobjinlines.h"
 #include "jsscopeinlines.h"
 
 #include "vm/String-inl.h"
 
+void * const js::NullPtr::constNullValue = NULL;
+
 /*
  * There are two mostly separate mark paths. The first is a fast path used
  * internally in the GC. The second is a slow path used for root marking and
  * for API consumers like the cycle collector or Class::trace implementations.
  *
  * The fast path uses explicit stacks. The basic marking process during a GC is
  * that all roots are pushed on to a mark stack, and then each item on the
  * stack is scanned (possibly pushing more stuff) until the stack is empty.
--- a/js/src/gc/Root.h
+++ b/js/src/gc/Root.h
@@ -9,16 +9,17 @@
 #define jsgc_root_h__
 
 #ifdef __cplusplus
 
 #include "mozilla/TypeTraits.h"
 
 #include "jspubtd.h"
 
+#include "js/TemplateLib.h"
 #include "js/Utility.h"
 
 namespace JS {
 
 /*
  * Moving GC Stack Rooting
  *
  * A moving GC may change the physical location of GC allocated things, even
@@ -62,32 +63,51 @@ namespace JS {
  */
 
 template <typename T> class Rooted;
 
 template <typename T>
 struct RootMethods { };
 
 /*
+ * Handle provides an implicit constructor for NullPtr so that, given:
+ *   foo(Handle<JSObject*> h);
+ * callers can simply write:
+ *   foo(NullPtr());
+ * which avoids creating a Rooted<JSObject*> just to pass NULL.
+ */
+struct NullPtr
+{
+    static void * const constNullValue;
+};
+
+/*
  * Reference to a T that has been rooted elsewhere. This is most useful
  * as a parameter type, which guarantees that the T lvalue is properly
  * rooted. See "Move GC Stack Rooting" above.
  */
 template <typename T>
 class Handle
 {
   public:
     /* Creates a handle from a handle of a type convertible to T. */
     template <typename S>
     Handle(Handle<S> handle,
            typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0)
     {
         ptr = reinterpret_cast<const T *>(handle.address());
     }
 
+    /* Create a handle for a NULL pointer. */
+    Handle(NullPtr)
+    {
+        typedef typename js::tl::StaticAssert<js::tl::IsPointerType<T>::result>::result _;
+        ptr = reinterpret_cast<const T *>(&NullPtr::constNullValue);
+    }
+
     /*
      * This may be called only if the location of the T is guaranteed
      * to be marked (for some reason other than being a Rooted),
      * e.g., if it is guaranteed to be reachable from an implicit root.
      *
      * Create a Handle from a raw location of a T.
      */
     static Handle fromMarkedLocation(const T *p) {
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -475,17 +475,16 @@ SetArrayElement(JSContext *cx, HandleObj
         if (result == JSObject::ED_FAILED)
             return false;
         JS_ASSERT(result == JSObject::ED_SPARSE);
         if (!JSObject::makeDenseArraySlow(cx, obj))
             return JS_FALSE;
     }
 
     RootedId id(cx);
-
     if (!IndexToId(cx, obj, index, NULL, id.address(), JS_TRUE))
         return JS_FALSE;
     JS_ASSERT(!JSID_IS_VOID(id));
 
     RootedValue tmp(cx, v);
     return obj->setGeneric(cx, obj, id, tmp.address(), true);
 }
 
@@ -1812,48 +1811,16 @@ InitArrayElements(JSContext *cx, HandleO
             return false;
         }
         idval.getDoubleRef() += 1;
     } while (vector != end);
 
     return true;
 }
 
-#if 0
-static JSBool
-InitArrayObject(JSContext *cx, JSObject *obj, uint32_t length, const Value *vector)
-{
-    JS_ASSERT(obj->isArray());
-
-    JS_ASSERT(obj->isDenseArray());
-    obj->setArrayLength(cx, length);
-    if (!vector || !length)
-        return true;
-
-    if (!InitArrayTypes(cx, obj->getType(cx), vector, length))
-        return false;
-
-    /* Avoid ensureDenseArrayElements to skip sparse array checks there. */
-    if (!obj->ensureElements(cx, length))
-        return false;
-
-    obj->setDenseArrayInitializedLength(length);
-
-    bool hole = false;
-    for (uint32_t i = 0; i < length; i++) {
-        obj->setDenseArrayElement(i, vector[i]);
-        hole |= vector[i].isMagic(JS_ARRAY_HOLE);
-    }
-    if (hole)
-        obj->markDenseArrayNotPacked(cx);
-
-    return true;
-}
-#endif
-
 /*
  * Perl-inspired join, reverse, and sort.
  */
 static JSBool
 array_join(JSContext *cx, unsigned argc, Value *vp)
 {
     JS_CHECK_RECURSION(cx, return false);
 
@@ -3682,27 +3649,24 @@ js_Array(JSContext *cx, unsigned argc, V
     return true;
 }
 
 JSObject *
 js_InitArrayClass(JSContext *cx, JSObject *obj)
 {
     JS_ASSERT(obj->isNative());
 
-    Rooted<GlobalObject*> global(cx);
-    global = &obj->asGlobal();
-
-    RootedObject arrayProto(cx);
-    arrayProto = global->createBlankPrototype(cx, &SlowArrayClass);
+    Rooted<GlobalObject*> global(cx, &obj->asGlobal());
+
+    RootedObject arrayProto(cx, global->createBlankPrototype(cx, &SlowArrayClass));
     if (!arrayProto || !AddLengthProperty(cx, arrayProto))
         return NULL;
     arrayProto->setArrayLength(cx, 0);
 
-    RootedFunction ctor(cx);
-    ctor = global->createConstructor(cx, js_Array, CLASS_NAME(cx, Array), 1);
+    RootedFunction ctor(cx, global->createConstructor(cx, js_Array, CLASS_NAME(cx, Array), 1));
     if (!ctor)
         return NULL;
 
     /*
      * The default 'new' type of Array.prototype is required by type inference
      * to have unknown properties, to simplify handling of e.g. heterogenous
      * arrays in JSON and script literals and allows setDenseArrayElement to
      * be used without updating the indexed type set for such default arrays.
@@ -3773,29 +3737,26 @@ NewArray(JSContext *cx, uint32_t length,
     }
 
     Rooted<GlobalObject*> parent(cx, parent_);
     RootedObject proto(cx, proto_);
 
     if (!proto && !FindProto(cx, &ArrayClass, parent, &proto))
         return NULL;
 
-    RootedTypeObject type(cx);
-
-    type = proto->getNewType(cx);
+    RootedTypeObject type(cx, proto->getNewType(cx));
     if (!type)
         return NULL;
 
     /*
      * Get a shape with zero fixed slots, regardless of the size class.
      * See JSObject::createDenseArray.
      */
-    RootedShape shape(cx);
-    shape = EmptyShape::getInitialShape(cx, &ArrayClass, proto,
-                                        parent, gc::FINALIZE_OBJECT0);
+    RootedShape shape(cx, EmptyShape::getInitialShape(cx, &ArrayClass, proto,
+                                                      parent, gc::FINALIZE_OBJECT0));
     if (!shape)
         return NULL;
 
     JSObject* obj = JSObject::createDenseArray(cx, kind, shape, type, length);
     if (!obj)
         return NULL;
 
     if (entry != -1)
--- a/js/src/jsbool.cpp
+++ b/js/src/jsbool.cpp
@@ -128,18 +128,17 @@ js_InitBooleanClass(JSContext *cx, JSObj
 
     Rooted<GlobalObject*> global(cx, &obj->asGlobal());
 
     RootedObject booleanProto (cx, global->createBlankPrototype(cx, &BooleanClass));
     if (!booleanProto)
         return NULL;
     booleanProto->setFixedSlot(BooleanObject::PRIMITIVE_VALUE_SLOT, BooleanValue(false));
 
-    RootedFunction ctor(cx);
-    ctor = global->createConstructor(cx, Boolean, CLASS_NAME(cx, Boolean), 1);
+    RootedFunction ctor(cx, global->createConstructor(cx, Boolean, CLASS_NAME(cx, Boolean), 1));
     if (!ctor)
         return NULL;
 
     if (!LinkConstructorAndPrototype(cx, ctor, booleanProto))
         return NULL;
 
     if (!DefinePropertiesAndBrand(cx, booleanProto, NULL, boolean_methods))
         return NULL;
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -171,19 +171,18 @@ JSCompartment::wrap(JSContext *cx, Value
     if (vp->isObject()) {
         Rooted<JSObject*> obj(cx, &vp->toObject());
 
         if (obj->compartment() == this)
             return WrapForSameCompartment(cx, obj, vp);
 
         /* Translate StopIteration singleton. */
         if (obj->isStopIteration()) {
-            RootedObject null(cx);
             RootedValue vvp(cx, *vp);
-            bool result = js_FindClassObject(cx, null, JSProto_StopIteration, &vvp);
+            bool result = js_FindClassObject(cx, NullPtr(), JSProto_StopIteration, &vvp);
             *vp = vvp;
             return result;
         }
 
         /* Unwrap the object, but don't unwrap outer windows. */
         obj = UnwrapObject(&vp->toObject(), /* stopAtOuter = */ true, &flags);
 
         if (obj->compartment() == this)
--- a/js/src/jsdate.cpp
+++ b/js/src/jsdate.cpp
@@ -3057,18 +3057,17 @@ js_InitDateClass(JSContext *cx, JSObject
 
     Rooted<GlobalObject*> global(cx, &obj->asGlobal());
 
     RootedObject dateProto(cx, global->createBlankPrototype(cx, &DateClass));
     if (!dateProto)
         return NULL;
     SetDateToNaN(cx, dateProto);
 
-    RootedFunction ctor(cx);
-    ctor = global->createConstructor(cx, js_Date, CLASS_NAME(cx, Date), MAXARGS);
+    RootedFunction ctor(cx, global->createConstructor(cx, js_Date, CLASS_NAME(cx, Date), MAXARGS));
     if (!ctor)
         return NULL;
 
     if (!LinkConstructorAndPrototype(cx, ctor, dateProto))
         return NULL;
 
     if (!DefinePropertiesAndBrand(cx, ctor, NULL, date_static_methods))
         return NULL;
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -792,19 +792,18 @@ InitErrorClass(JSContext *cx, Handle<Glo
                               JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE, 0, 0) ||
         !DefineNativeProperty(cx, errorProto, lineNumberId, Int32Value(0),
                               JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE, 0, 0))
     {
         return NULL;
     }
 
     /* Create the corresponding constructor. */
-    RootedFunction ctor(cx);
-    ctor = global->createConstructor(cx, Exception, name, 1,
-                                     JSFunction::ExtendedFinalizeKind);
+    RootedFunction ctor(cx, global->createConstructor(cx, Exception, name, 1,
+                                                      JSFunction::ExtendedFinalizeKind));
     if (!ctor)
         return NULL;
     ctor->setExtendedSlot(0, Int32Value(int32_t(type)));
 
     if (!LinkConstructorAndPrototype(cx, ctor, errorProto))
         return NULL;
 
     if (!DefineConstructorAndPrototype(cx, global, key, ctor, errorProto))
@@ -823,18 +822,17 @@ js_InitExceptionClasses(JSContext *cx, J
 
     Rooted<GlobalObject*> global(cx, &obj->asGlobal());
 
     RootedObject objectProto(cx, global->getOrCreateObjectPrototype(cx));
     if (!objectProto)
         return NULL;
 
     /* Initialize the base Error class first. */
-    RootedObject errorProto(cx);
-    errorProto = InitErrorClass(cx, global, JSEXN_ERR, objectProto);
+    RootedObject errorProto(cx, InitErrorClass(cx, global, JSEXN_ERR, objectProto));
     if (!errorProto)
         return NULL;
 
     /* |Error.prototype| alone has method properties. */
     if (!DefinePropertiesAndBrand(cx, errorProto, NULL, exception_methods))
         return NULL;
 
     /* Define all remaining *Error constructors. */
@@ -958,19 +956,18 @@ js_ErrorToException(JSContext *cx, const
     PodArrayZero(tv);
     AutoArrayRooter tvr(cx, ArrayLength(tv), tv);
 
     /*
      * Try to get an appropriate prototype by looking up the corresponding
      * exception constructor name in the scope chain of the current context's
      * top stack frame, or in the global object if no frame is active.
      */
-    RootedObject null(cx);
     RootedObject errProto(cx);
-    if (!js_GetClassPrototype(cx, null, GetExceptionProtoKey(exn), &errProto))
+    if (!js_GetClassPrototype(cx, NullPtr(), GetExceptionProtoKey(exn), &errProto))
         return false;
     tv[0] = OBJECT_TO_JSVAL(errProto);
 
     RootedObject errObject(cx, NewObjectWithGivenProto(cx, &ErrorClass, errProto, NULL));
     if (!errObject)
         return false;
     tv[1] = OBJECT_TO_JSVAL(errObject);
 
@@ -1018,17 +1015,16 @@ IsDuckTypedErrorObject(JSContext *cx, Ha
     return true;
 }
 
 JSBool
 js_ReportUncaughtException(JSContext *cx)
 {
     jsval roots[6];
     JSErrorReport *reportp, report;
-    RootedString str(cx);
 
     if (!JS_IsExceptionPending(cx))
         return true;
 
     RootedValue exn(cx);
     if (!JS_GetPendingException(cx, exn.address()))
         return false;
 
@@ -1048,17 +1044,17 @@ js_ReportUncaughtException(JSContext *cx
         exnObject = JSVAL_TO_OBJECT(exn);
         roots[0] = exn;
     }
 
     JS_ClearPendingException(cx);
     reportp = js_ErrorFromException(cx, exn);
 
     /* XXX L10N angels cry once again. see also everywhere else */
-    str = ToString(cx, exn);
+    RootedString str(cx, ToString(cx, exn));
     if (str)
         roots[1] = StringValue(str);
 
     const char *filename_str = js_fileName_str;
     JSAutoByteString filename;
     if (!reportp && exnObject &&
         (exnObject->isError() ||
          IsDuckTypedErrorObject(cx, exnObject, &filename_str)))
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -243,19 +243,18 @@ JS_DefineFunctionsWithHelp(JSContext *cx
 
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     for (; fs->name; fs++) {
         JSAtom *atom = js_Atomize(cx, fs->name, strlen(fs->name));
         if (!atom)
             return false;
 
-        RootedFunction fun(cx);
         Rooted<jsid> id(cx, AtomToId(atom));
-        fun = js_DefineFunction(cx, obj, id, fs->call, fs->nargs, fs->flags);
+        RootedFunction fun(cx, js_DefineFunction(cx, obj, id, fs->call, fs->nargs, fs->flags));
         if (!fun)
             return false;
 
         if (fs->usage) {
             if (!DefineHelpProperty(cx, fun, "usage", fs->usage))
                 return false;
         }
 
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -255,18 +255,17 @@ ResolveInterpretedFunctionPrototype(JSCo
 
 static JSBool
 fun_resolve(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
             MutableHandleObject objp)
 {
     if (!JSID_IS_ATOM(id))
         return true;
 
-    RootedFunction fun(cx);
-    fun = obj->toFunction();
+    RootedFunction fun(cx, obj->toFunction());
 
     if (JSID_IS_ATOM(id, cx->runtime->atomState.classPrototypeAtom)) {
         /*
          * Native or "built-in" functions do not have a .prototype property per
          * ECMA-262, or (Object.prototype, Function.prototype, etc.) have that
          * property created eagerly.
          *
          * ES5 15.3.4: the non-native function object named Function.prototype
@@ -905,30 +904,27 @@ fun_bind(JSContext *cx, unsigned argc, V
     Value &thisv = args.thisv();
 
     /* Step 2. */
     if (!js_IsCallable(thisv)) {
         ReportIncompatibleMethod(cx, args, &FunctionClass);
         return false;
     }
 
-    RootedObject target(cx);
-    target = &thisv.toObject();
-
     /* Step 3. */
     Value *boundArgs = NULL;
     unsigned argslen = 0;
     if (args.length() > 1) {
         boundArgs = args.array() + 1;
         argslen = args.length() - 1;
     }
 
     /* Steps 7-9. */
     RootedValue thisArg(cx, args.length() >= 1 ? args[0] : UndefinedValue());
-
+    RootedObject target(cx, &thisv.toObject());
     JSObject *boundFunction = js_fun_bind(cx, target, thisArg, boundArgs, argslen);
     if (!boundFunction)
         return false;
 
     /* Step 22. */
     args.rval().setObject(*boundFunction);
     return true;
 }
@@ -943,19 +939,18 @@ js_fun_bind(JSContext *cx, HandleObject 
         unsigned nargs = target->toFunction()->nargs;
         if (nargs > argslen)
             length = nargs - argslen;
     }
 
     /* Step 4-6, 10-11. */
     JSAtom *name = target->isFunction() ? target->toFunction()->atom.get() : NULL;
 
-    RootedObject funobj(cx);
-    funobj = js_NewFunction(cx, NULL, CallOrConstructBoundFunction, length,
-                            JSFUN_CONSTRUCTOR, target, name);
+    RootedObject funobj(cx, js_NewFunction(cx, NULL, CallOrConstructBoundFunction, length,
+                                           JSFUN_CONSTRUCTOR, target, name));
     if (!funobj)
         return NULL;
 
     /* NB: Bound functions abuse |parent| to store their target. */
     if (!JSObject::setParent(cx, funobj, target))
         return NULL;
 
     if (!funobj->toFunction()->initBoundFunction(cx, thisArg, boundArgs, argslen))
@@ -997,18 +992,17 @@ JSFunctionSpec function_methods[] = {
 };
 
 JSBool
 Function(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     /* Block this call if security callbacks forbid it. */
-    Rooted<GlobalObject*> global(cx);
-    global = &args.callee().global();
+    Rooted<GlobalObject*> global(cx, &args.callee().global());
     if (!global->isRuntimeCodeGenEnabled(cx)) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CSP_BLOCKED_FUNCTION);
         return false;
     }
 
     Bindings bindings;
     Bindings::AutoRooter bindingsRoot(cx, &bindings);
 
@@ -1207,27 +1201,26 @@ JSFunction *
 js_NewFunction(JSContext *cx, JSObject *funobj, Native native, unsigned nargs,
                unsigned flags, HandleObject parent, JSAtom *atom_, js::gc::AllocKind kind)
 {
     JS_ASSERT(kind == JSFunction::FinalizeKind || kind == JSFunction::ExtendedFinalizeKind);
     JS_ASSERT(sizeof(JSFunction) <= gc::Arena::thingSize(JSFunction::FinalizeKind));
     JS_ASSERT(sizeof(FunctionExtended) <= gc::Arena::thingSize(JSFunction::ExtendedFinalizeKind));
 
     RootedAtom atom(cx, atom_);
-    RootedFunction fun(cx);
 
     if (funobj) {
         JS_ASSERT(funobj->isFunction());
         JS_ASSERT(funobj->getParent() == parent);
     } else {
         funobj = NewObjectWithClassProto(cx, &FunctionClass, NULL, SkipScopeParent(parent), kind);
         if (!funobj)
             return NULL;
     }
-    fun = static_cast<JSFunction *>(funobj);
+    RootedFunction fun(cx, static_cast<JSFunction *>(funobj));
 
     /* Initialize all function members. */
     fun->nargs = uint16_t(nargs);
     fun->flags = flags & (JSFUN_FLAGS_MASK | JSFUN_KINDMASK);
     if ((flags & JSFUN_KINDMASK) >= JSFUN_INTERPRETED) {
         JS_ASSERT(!native);
         fun->mutableScript().init(NULL);
         fun->initEnvironment(parent);
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -4565,18 +4565,17 @@ AnalyzePoppedThis(JSContext *cx, Vector<
  */
 static void
 CheckNewScriptProperties(JSContext *cx, HandleTypeObject type, JSFunction *fun)
 {
     if (type->unknownProperties() || fun->script()->isInnerFunction)
         return;
 
     /* Strawman object to add properties to and watch for duplicates. */
-    RootedObject baseobj(cx);
-    baseobj = NewBuiltinClassInstance(cx, &ObjectClass, gc::FINALIZE_OBJECT16);
+    RootedObject baseobj(cx, NewBuiltinClassInstance(cx, &ObjectClass, gc::FINALIZE_OBJECT16));
     if (!baseobj) {
         if (type->newScript)
             type->clearNewScript(cx);
         return;
     }
 
     Vector<TypeNewScript::Initializer> initializerList(cx);
     AnalyzeNewScriptProperties(cx, type, fun, baseobj.address(), &initializerList);
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -478,29 +478,26 @@ Compare(T *a, T *b, size_t c)
     }
     return true;
 }
 
 static inline JSObject *
 NewIteratorObject(JSContext *cx, unsigned flags)
 {
     if (flags & JSITER_ENUMERATE) {
-        RootedTypeObject type(cx);
-        type = cx->compartment->getEmptyType(cx);
+        RootedTypeObject type(cx, cx->compartment->getEmptyType(cx));
         if (!type)
             return NULL;
 
-        RootedShape emptyEnumeratorShape(cx);
-        emptyEnumeratorShape = EmptyShape::getInitialShape(cx, &IteratorClass, NULL, NULL,
-                                                           ITERATOR_FINALIZE_KIND);
-        if (!emptyEnumeratorShape)
+        RootedShape shape(cx, EmptyShape::getInitialShape(cx, &IteratorClass, NULL, NULL,
+                                                          ITERATOR_FINALIZE_KIND));
+        if (!shape)
             return NULL;
 
-        JSObject *obj = JSObject::create(cx, ITERATOR_FINALIZE_KIND,
-                                         emptyEnumeratorShape, type, NULL);
+        JSObject *obj = JSObject::create(cx, ITERATOR_FINALIZE_KIND, shape, type, NULL);
         if (!obj)
             return NULL;
 
         JS_ASSERT(obj->numFixedSlots() == JSObject::ITER_CLASS_NFIXED_SLOTS);
         return obj;
     }
 
     return NewBuiltinClassInstance(cx, &IteratorClass);
@@ -812,18 +809,17 @@ Iterator(JSContext *cx, unsigned argc, V
     return true;
 }
 
 JSBool
 js_ThrowStopIteration(JSContext *cx)
 {
     JS_ASSERT(!JS_IsExceptionPending(cx));
     RootedValue v(cx);
-    RootedObject null(cx);
-    if (js_FindClassObject(cx, null, JSProto_StopIteration, &v))
+    if (js_FindClassObject(cx, NullPtr(), JSProto_StopIteration, &v))
         cx->setPendingException(v);
     return JS_FALSE;
 }
 
 static JSBool
 iterator_next(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
@@ -1710,18 +1706,17 @@ InitIteratorClass(JSContext *cx, Handle<
     AutoIdVector blank(cx);
     NativeIterator *ni = NativeIterator::allocateIterator(cx, 0, blank);
     if (!ni)
         return false;
     ni->init(NULL, 0 /* flags */, 0, 0);
 
     iteratorProto->setNativeIterator(ni);
 
-    RootedFunction ctor(cx);
-    ctor = global->createConstructor(cx, Iterator, CLASS_NAME(cx, Iterator), 2);
+    RootedFunction ctor(cx, global->createConstructor(cx, Iterator, CLASS_NAME(cx, Iterator), 2));
     if (!ctor)
         return false;
 
     if (!LinkConstructorAndPrototype(cx, ctor, iteratorProto))
         return false;
 
     if (!DefinePropertiesAndBrand(cx, iteratorProto, NULL, iterator_methods))
         return false;
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -1051,18 +1051,17 @@ js_InitNumberClass(JSContext *cx, JSObje
 
     Rooted<GlobalObject*> global(cx, &obj->asGlobal());
 
     RootedObject numberProto(cx, global->createBlankPrototype(cx, &NumberClass));
     if (!numberProto)
         return NULL;
     numberProto->asNumber().setPrimitiveValue(0);
 
-    RootedFunction ctor(cx);
-    ctor = global->createConstructor(cx, Number, CLASS_NAME(cx, Number), 1);
+    RootedFunction ctor(cx, global->createConstructor(cx, Number, CLASS_NAME(cx, Number), 1));
     if (!ctor)
         return NULL;
 
     if (!LinkConstructorAndPrototype(cx, ctor, numberProto))
         return NULL;
 
     /* Add numeric constants (MAX_VALUE, NaN, &c.) to the Number constructor. */
     if (!JS_DefineConstDoubles(cx, ctor, number_constants))
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -2001,18 +2001,17 @@ obj_create(JSContext *cx, unsigned argc,
         return false;
     }
 #endif
 
     /*
      * Use the callee's global as the parent of the new object to avoid dynamic
      * scoping (i.e., using the caller's global).
      */
-    RootedObject obj(cx);
-    obj = NewObjectWithGivenProto(cx, &ObjectClass, proto, &args.callee().global());
+    RootedObject obj(cx, NewObjectWithGivenProto(cx, &ObjectClass, proto, &args.callee().global()));
     if (!obj)
         return false;
 
     /* Don't track types or array-ness for objects created here. */
     MarkTypeObjectUnknownProperties(cx, obj->type());
 
     /* 15.2.3.5 step 4. */
     if (args.hasDefined(1)) {
@@ -2347,18 +2346,17 @@ NewObject(JSContext *cx, Class *clasp, t
 {
     JS_ASSERT(clasp != &ArrayClass);
     JS_ASSERT_IF(clasp == &FunctionClass,
                  kind == JSFunction::FinalizeKind || kind == JSFunction::ExtendedFinalizeKind);
     JS_ASSERT_IF(parent, &parent->global() == cx->compartment->maybeGlobal());
 
     RootedTypeObject type(cx, type_);
 
-    RootedShape shape(cx);
-    shape = EmptyShape::getInitialShape(cx, clasp, type->proto, parent, kind);
+    RootedShape shape(cx, EmptyShape::getInitialShape(cx, clasp, type->proto, parent, kind));
     if (!shape)
         return NULL;
 
     HeapSlot *slots;
     if (!PreallocateObjectDynamicSlots(cx, shape, &slots))
         return NULL;
 
     JSObject *obj = JSObject::create(cx, kind, shape, type, slots);
@@ -3244,18 +3242,17 @@ DefineConstructorAndPrototype(JSContext 
 
     /*
      * Create the prototype object.  (GlobalObject::createBlankPrototype isn't
      * used because it parents the prototype object to the global and because
      * it uses WithProto::Given.  FIXME: Undo dependencies on this parentage
      * [which already needs to happen for bug 638316], figure out nicer
      * semantics for null-protoProto, and use createBlankPrototype.)
      */
-    RootedObject proto(cx);
-    proto = NewObjectWithClassProto(cx, clasp, protoProto, obj);
+    RootedObject proto(cx, NewObjectWithClassProto(cx, clasp, protoProto, obj));
     if (!proto)
         return NULL;
 
     if (!proto->setSingletonType(cx))
         return NULL;
 
     if (clasp == &ArrayClass && !JSObject::makeDenseArraySlow(cx, proto))
         return NULL;
@@ -3282,19 +3279,18 @@ DefineConstructorAndPrototype(JSContext 
         ctor = proto;
     } else {
         /*
          * Create the constructor, not using GlobalObject::createConstructor
          * because the constructor currently must have |obj| as its parent.
          * (FIXME: remove this dependency on the exact identity of the parent,
          * perhaps as part of bug 638316.)
          */
-        RootedFunction fun(cx);
-        fun = js_NewFunction(cx, NULL, constructor, nargs, JSFUN_CONSTRUCTOR, obj, atom,
-                             ctorKind);
+        RootedFunction fun(cx, js_NewFunction(cx, NULL, constructor, nargs, JSFUN_CONSTRUCTOR,
+                                              obj, atom, ctorKind));
         if (!fun)
             goto bad;
 
         /*
          * Set the class object early for standard class constructors. Type
          * inference may need to access these, and js_GetClassPrototype will
          * fail if it tries to do a reentrant reconstruction of the class.
          */
@@ -3390,18 +3386,17 @@ JSObject *
 js_InitClass(JSContext *cx, HandleObject obj, JSObject *protoProto_,
              Class *clasp, Native constructor, unsigned nargs,
              JSPropertySpec *ps, JSFunctionSpec *fs,
              JSPropertySpec *static_ps, JSFunctionSpec *static_fs,
              JSObject **ctorp, AllocKind ctorKind)
 {
     RootedObject protoProto(cx, protoProto_);
 
-    RootedAtom atom(cx);
-    atom = js_Atomize(cx, clasp->name, strlen(clasp->name));
+    RootedAtom atom(cx, js_Atomize(cx, clasp->name, strlen(clasp->name)));
     if (!atom)
         return NULL;
 
     /*
      * All instances of the class will inherit properties from the prototype
      * object we are about to create (in DefineConstructorAndPrototype), which
      * in turn will inherit from protoProto.
      *
@@ -4082,29 +4077,28 @@ CallAddPropertyHook(JSContext *cx, Class
         }
     }
     return true;
 }
 
 namespace js {
 
 Shape *
-DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, const Value &value_,
+DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, const Value &valueArg,
                      PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
                      unsigned flags, int shortid, unsigned defineHow /* = 0 */)
 {
     JS_ASSERT((defineHow & ~(DNP_CACHE_RESULT | DNP_DONT_PURGE |
                              DNP_SKIP_TYPE)) == 0);
     JS_ASSERT(!(attrs & JSPROP_NATIVE_ACCESSORS));
 
     AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
 
     /* Make a local copy of value so addProperty can mutate its inout parameter. */
-    RootedValue value(cx);
-    value = value_;
+    RootedValue value(cx, valueArg);
 
     /*
      * If defining a getter or setter, we must check for its counterpart and
      * update the attributes and property ops.  A getter or setter is really
      * only half of a property.
      */
     RootedShape shape(cx);
     if (attrs & (JSPROP_GETTER | JSPROP_SETTER)) {
--- a/js/src/jsscope.cpp
+++ b/js/src/jsscope.cpp
@@ -407,19 +407,17 @@ JSObject::toDictionaryMode(JSContext *cx
      * Clone the shapes into a new dictionary list. Don't update the
      * last property of this object until done, otherwise a GC
      * triggered while creating the dictionary will get the wrong
      * slot span for this object.
      */
     RootedShape root(cx);
     RootedShape dictionaryShape(cx);
 
-    RootedShape shape(cx);
-    shape = lastProperty();
-
+    RootedShape shape(cx, lastProperty());
     while (shape) {
         JS_ASSERT(!shape->inDictionary());
 
         Shape *dprop = js_NewGCShape(cx);
         if (!dprop) {
             js_ReportOutOfMemory(cx);
             return false;
         }
@@ -799,20 +797,18 @@ JSObject::changeProperty(JSContext *cx, 
 }
 
 bool
 JSObject::removeProperty(JSContext *cx, jsid id_)
 {
     RootedId id(cx, id_);
     RootedObject self(cx, this);
 
-    RootedShape shape(cx);
-
     Shape **spp;
-    shape = Shape::search(cx, lastProperty(), id, &spp);
+    RootedShape shape(cx, Shape::search(cx, lastProperty(), id, &spp));
     if (!shape)
         return true;
 
     /*
      * If shape is not the last property added, or the last property cannot
      * be removed, switch to dictionary mode.
      */
     if (!self->inDictionaryMode() && (shape != self->lastProperty() || !self->canRemoveLastProperty())) {
@@ -1290,20 +1286,18 @@ EmptyShape::getInitialShape(JSContext *c
     InitialShapeSet::AddPtr p = table.lookupForAdd(lookup);
 
     if (p)
         return p->shape;
 
     RootedObject protoRoot(cx, lookup.proto);
     RootedObject parentRoot(cx, lookup.parent);
 
-    Rooted<UnownedBaseShape*> nbase(cx);
-
     StackBaseShape base(clasp, parent, objectFlags);
-    nbase = BaseShape::getUnowned(cx, base);
+    Rooted<UnownedBaseShape*> nbase(cx, BaseShape::getUnowned(cx, base));
     if (!nbase)
         return NULL;
 
     Shape *shape = cx->propertyTree().newShape(cx);
     if (!shape)
         return NULL;
     new (shape) EmptyShape(nbase, nfixed);
 
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -168,18 +168,17 @@ Bindings::callObjectShape(JSContext *cx)
             if (!shapes.append(&s))
                 return NULL;
         }
     }
 
     /*
      * Now build the Shape without duplicate properties.
      */
-    RootedShape shape(cx);
-    shape = initialShape(cx);
+    RootedShape shape(cx, initialShape(cx));
     for (int i = shapes.length() - 1; i >= 0; --i) {
         shape = shape->getChildBinding(cx, shapes[i]);
         if (!shape)
             return NULL;
     }
 
     return shape;
 }
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -1956,47 +1956,44 @@ BuildFlatReplacement(JSContext *cx, Hand
                  */
                 if (match >= pos) {
                     /*
                      * If this part of the rope overlaps with the left side of
                      * the pattern, then it must be the only one to overlap with
                      * the first character in the pattern, so we include the
                      * replacement string here.
                      */
-                    RootedString leftSide(cx);
-                    leftSide = js_NewDependentString(cx, str, 0, match - pos);
+                    RootedString leftSide(cx, js_NewDependentString(cx, str, 0, match - pos));
                     if (!leftSide ||
                         !builder.append(leftSide) ||
                         !builder.append(repstr)) {
                         return false;
                     }
                 }
 
                 /*
                  * If str runs off the end of the matched string, append the
                  * last part of str.
                  */
                 if (strEnd > matchEnd) {
-                    RootedString rightSide(cx);
-                    rightSide = js_NewDependentString(cx, str, matchEnd - pos,
-                                                      strEnd - matchEnd);
+                    RootedString rightSide(cx, js_NewDependentString(cx, str, matchEnd - pos,
+                                                                     strEnd - matchEnd));
                     if (!rightSide || !builder.append(rightSide))
                         return false;
                 }
             } else {
                 if (!builder.append(str))
                     return false;
             }
             pos += str->length();
             if (!r.popFront())
                 return false;
         }
     } else {
-        RootedString leftSide(cx);
-        leftSide = js_NewDependentString(cx, textstr, 0, match);
+        RootedString leftSide(cx, js_NewDependentString(cx, textstr, 0, match));
         if (!leftSide)
             return false;
         RootedString rightSide(cx);
         rightSide = js_NewDependentString(cx, textstr, match + fm.patternLength(),
                                           textstr->length() - match - fm.patternLength());
         if (!rightSide ||
             !builder.append(leftSide) ||
             !builder.append(repstr) ||
@@ -2208,18 +2205,17 @@ LambdaIsGetElem(JSObject &lambda, JSCont
     GET_NAME_FROM_BYTECODE(script, pc, 0, bname);
     pc += JSOP_NAME_LENGTH;
 
     /*
      * Do a conservative search for 'b' in the enclosing scope. Avoid using a
      * real name lookup since this can trigger observable effects.
      */
     Value b;
-    RootedObject scope(cx);
-    scope = cx->stack.currentScriptedScopeChain();
+    RootedObject scope(cx, cx->stack.currentScriptedScopeChain());
     while (true) {
         if (!scope->isCall() && !scope->isBlock())
             return NULL;
         if (HasDataProperty(cx, scope, bname, &b))
             break;
         scope = &scope->asScope().enclosingScope();
     }
 
@@ -3064,18 +3060,17 @@ js_InitStringClass(JSContext *cx, JSObje
     Rooted<GlobalObject*> global(cx, &obj->asGlobal());
 
     Rooted<JSString*> empty(cx, cx->runtime->emptyString);
     RootedObject proto(cx, global->createBlankPrototype(cx, &StringClass));
     if (!proto || !proto->asString().init(cx, empty))
         return NULL;
 
     /* Now create the String function. */
-    RootedFunction ctor(cx);
-    ctor = global->createConstructor(cx, js_String, CLASS_NAME(cx, String), 1);
+    RootedFunction ctor(cx, global->createConstructor(cx, js_String, CLASS_NAME(cx, String), 1));
     if (!ctor)
         return NULL;
 
     if (!LinkConstructorAndPrototype(cx, ctor, proto))
         return NULL;
 
     if (!DefinePropertiesAndBrand(cx, proto, NULL, string_methods) ||
         !DefinePropertiesAndBrand(cx, ctor, NULL, string_static_methods))
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -3029,18 +3029,16 @@ InitTypedArrayClass(JSContext *cx)
         !proto->defineProperty(cx, cx->runtime->atomState.BYTES_PER_ELEMENTAtom,
                                Int32Value(ArrayType::BYTES_PER_ELEMENT),
                                JS_PropertyStub, JS_StrictPropertyStub,
                                JSPROP_PERMANENT | JSPROP_READONLY))
     {
         return NULL;
     }
 
-    RootedObject foo(cx);
-
     if (!ArrayType::defineGetters(cx, proto))
         return NULL;
 
     if (!JS_DefineFunctions(cx, proto, ArrayType::jsfuncs))
         return NULL;
 
     if (!DefineConstructorAndPrototype(cx, global, ArrayType::key, ctor, proto))
         return NULL;
@@ -3085,19 +3083,18 @@ Class TypedArray::protoClasses[TYPE_MAX]
 static JSObject *
 InitArrayBufferClass(JSContext *cx)
 {
     Rooted<GlobalObject*> global(cx, cx->compartment->maybeGlobal());
     RootedObject arrayBufferProto(cx, global->createBlankPrototype(cx, &ArrayBufferObject::protoClass));
     if (!arrayBufferProto)
         return NULL;
 
-    RootedFunction ctor(cx);
-    ctor = global->createConstructor(cx, ArrayBufferObject::class_constructor,
-                                     CLASS_NAME(cx, ArrayBuffer), 1);
+    RootedFunction ctor(cx, global->createConstructor(cx, ArrayBufferObject::class_constructor,
+                                                      CLASS_NAME(cx, ArrayBuffer), 1));
     if (!ctor)
         return NULL;
 
     if (!LinkConstructorAndPrototype(cx, ctor, arrayBufferProto))
         return NULL;
 
     RootedId byteLengthId(cx, NameToId(cx->runtime->atomState.byteLengthAtom));
     unsigned flags = JSPROP_PERMANENT | JSPROP_READONLY | JSPROP_SHARED | JSPROP_GETTER;
--- a/js/src/jsweakmap.cpp
+++ b/js/src/jsweakmap.cpp
@@ -363,19 +363,18 @@ js_InitWeakMapClass(JSContext *cx, JSObj
     JS_ASSERT(obj->isNative());
 
     Rooted<GlobalObject*> global(cx, &obj->asGlobal());
 
     RootedObject weakMapProto(cx, global->createBlankPrototype(cx, &WeakMapClass));
     if (!weakMapProto)
         return NULL;
 
-    RootedFunction ctor(cx);
-    ctor = global->createConstructor(cx, WeakMap_construct,
-                                     CLASS_NAME(cx, WeakMap), 0);
+    RootedFunction ctor(cx, global->createConstructor(cx, WeakMap_construct,
+                                                      CLASS_NAME(cx, WeakMap), 0));
     if (!ctor)
         return NULL;
 
     if (!LinkConstructorAndPrototype(cx, ctor, weakMapProto))
         return NULL;
 
     if (!DefinePropertiesAndBrand(cx, weakMapProto, NULL, weak_map_methods))
         return NULL;
--- a/js/src/vm/ArgumentsObject.cpp
+++ b/js/src/vm/ArgumentsObject.cpp
@@ -25,30 +25,27 @@ using namespace js::gc;
 ArgumentsObject *
 ArgumentsObject::create(JSContext *cx, StackFrame *fp)
 {
     JSFunction &callee = fp->callee();
     RootedObject proto(cx, callee.global().getOrCreateObjectPrototype(cx));
     if (!proto)
         return NULL;
 
-    RootedTypeObject type(cx);
-    type = proto->getNewType(cx);
+    RootedTypeObject type(cx, proto->getNewType(cx));
     if (!type)
         return NULL;
 
     bool strict = callee.inStrictMode();
     Class *clasp = strict ? &StrictArgumentsObjectClass : &NormalArgumentsObjectClass;
 
-    RootedShape emptyArgumentsShape(cx);
-    emptyArgumentsShape =
-        EmptyShape::getInitialShape(cx, clasp, proto,
-                                    proto->getParent(), FINALIZE_KIND,
-                                    BaseShape::INDEXED);
-    if (!emptyArgumentsShape)
+    RootedShape shape(cx, EmptyShape::getInitialShape(cx, clasp, proto,
+                                                      proto->getParent(), FINALIZE_KIND,
+                                                      BaseShape::INDEXED));
+    if (!shape)
         return NULL;
 
     unsigned numActuals = fp->numActualArgs();
     unsigned numFormals = fp->numFormalArgs();
     unsigned numDeletedWords = NumWordsForBitArrayOfLength(numActuals);
     unsigned numArgs = Max(numActuals, numFormals);
     unsigned numBytes = offsetof(ArgumentsData, args) +
                         numDeletedWords * sizeof(size_t) +
@@ -72,17 +69,17 @@ ArgumentsObject::create(JSContext *cx, S
     } else if (numActuals < numFormals) {
         for (; dst != dstEnd; ++dst)
             dst->init(UndefinedValue());
     }
 
     data->deletedBits = reinterpret_cast<size_t *>(dstEnd);
     ClearAllBitArrayElements(data->deletedBits, numDeletedWords);
 
-    JSObject *obj = JSObject::create(cx, FINALIZE_KIND, emptyArgumentsShape, type, NULL);
+    JSObject *obj = JSObject::create(cx, FINALIZE_KIND, shape, type, NULL);
     if (!obj)
         return NULL;
 
     obj->initFixedSlot(INITIAL_LENGTH_SLOT, Int32Value(numActuals << PACKED_BITS_COUNT));
     obj->initFixedSlot(DATA_SLOT, PrivateValue(data));
 
     /*
      * If it exists and the arguments object aliases formals, the call object
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -108,26 +108,25 @@ GlobalObject::initFunctionAndObjectClass
          */
         JSObject *proto = js_NewFunction(cx, functionProto,
                                          NULL, 0, JSFUN_INTERPRETED, self, NULL);
         if (!proto)
             return NULL;
         JS_ASSERT(proto == functionProto);
         functionProto->flags |= JSFUN_PROTOTYPE;
 
-        Rooted<JSScript*> script(cx);
-        script = JSScript::Create(cx,
-                                  /* savedCallerFun = */ false,
-                                  /* principals = */ NULL,
-                                  /* originPrincipals = */ NULL,
-                                  /* compileAndGo = */ false,
-                                  /* noScriptRval = */ true,
-                                  /* globalObject = */ NULL,
-                                  JSVERSION_DEFAULT,
-                                  /* staticLevel = */ 0);
+        Rooted<JSScript*> script(cx, JSScript::Create(cx,
+                                                      /* savedCallerFun = */ false,
+                                                      /* principals = */ NULL,
+                                                      /* originPrincipals = */ NULL,
+                                                      /* compileAndGo = */ false,
+                                                      /* noScriptRval = */ true,
+                                                      /* globalObject = */ NULL,
+                                                      JSVERSION_DEFAULT,
+                                                      /* staticLevel = */ 0));
         if (!script || !script->fullyInitTrivial(cx))
             return NULL;
 
         functionProto->initScript(script);
         functionProto->getType(cx)->interpretedFunction = functionProto;
         script->setFunction(functionProto);
 
         if (!functionProto->setSingletonType(cx))
--- a/js/src/vm/ScopeObject.cpp
+++ b/js/src/vm/ScopeObject.cpp
@@ -86,27 +86,25 @@ js::ScopeCoordinateToFrameIndex(JSScript
  * Construct a call object for the given bindings.  If this is a call object
  * for a function invocation, callee should be the function being called.
  * Otherwise it must be a call object for eval of strict mode code, and callee
  * must be null.
  */
 CallObject *
 CallObject::create(JSContext *cx, JSScript *script, HandleObject enclosing, HandleFunction callee)
 {
-    RootedShape shape(cx);
-    shape = script->bindings.callObjectShape(cx);
+    RootedShape shape(cx, script->bindings.callObjectShape(cx));
     if (shape == NULL)
         return NULL;
 
     gc::AllocKind kind = gc::GetGCObjectKind(shape->numFixedSlots());
     JS_ASSERT(CanBeFinalizedInBackground(kind, &CallClass));
     kind = gc::GetBackgroundAllocKind(kind);
 
-    RootedTypeObject type(cx);
-    type = cx->compartment->getEmptyType(cx);
+    RootedTypeObject type(cx, cx->compartment->getEmptyType(cx));
     if (!type)
         return NULL;
 
     HeapSlot *slots;
     if (!PreallocateObjectDynamicSlots(cx, shape, &slots))
         return NULL;
 
     RootedObject obj(cx, JSObject::create(cx, kind, shape, type, slots));
@@ -283,18 +281,17 @@ Class js::DeclEnvClass = {
     JS_EnumerateStub,
     JS_ResolveStub,
     JS_ConvertStub
 };
 
 DeclEnvObject *
 DeclEnvObject::create(JSContext *cx, StackFrame *fp)
 {
-    RootedTypeObject type(cx);
-    type = cx->compartment->getEmptyType(cx);
+    RootedTypeObject type(cx, cx->compartment->getEmptyType(cx));
     if (!type)
         return NULL;
 
     RootedShape emptyDeclEnvShape(cx);
     emptyDeclEnvShape = EmptyShape::getInitialShape(cx, &DeclEnvClass, NULL,
                                                     &fp->global(), FINALIZE_KIND);
     if (!emptyDeclEnvShape)
         return NULL;
@@ -315,28 +312,26 @@ DeclEnvObject::create(JSContext *cx, Sta
     }
 
     return &obj->asDeclEnv();
 }
 
 WithObject *
 WithObject::create(JSContext *cx, HandleObject proto, HandleObject enclosing, uint32_t depth)
 {
-    RootedTypeObject type(cx);
-    type = proto->getNewType(cx);
+    RootedTypeObject type(cx, proto->getNewType(cx));
     if (!type)
         return NULL;
 
-    RootedShape emptyWithShape(cx);
-    emptyWithShape = EmptyShape::getInitialShape(cx, &WithClass, proto,
-                                                 &enclosing->global(), FINALIZE_KIND);
-    if (!emptyWithShape)
+    RootedShape shape(cx, EmptyShape::getInitialShape(cx, &WithClass, proto,
+                                                      &enclosing->global(), FINALIZE_KIND));
+    if (!shape)
         return NULL;
 
-    RootedObject obj(cx, JSObject::create(cx, FINALIZE_KIND, emptyWithShape, type, NULL));
+    RootedObject obj(cx, JSObject::create(cx, FINALIZE_KIND, shape, type, NULL));
     if (!obj)
         return NULL;
 
     if (!obj->asScope().setEnclosingScope(cx, enclosing))
         return NULL;
 
     obj->setReservedSlot(DEPTH_SLOT, PrivateUint32Value(depth));
 
@@ -578,27 +573,25 @@ Class js::WithClass = {
     }
 };
 
 /*****************************************************************************/
 
 ClonedBlockObject *
 ClonedBlockObject::create(JSContext *cx, Handle<StaticBlockObject *> block, StackFrame *fp)
 {
-    RootedTypeObject type(cx);
-    type = block->getNewType(cx);
+    RootedTypeObject type(cx, block->getNewType(cx));
     if (!type)
         return NULL;
 
     HeapSlot *slots;
     if (!PreallocateObjectDynamicSlots(cx, block->lastProperty(), &slots))
         return NULL;
 
-    RootedShape shape(cx);
-    shape = block->lastProperty();
+    RootedShape shape(cx, block->lastProperty());
 
     RootedObject obj(cx, JSObject::create(cx, FINALIZE_KIND, shape, type, slots));
     if (!obj)
         return NULL;
 
     /* Set the parent if necessary, as for call objects. */
     if (&fp->global() != obj->getParent()) {
         JS_ASSERT(obj->getParent() == NULL);
@@ -639,27 +632,25 @@ ClonedBlockObject::copyUnaliasedValues(S
         if (!block.isAliased(i))
             setVar(i, fp->unaliasedLocal(base + i), DONT_CHECK_ALIASING);
     }
 }
 
 StaticBlockObject *
 StaticBlockObject::create(JSContext *cx)
 {
-    RootedTypeObject type(cx);
-    type = cx->compartment->getEmptyType(cx);
+    RootedTypeObject type(cx, cx->compartment->getEmptyType(cx));
     if (!type)
         return NULL;
 
-    RootedShape emptyBlockShape(cx);
-    emptyBlockShape = EmptyShape::getInitialShape(cx, &BlockClass, NULL, NULL, FINALIZE_KIND);
-    if (!emptyBlockShape)
+    RootedShape shape(cx, EmptyShape::getInitialShape(cx, &BlockClass, NULL, NULL, FINALIZE_KIND));
+    if (!shape)
         return NULL;
 
-    JSObject *obj = JSObject::create(cx, FINALIZE_KIND, emptyBlockShape, type, NULL);
+    JSObject *obj = JSObject::create(cx, FINALIZE_KIND, shape, type, NULL);
     if (!obj)
         return NULL;
 
     return &obj->asStaticBlock();
 }
 
 Shape *
 StaticBlockObject::addVar(JSContext *cx, jsid id, int index, bool *redeclared)