Bug 777219 - Prepare SpiderMonkey for a fully rooted API; r=bhackett
authorSteve Fink <sfink@mozilla.com>
Mon, 23 Jul 2012 13:37:31 -0700
changeset 104275 a91040f69ea354d3c19a250e0fa5da1bbf9aabfc
parent 104274 aa61e5ec56123c8411689e146ff4c3983bdc9b67
child 104276 61d7f15ea6a760def8b09109848a6dd2e6481941
child 104285 88798c5eafa90f99544649f33195482138a8e7a1
push idunknown
push userunknown
push dateunknown
reviewersbhackett
bugs777219
milestone17.0a1
Bug 777219 - Prepare SpiderMonkey for a fully rooted API; r=bhackett
js/src/builtin/Eval.cpp
js/src/builtin/MapObject.cpp
js/src/builtin/TestingFunctions.cpp
js/src/builtin/TestingFunctions.h
js/src/ctypes/CTypes.cpp
js/src/ctypes/CTypes.h
js/src/ctypes/Library.cpp
js/src/gc/Root.h
js/src/jsapi-tests/selfTest.cpp
js/src/jsapi-tests/testAddPropertyPropcache.cpp
js/src/jsapi-tests/testBindCallable.cpp
js/src/jsapi-tests/testBug604087.cpp
js/src/jsapi-tests/testCallNonGenericMethodOnProxy.cpp
js/src/jsapi-tests/testChromeBuffer.cpp
js/src/jsapi-tests/testClassGetter.cpp
js/src/jsapi-tests/testCloneScript.cpp
js/src/jsapi-tests/testConservativeGC.cpp
js/src/jsapi-tests/testCustomIterator.cpp
js/src/jsapi-tests/testDebugger.cpp
js/src/jsapi-tests/testDeepFreeze.cpp
js/src/jsapi-tests/testDefineGetterSetterNonEnumerable.cpp
js/src/jsapi-tests/testDefineProperty.cpp
js/src/jsapi-tests/testFunctionProperties.cpp
js/src/jsapi-tests/testGCOutOfMemory.cpp
js/src/jsapi-tests/testGetPropertyDefault.cpp
js/src/jsapi-tests/testIntString.cpp
js/src/jsapi-tests/testJSEvaluateScript.cpp
js/src/jsapi-tests/testLookup.cpp
js/src/jsapi-tests/testLooselyEqual.cpp
js/src/jsapi-tests/testNewObject.cpp
js/src/jsapi-tests/testOps.cpp
js/src/jsapi-tests/testOriginPrincipals.cpp
js/src/jsapi-tests/testParseJSON.cpp
js/src/jsapi-tests/testProfileStrings.cpp
js/src/jsapi-tests/testRegExp.cpp
js/src/jsapi-tests/testResolveRecursion.cpp
js/src/jsapi-tests/testScriptObject.cpp
js/src/jsapi-tests/testSetProperty.cpp
js/src/jsapi-tests/testTrap.cpp
js/src/jsapi-tests/testTypedArrays.cpp
js/src/jsapi-tests/testValueABI.cpp
js/src/jsapi-tests/testVersion.cpp
js/src/jsapi-tests/testXDR.cpp
js/src/jsapi-tests/tests.cpp
js/src/jsapi-tests/tests.h
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jsarray.cpp
js/src/jsclone.cpp
js/src/jsclone.h
js/src/jscntxt.cpp
js/src/jscntxt.h
js/src/jscntxtinlines.h
js/src/jscompartment.cpp
js/src/jsdate.cpp
js/src/jsdbgapi.cpp
js/src/jsfriendapi.cpp
js/src/jsfriendapi.h
js/src/jsfun.cpp
js/src/jsfun.h
js/src/jsinferinlines.h
js/src/jsinterp.cpp
js/src/jsinterp.h
js/src/jsiter.cpp
js/src/jsmath.cpp
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsobjinlines.h
js/src/json.cpp
js/src/json.h
js/src/jsopcode.cpp
js/src/jsproxy.cpp
js/src/jsproxy.h
js/src/jspubtd.h
js/src/jsreflect.cpp
js/src/jsscript.cpp
js/src/jsstr.cpp
js/src/jstypedarray.cpp
js/src/jsweakmap.cpp
js/src/jswrapper.cpp
js/src/jswrapper.h
js/src/jsxml.cpp
js/src/perf/jsperf.cpp
js/src/perf/jsperf.h
js/src/shell/js.cpp
js/src/vm/Debugger.cpp
js/src/vm/GlobalObject.h
js/src/vm/ScopeObject.cpp
js/src/vm/Xdr.cpp
js/src/vm/Xdr.h
--- a/js/src/builtin/Eval.cpp
+++ b/js/src/builtin/Eval.cpp
@@ -126,17 +126,17 @@ class EvalScriptGuard
         script_ = script;
         script_->isActiveEval = true;
     }
 
     bool foundScript() {
         return !!script_;
     }
 
-    JSScript *script() const {
+    HandleScript script() {
         JS_ASSERT(script_);
         return script_;
     }
 };
 
 // Define subset of ExecuteType so that casting performs the injection.
 enum EvalType { DIRECT_EVAL = EXECUTE_DIRECT_EVAL, INDIRECT_EVAL = EXECUTE_INDIRECT_EVAL };
 
--- a/js/src/builtin/MapObject.cpp
+++ b/js/src/builtin/MapObject.cpp
@@ -1218,17 +1218,17 @@ SetIteratorObject::range()
 }
 
 bool
 GlobalObject::initSetIteratorProto(JSContext *cx, Handle<GlobalObject*> global)
 {
     JSObject *base = global->getOrCreateIteratorPrototype(cx);
     if (!base)
         return false;
-    JSObject *proto = NewObjectWithGivenProto(cx, &SetIteratorClass, base, global);
+    RootedObject proto(cx, NewObjectWithGivenProto(cx, &SetIteratorClass, base, global));
     if (!proto)
         return false;
     proto->setSlot(SetIteratorObject::RangeSlot, PrivateValue(NULL));
     if (!JS_DefineFunctions(cx, proto, SetIteratorObject::methods))
         return false;
     global->setReservedSlot(SET_ITERATOR_PROTO, ObjectValue(*proto));
     return true;
 }
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -331,51 +331,55 @@ InternalConst(JSContext *cx, unsigned ar
     return true;
 }
 
 #ifdef JS_GC_ZEAL
 static JSBool
 GCZeal(JSContext *cx, unsigned argc, jsval *vp)
 {
     uint32_t zeal, frequency = JS_DEFAULT_ZEAL_FREQ;
+    CallArgs args = CallArgsFromVp(argc, vp);
 
     if (argc > 2) {
-        ReportUsageError(cx, &JS_CALLEE(cx, vp).toObject(), "Too many arguments");
+        RootedObject callee(cx, &args.callee());
+        ReportUsageError(cx, callee, "Too many arguments");
         return JS_FALSE;
     }
-    if (!JS_ValueToECMAUint32(cx, argc < 1 ? JSVAL_VOID : vp[2], &zeal))
+    if (!JS_ValueToECMAUint32(cx, argc < 1 ? JSVAL_VOID : args[0], &zeal))
         return JS_FALSE;
     if (argc >= 2)
-        if (!JS_ValueToECMAUint32(cx, vp[3], &frequency))
+        if (!JS_ValueToECMAUint32(cx, args[1], &frequency))
             return JS_FALSE;
 
     JS_SetGCZeal(cx, (uint8_t)zeal, frequency);
     *vp = JSVAL_VOID;
     return JS_TRUE;
 }
 
 static JSBool
 ScheduleGC(JSContext *cx, unsigned argc, jsval *vp)
 {
+    CallArgs args = CallArgsFromVp(argc, vp);
+
     if (argc != 1) {
-        ReportUsageError(cx, &JS_CALLEE(cx, vp).toObject(), "Wrong number of arguments");
+        RootedObject callee(cx, &args.callee());
+        ReportUsageError(cx, callee, "Wrong number of arguments");
         return JS_FALSE;
     }
 
-    Value arg(vp[2]);
-    if (arg.isInt32()) {
+    if (args[0].isInt32()) {
         /* Schedule a GC to happen after |arg| allocations. */
-        JS_ScheduleGC(cx, arg.toInt32());
-    } else if (arg.isObject()) {
+        JS_ScheduleGC(cx, args[0].toInt32());
+    } else if (args[0].isObject()) {
         /* Ensure that |comp| is collected during the next GC. */
-        JSCompartment *comp = UnwrapObject(&arg.toObject())->compartment();
+        JSCompartment *comp = UnwrapObject(&args[0].toObject())->compartment();
         PrepareCompartmentForGC(comp);
-    } else if (arg.isString()) {
+    } else if (args[0].isString()) {
         /* This allows us to schedule atomsCompartment for GC. */
-        PrepareCompartmentForGC(arg.toString()->compartment());
+        PrepareCompartmentForGC(args[0].toString()->compartment());
     }
 
     *vp = JSVAL_VOID;
     return JS_TRUE;
 }
 
 static JSBool
 SelectForGC(JSContext *cx, unsigned argc, jsval *vp)
@@ -392,79 +396,91 @@ SelectForGC(JSContext *cx, unsigned argc
 
     *vp = JSVAL_VOID;
     return true;
 }
 
 static JSBool
 VerifyPreBarriers(JSContext *cx, unsigned argc, jsval *vp)
 {
+    CallArgs args = CallArgsFromVp(argc, vp);
+
     if (argc) {
-        ReportUsageError(cx, &JS_CALLEE(cx, vp).toObject(), "Too many arguments");
+        RootedObject callee(cx, &args.callee());
+        ReportUsageError(cx, callee, "Too many arguments");
         return JS_FALSE;
     }
     gc::VerifyBarriers(cx->runtime, gc::PreBarrierVerifier);
     *vp = JSVAL_VOID;
     return JS_TRUE;
 }
 
 static JSBool
 VerifyPostBarriers(JSContext *cx, unsigned argc, jsval *vp)
 {
     if (argc) {
-        ReportUsageError(cx, &JS_CALLEE(cx, vp).toObject(), "Too many arguments");
+        RootedObject callee(cx, &JS_CALLEE(cx, vp).toObject());
+        ReportUsageError(cx, callee, "Too many arguments");
         return JS_FALSE;
     }
     gc::VerifyBarriers(cx->runtime, gc::PostBarrierVerifier);
     *vp = JSVAL_VOID;
     return JS_TRUE;
 }
 
 static JSBool
 GCSlice(JSContext *cx, unsigned argc, jsval *vp)
 {
     bool limit = true;
     uint32_t budget = 0;
+    CallArgs args = CallArgsFromVp(argc, vp);
 
     if (argc > 1) {
-        ReportUsageError(cx, &JS_CALLEE(cx, vp).toObject(), "Wrong number of arguments");
+        RootedObject callee(cx, &args.callee());
+        ReportUsageError(cx, callee, "Wrong number of arguments");
         return JS_FALSE;
     }
 
     if (argc == 1) {
-        if (!JS_ValueToECMAUint32(cx, vp[2], &budget))
+        if (!JS_ValueToECMAUint32(cx, args[0], &budget))
             return false;
     } else {
         limit = false;
     }
 
     GCDebugSlice(cx->runtime, limit, budget);
     *vp = JSVAL_VOID;
     return JS_TRUE;
 }
 
 static JSBool
 GCPreserveCode(JSContext *cx, unsigned argc, jsval *vp)
 {
+    CallArgs args = CallArgsFromVp(argc, vp);
+
     if (argc != 0) {
-        ReportUsageError(cx, &JS_CALLEE(cx, vp).toObject(), "Wrong number of arguments");
+        RootedObject callee(cx, &args.callee());
+        ReportUsageError(cx, callee, "Wrong number of arguments");
         return JS_FALSE;
     }
 
     cx->runtime->alwaysPreserveCode = true;
 
     *vp = JSVAL_VOID;
     return JS_TRUE;
 }
 
 static JSBool
 DeterministicGC(JSContext *cx, unsigned argc, jsval *vp)
 {
+    CallArgs args = CallArgsFromVp(argc, vp);
+
     if (argc != 1) {
-        ReportUsageError(cx, &JS_CALLEE(cx, vp).toObject(), "Wrong number of arguments");
+        RootedObject callee(cx, &args.callee());
+        ReportUsageError(cx, callee, "Wrong number of arguments");
         return JS_FALSE;
     }
 
     gc::SetDeterministicGC(cx, ToBoolean(vp[2]));
     *vp = JSVAL_VOID;
     return JS_TRUE;
 }
 #endif /* JS_GC_ZEAL */
@@ -637,17 +653,17 @@ static JSClass FinalizeCounterClass = {
     JS_ResolveStub,
     JS_ConvertStub,
     finalize_counter_finalize
 };
 
 static JSBool
 MakeFinalizeObserver(JSContext *cx, unsigned argc, jsval *vp)
 {
-    JSObject *scope = JS_GetGlobalForScopeChain(cx);
+    RootedObject scope(cx, JS_GetGlobalForScopeChain(cx));
     if (!scope)
         return false;
 
     JSObject *obj = JS_NewObjectWithGivenProto(cx, &FinalizeCounterClass, NULL, scope);
     if (!obj)
         return false;
 
     *vp = OBJECT_TO_JSVAL(obj);
@@ -659,28 +675,31 @@ FinalizeCount(JSContext *cx, unsigned ar
 {
     *vp = INT_TO_JSVAL(finalizeCount);
     return true;
 }
 
 JSBool
 MJitChunkLimit(JSContext *cx, unsigned argc, jsval *vp)
 {
+    CallArgs args = CallArgsFromVp(argc, vp);
+
     if (argc != 1) {
-        ReportUsageError(cx, &JS_CALLEE(cx, vp).toObject(), "Wrong number of arguments");
+        RootedObject callee(cx, &args.callee());
+        ReportUsageError(cx, callee, "Wrong number of arguments");
         return JS_FALSE;
     }
 
     if (cx->runtime->alwaysPreserveCode) {
         JS_ReportError(cx, "Can't change chunk limit after gcPreserveCode()");
         return JS_FALSE;
     }
 
     double t;
-    if (!JS_ValueToNumber(cx, JS_ARGV(cx, vp)[0], &t))
+    if (!JS_ValueToNumber(cx, args[0], &t))
         return JS_FALSE;
 
 #ifdef JS_METHODJIT
     mjit::SetChunkLimit((uint32_t) t);
 #endif
 
     // Clear out analysis information which might refer to code compiled with
     // the previous chunk limit.
@@ -695,31 +714,31 @@ Terminate(JSContext *cx, unsigned arg, j
 {
     JS_ClearPendingException(cx);
     return JS_FALSE;
 }
 
 static JSBool
 EnableSPSProfilingAssertions(JSContext *cx, unsigned argc, jsval *vp)
 {
-    jsval arg = JS_ARGV(cx, vp)[0];
-    if (argc == 0 || !JSVAL_IS_BOOLEAN(arg)) {
-        ReportUsageError(cx, &JS_CALLEE(cx, vp).toObject(),
-                         "Must have one boolean argument");
+    CallArgs args = CallArgsFromVp(argc, vp);
+    if (argc == 0 || !args[0].isBoolean()) {
+        RootedObject arg(cx, &args.callee());
+        ReportUsageError(cx, arg, "Must have one boolean argument");
         return false;
     }
 
     static ProfileEntry stack[1000];
     static uint32_t stack_size = 0;
 
-    if (JSVAL_TO_BOOLEAN(arg))
+    if (args[0].toBoolean())
         SetRuntimeProfilingStack(cx->runtime, stack, &stack_size, 1000);
     else
         SetRuntimeProfilingStack(cx->runtime, NULL, NULL, 0);
-    cx->runtime->spsProfiler.enableSlowAssertions(JSVAL_TO_BOOLEAN(arg));
+    cx->runtime->spsProfiler.enableSlowAssertions(args[0].toBoolean());
 
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return true;
 }
 
 static JSFunctionSpecWithHelp TestingFunctions[] = {
     JS_FN_HELP("gc", ::GC, 0, 0,
 "gc([obj] | 'compartment')",
@@ -827,14 +846,14 @@ static JSFunctionSpecWithHelp TestingFun
 "  expensive, so it shouldn't be enabled normally."),
 
     JS_FS_END
 };
 
 namespace js {
 
 bool
-DefineTestingFunctions(JSContext *cx, JSObject *obj)
+DefineTestingFunctions(JSContext *cx, HandleObject obj)
 {
     return JS_DefineFunctionsWithHelp(cx, obj, TestingFunctions);
 }
 
 } /* namespace js */
--- a/js/src/builtin/TestingFunctions.h
+++ b/js/src/builtin/TestingFunctions.h
@@ -4,13 +4,13 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef TestingFunctions_h__
 #define TestingFunctions_h__
 
 namespace js {
 
 bool
-DefineTestingFunctions(JSContext *cx, JSObject *obj);
+DefineTestingFunctions(JSContext *cx, JSHandleObject obj);
 
 } /* namespace js */
 
 #endif /* TestingFunctions_h__ */
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -284,17 +284,17 @@ namespace CDataFinalizer {
   static bool GetValue(JSContext *cx, JSObject *obj, jsval *result);
 
   static JSObject* GetCData(JSContext *cx, JSObject *obj);
  }
 
 
 // Int64Base provides functions common to Int64 and UInt64.
 namespace Int64Base {
-  JSObject* Construct(JSContext* cx, JSObject* proto, uint64_t data,
+  JSObject* Construct(JSContext* cx, HandleObject proto, uint64_t data,
     bool isUnsigned);
 
   uint64_t GetInt(JSObject* obj);
 
   JSBool ToString(JSContext* cx, JSObject* obj, unsigned argc, jsval* vp,
     bool isUnsigned);
 
   JSBool ToSource(JSContext* cx, JSObject* obj, unsigned argc, jsval* vp,
@@ -703,17 +703,17 @@ static JSObject*
 InitCTypeClass(JSContext* cx, HandleObject parent)
 {
   JSFunction *fun = JS_DefineFunction(cx, parent, "CType", ConstructAbstract, 0,
                                       CTYPESCTOR_FLAGS);
   if (!fun)
     return NULL;
 
   RootedObject ctor(cx, JS_GetFunctionObject(fun));
-  JSObject *fnproto = JS_GetPrototype(ctor);
+  RootedObject fnproto(cx, JS_GetPrototype(ctor));
   JS_ASSERT(ctor);
   JS_ASSERT(fnproto);
 
   // Set up ctypes.CType.prototype.
   RootedObject prototype(cx, JS_NewObject(cx, &sCTypeProtoClass, fnproto, parent));
   if (!prototype)
     return NULL;
 
@@ -793,20 +793,20 @@ InitCDataClass(JSContext* cx, HandleObje
   return prototype;
 }
 
 static JSBool
 DefineABIConstant(JSContext* cx,
                   HandleObject parent,
                   const char* name,
                   ABICode code,
-                  JSObject* prototype)
-{
-  JSObject* obj = JS_DefineObject(cx, parent, name, &sCABIClass, prototype,
-                    JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
+                  HandleObject prototype)
+{
+  RootedObject obj(cx, JS_DefineObject(cx, parent, name, &sCABIClass, prototype,
+                                       JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT));
   if (!obj)
     return false;
   JS_SetReservedSlot(obj, SLOT_ABICODE, INT_TO_JSVAL(code));
   return JS_FreezeObject(cx, obj);
 }
 
 // Set up a single type constructor for
 // ctypes.{Pointer,Array,Struct,Function}Type.
@@ -815,30 +815,30 @@ InitTypeConstructor(JSContext* cx,
                     HandleObject parent,
                     HandleObject CTypeProto,
                     HandleObject CDataProto,
                     JSFunctionSpec spec,
                     JSFunctionSpec* fns,
                     JSPropertySpec* props,
                     JSFunctionSpec* instanceFns,
                     JSPropertySpec* instanceProps,
-                    JSObject*& typeProto,
-                    JSObject*& dataProto)
+                    MutableHandleObject typeProto,
+                    MutableHandleObject dataProto)
 {
   JSFunction* fun = js::DefineFunctionWithReserved(cx, parent, spec.name, spec.call, 
                       spec.nargs, spec.flags);
   if (!fun)
     return false;
 
   RootedObject obj(cx, JS_GetFunctionObject(fun));
   if (!obj)
     return false;
 
   // Set up the .prototype and .prototype.constructor properties.
-  typeProto = JS_NewObject(cx, &sCTypeProtoClass, CTypeProto, parent);
+  typeProto.set(JS_NewObject(cx, &sCTypeProtoClass, CTypeProto, parent));
   if (!typeProto)
     return false;
 
   // Define property before proceeding, for GC safety.
   if (!JS_DefineProperty(cx, obj, "prototype", OBJECT_TO_JSVAL(typeProto),
          NULL, NULL, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT))
     return false;
 
@@ -855,20 +855,19 @@ InitTypeConstructor(JSContext* cx,
   // Stash ctypes.{Pointer,Array,Struct}Type.prototype on a reserved slot of
   // the type constructor, for faster lookup.
   js::SetFunctionNativeReserved(obj, SLOT_FN_CTORPROTO, OBJECT_TO_JSVAL(typeProto));
 
   // Create an object to serve as the common ancestor for all CData objects
   // created from the given type constructor. This has ctypes.CData.prototype
   // as its prototype, such that it inherits the properties and functions
   // common to all CDatas.
-  dataProto = JS_NewObject(cx, &sCDataProtoClass, CDataProto, parent);
+  dataProto.set(JS_NewObject(cx, &sCDataProtoClass, CDataProto, parent));
   if (!dataProto)
     return false;
-  js::AutoObjectRooter protoroot(cx, dataProto);
 
   // Define functions and properties on the 'dataProto' object that are common
   // to all CData objects created from this type constructor. (These will
   // become functions and properties on CData objects created from this type.)
   if (instanceFns && !JS_DefineFunctions(cx, dataProto, instanceFns))
     return false;
 
   if (instanceProps && !JS_DefineProperties(cx, dataProto, instanceProps))
@@ -997,34 +996,34 @@ InitTypeClasses(JSContext* cx, HandleObj
   //     * [[Class]] "CDataProto"
   //     * __proto__ === 'p', the prototype object from above
   //     * 'constructor' property === 't'
   AutoObjectVector protos(cx);
   protos.resize(CTYPEPROTO_SLOTS);
   if (!InitTypeConstructor(cx, parent, CTypeProto, CDataProto,
          sPointerFunction, NULL, sPointerProps,
          sPointerInstanceFunctions, sPointerInstanceProps,
-         protos[SLOT_POINTERPROTO], protos[SLOT_POINTERDATAPROTO]))
+         protos.handleAt(SLOT_POINTERPROTO), protos.handleAt(SLOT_POINTERDATAPROTO)))
     return false;
 
   if (!InitTypeConstructor(cx, parent, CTypeProto, CDataProto,
          sArrayFunction, NULL, sArrayProps,
          sArrayInstanceFunctions, sArrayInstanceProps,
-         protos[SLOT_ARRAYPROTO], protos[SLOT_ARRAYDATAPROTO]))
+         protos.handleAt(SLOT_ARRAYPROTO), protos.handleAt(SLOT_ARRAYDATAPROTO)))
     return false;
 
   if (!InitTypeConstructor(cx, parent, CTypeProto, CDataProto,
          sStructFunction, sStructFunctions, sStructProps,
          sStructInstanceFunctions, NULL,
-         protos[SLOT_STRUCTPROTO], protos[SLOT_STRUCTDATAPROTO]))
+         protos.handleAt(SLOT_STRUCTPROTO), protos.handleAt(SLOT_STRUCTDATAPROTO)))
     return false;
 
   if (!InitTypeConstructor(cx, parent, CTypeProto, protos.handleAt(SLOT_POINTERDATAPROTO),
          sFunctionFunction, NULL, sFunctionProps, sFunctionInstanceFunctions, NULL,
-         protos[SLOT_FUNCTIONPROTO], protos[SLOT_FUNCTIONDATAPROTO]))
+         protos.handleAt(SLOT_FUNCTIONPROTO), protos.handleAt(SLOT_FUNCTIONDATAPROTO)))
     return false;
 
   protos[SLOT_CDATAPROTO] = CDataProto;
 
   // Create and attach the ctypes.{Int64,UInt64} constructors.
   // Each of these has, respectively:
   //   * [[Class]] "Function"
   //   * __proto__ === Function.prototype
@@ -1086,19 +1085,19 @@ InitTypeClasses(JSContext* cx, HandleObj
   // Alias 'ctypes.unsigned' as 'ctypes.unsigned_int', since they represent
   // the same type in C.
   if (!JS_DefineProperty(cx, parent, "unsigned",
          OBJECT_TO_JSVAL(typeObj_unsigned_int), NULL, NULL,
          JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT))
     return false;
 
   // Create objects representing the special types void_t and voidptr_t.
-  JSObject *typeObj =
+  RootedObject typeObj(cx,
     CType::DefineBuiltin(cx, parent, "void_t", CTypeProto, CDataProto, "void",
-                         TYPE_void_t, JSVAL_VOID, JSVAL_VOID, &ffi_type_void);
+                         TYPE_void_t, JSVAL_VOID, JSVAL_VOID, &ffi_type_void));
   if (!typeObj)
     return false;
 
   typeObj = PointerType::CreateInternal(cx, typeObj);
   if (!typeObj)
     return false;
   if (!JS_DefineProperty(cx, parent, "voidptr_t", OBJECT_TO_JSVAL(typeObj),
          NULL, NULL, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT))
@@ -1124,60 +1123,61 @@ GetCallbacks(JSObject* obj)
     return NULL;
 
   return static_cast<JSCTypesCallbacks*>(JSVAL_TO_PRIVATE(result));
 }
 
 // Utility function to access a property of an object as an object
 // returns false and sets the error if the property does not exist
 // or is not an object
-bool GetObjectProperty(JSContext *cx, JSObject *obj,
-                       const char *property, JSObject **result)
+bool GetObjectProperty(JSContext *cx, HandleObject obj,
+                       const char *property, MutableHandleObject result)
 {
   jsval val;
   if (!JS_GetProperty(cx, obj, property, &val)) {
     return false;
   }
 
   if (JSVAL_IS_PRIMITIVE(val)) {
     JS_ReportError(cx, "missing or non-object field");
     return false;
   }
 
-  *result = JSVAL_TO_OBJECT(val);
+  result.set(JSVAL_TO_OBJECT(val));
   return true;
 }
 
 JS_BEGIN_EXTERN_C
 
 JS_PUBLIC_API(JSBool)
-JS_InitCTypesClass(JSContext* cx, JSObject* global_)
-{
+JS_InitCTypesClass(JSContext* cx, JSObject *globalArg)
+{
+  RootedObject global(cx, globalArg);
+
   // attach ctypes property to global object
-  RootedObject global(cx, global_);
   RootedObject ctypes(cx, JS_NewObject(cx, &sCTypesGlobalClass, NULL, NULL));
   if (!ctypes)
     return false;
 
   if (!JS_DefineProperty(cx, global, "ctypes", OBJECT_TO_JSVAL(ctypes),
-         JS_PropertyStub, JS_StrictPropertyStub, JSPROP_READONLY | JSPROP_PERMANENT)) {
+         JS_PropertyStub, JS_StrictPropertyStub, JSPROP_READONLY | JSPROP_PERMANENT)){
     return false;
   }
 
   if (!InitTypeClasses(cx, ctypes))
     return false;
 
   // attach API functions and properties
   if (!JS_DefineFunctions(cx, ctypes, sModuleFunctions) ||
       !JS_DefineProperties(cx, ctypes, sModuleProps))
     return false;
 
   // Set up ctypes.CDataFinalizer.prototype.
   RootedObject ctor(cx);
-  if (!GetObjectProperty(cx, ctypes, "CDataFinalizer", ctor.address()))
+  if (!GetObjectProperty(cx, ctypes, "CDataFinalizer", &ctor))
     return false;
 
   RootedObject prototype(cx, JS_NewObject(cx, &sCDataFinalizerProtoClass, NULL, ctypes));
   if (!prototype)
     return false;
 
   if (!JS_DefineProperties(cx, prototype, sCDataFinalizerProps) ||
       !JS_DefineFunctions(cx, prototype, sCDataFinalizerFunctions))
@@ -1192,18 +1192,17 @@ JS_InitCTypesClass(JSContext* cx, JSObje
     return false;
 
 
   // Seal the ctypes object, to prevent modification.
   return JS_FreezeObject(cx, ctypes);
 }
 
 JS_PUBLIC_API(void)
-JS_SetCTypesCallbacks(JSObject* ctypesObj,
-                      JSCTypesCallbacks* callbacks)
+JS_SetCTypesCallbacks(JSRawObject ctypesObj, JSCTypesCallbacks* callbacks)
 {
   JS_ASSERT(callbacks);
   JS_ASSERT(IsCTypesGlobal(ctypesObj));
 
   // Set the callbacks on a reserved slot.
   JS_SetReservedSlot(ctypesObj, SLOT_CALLBACKS, PRIVATE_TO_JSVAL(callbacks));
 }
 
@@ -1877,18 +1876,18 @@ strnlen(const CharType* begin, size_t ma
 //   object. Otherwise:
 // * If a CData object 'parentObj' is supplied, the new CData object is
 //   dependent on the given parent and its buffer refers to a slice of the
 //   parent's buffer.
 // * If 'parentObj' is null, the new CData object may or may not own its
 //   resulting buffer depending on the 'ownResult' argument.
 JSBool
 ConvertToJS(JSContext* cx,
-            JSObject* typeObj,
-            JSObject* parentObj,
+            HandleObject typeObj,
+            HandleObject parentObj,
             void* data,
             bool wantPrimitive,
             bool ownResult,
             jsval* result)
 {
   JS_ASSERT(!parentObj || CData::IsCData(parentObj));
   JS_ASSERT(!parentObj || !ownResult);
   JS_ASSERT(!wantPrimitive || !ownResult);
@@ -1910,17 +1909,17 @@ ConvertToJS(JSContext* cx,
     else if (!JS_NewNumberValue(cx, double(value), result))                    \
       return false;                                                            \
     break;                                                                     \
   }
 #define DEFINE_WRAPPED_INT_TYPE(name, type, ffiType)                           \
   case TYPE_##name: {                                                          \
     /* Return an Int64 or UInt64 object - do not convert to a JS number. */    \
     uint64_t value;                                                            \
-    JSObject* proto;                                                           \
+    RootedObject proto(cx);                                                    \
     if (!numeric_limits<type>::is_signed) {                                    \
       value = *static_cast<type*>(data);                                       \
       /* Get ctypes.UInt64.prototype from ctypes.CType.prototype. */           \
       proto = CType::GetProtoFromType(typeObj, SLOT_UINT64PROTO);              \
     } else {                                                                   \
       value = int64_t(*static_cast<type*>(data));                              \
       /* Get ctypes.Int64.prototype from ctypes.CType.prototype. */            \
       proto = CType::GetProtoFromType(typeObj, SLOT_INT64PROTO);               \
@@ -2000,30 +1999,32 @@ ImplicitConvert(JSContext* cx,
                 bool* freePointer)
 {
   JS_ASSERT(CType::IsSizeDefined(targetType));
 
   // First, check if val is either a CData object or a CDataFinalizer
   // of type targetType.
   JSObject* sourceData = NULL;
   JSObject* sourceType = NULL;
+  RootedObject valObj(cx, NULL);
   if (!JSVAL_IS_PRIMITIVE(val)) {
-    if (CData::IsCData(JSVAL_TO_OBJECT(val))) {
-      sourceData = JSVAL_TO_OBJECT(val);
+    valObj = JSVAL_TO_OBJECT(val);
+    if (CData::IsCData(valObj)) {
+      sourceData = valObj;
       sourceType = CData::GetCType(sourceData);
 
       // If the types are equal, copy the buffer contained within the CData.
       // (Note that the buffers may overlap partially or completely.)
       if (CType::TypesEqual(sourceType, targetType)) {
         size_t size = CType::GetSize(sourceType);
         memmove(buffer, CData::GetData(sourceData), size);
         return true;
       }
-    } else if (CDataFinalizer::IsCDataFinalizer(JSVAL_TO_OBJECT(val))) {
-      sourceData = JSVAL_TO_OBJECT(val);
+    } else if (CDataFinalizer::IsCDataFinalizer(valObj)) {
+      sourceData = valObj;
       sourceType = CDataFinalizer::GetCType(cx, sourceData);
 
       CDataFinalizer::Private *p = (CDataFinalizer::Private *)
         JS_GetPrivate(sourceData);
 
       if (!p) {
         // We have called |dispose| or |forget| already.
         JS_ReportError(cx, "Attempting to convert an empty CDataFinalizer");
@@ -2166,23 +2167,21 @@ ImplicitConvert(JSContext* cx,
         memcpy(*jscharBuffer, sourceChars, sourceLength * sizeof(jschar));
         (*jscharBuffer)[sourceLength] = 0;
         break;
       }
       default:
         return TypeError(cx, "string pointer", val);
       }
       break;
-    } else if (!JSVAL_IS_PRIMITIVE(val) &&
-               JS_IsArrayBufferObject(JSVAL_TO_OBJECT(val), cx)) {
+    } else if (!JSVAL_IS_PRIMITIVE(val) && JS_IsArrayBufferObject(valObj, cx)) {
       // Convert ArrayBuffer to pointer without any copy.
       // Just as with C arrays, we make no effort to
       // keep the ArrayBuffer alive.
-      JSObject *sourceBuffer = JSVAL_TO_OBJECT(val);
-      *static_cast<void**>(buffer) = JS_GetArrayBufferData(sourceBuffer, cx);
+      *static_cast<void**>(buffer) = JS_GetArrayBufferData(valObj, cx);
       break;
     }
     return TypeError(cx, "pointer", val);
   }
   case TYPE_array: {
     JSObject* baseType = ArrayType::GetBaseType(targetType);
     size_t targetLength = ArrayType::GetLength(targetType);
 
@@ -2230,78 +2229,74 @@ ImplicitConvert(JSContext* cx,
           static_cast<jschar*>(buffer)[sourceLength] = 0;
 
         break;
       }
       default:
         return TypeError(cx, "array", val);
       }
 
-    } else if (!JSVAL_IS_PRIMITIVE(val) &&
-               JS_IsArrayObject(cx, JSVAL_TO_OBJECT(val))) {
+    } else if (!JSVAL_IS_PRIMITIVE(val) && JS_IsArrayObject(cx, valObj)) {
       // Convert each element of the array by calling ImplicitConvert.
-      RootedObject sourceArray(cx, JSVAL_TO_OBJECT(val));
       uint32_t sourceLength;
-      if (!JS_GetArrayLength(cx, sourceArray, &sourceLength) ||
+      if (!JS_GetArrayLength(cx, valObj, &sourceLength) ||
           targetLength != size_t(sourceLength)) {
         JS_ReportError(cx, "ArrayType length does not match source array length");
         return false;
       }
 
       // Convert into an intermediate, in case of failure.
       size_t elementSize = CType::GetSize(baseType);
       size_t arraySize = elementSize * targetLength;
       AutoPtr<char>::Array intermediate(cx->array_new<char>(arraySize));
       if (!intermediate) {
         JS_ReportAllocationOverflow(cx);
         return false;
       }
 
       for (uint32_t i = 0; i < sourceLength; ++i) {
         js::AutoValueRooter item(cx);
-        if (!JS_GetElement(cx, sourceArray, i, item.jsval_addr()))
+        if (!JS_GetElement(cx, valObj, i, item.jsval_addr()))
           return false;
 
         char* data = intermediate.get() + elementSize * i;
         if (!ImplicitConvert(cx, item.jsval_value(), baseType, data, false, NULL))
           return false;
       }
 
       memcpy(buffer, intermediate.get(), arraySize);
 
     } else if (!JSVAL_IS_PRIMITIVE(val) &&
-               JS_IsArrayBufferObject(JSVAL_TO_OBJECT(val), cx)) {
+               JS_IsArrayBufferObject(valObj, cx)) {
       // Check that array is consistent with type, then
       // copy the array. As with C arrays, data is *not*
       // copied back to the ArrayBuffer at the end of a
       // function call, so do not expect this to work
       // as an inout argument.
-      JSObject *sourceArrayBuffer = JSVAL_TO_OBJECT(val);
-      uint32_t sourceLength = JS_GetArrayBufferByteLength(sourceArrayBuffer, cx);
+      uint32_t sourceLength = JS_GetArrayBufferByteLength(valObj, cx);
       size_t elementSize = CType::GetSize(baseType);
       size_t arraySize = elementSize * targetLength;
       if (arraySize != size_t(sourceLength)) {
         JS_ReportError(cx, "ArrayType length does not match source array length");
         return false;
       }
-      memcpy(buffer, JS_GetArrayBufferData(sourceArrayBuffer, cx), sourceLength);
+      memcpy(buffer, JS_GetArrayBufferData(valObj, cx), sourceLength);
       break;
     } else {
       // Don't implicitly convert to string. Users can implicitly convert
       // with `String(x)` or `""+x`.
       return TypeError(cx, "array", val);
     }
     break;
   }
   case TYPE_struct: {
     if (!JSVAL_IS_PRIMITIVE(val) && !sourceData) {
       // Enumerate the properties of the object; if they match the struct
       // specification, convert the fields.
-      RootedObject obj(cx, JSVAL_TO_OBJECT(val));
-      RootedObject iter(cx, JS_NewPropertyIterator(cx, obj));
+      RootedObject iter(cx, JS_NewPropertyIterator(cx, valObj));
       if (!iter)
         return false;
 
       // Convert into an intermediate, in case of failure.
       size_t structSize = CType::GetSize(targetType);
       AutoPtr<char>::Array intermediate(cx->array_new<char>(structSize));
       if (!intermediate) {
         JS_ReportAllocationOverflow(cx);
@@ -2322,17 +2317,17 @@ ImplicitConvert(JSContext* cx,
         }
 
         JSFlatString *name = JSID_TO_FLAT_STRING(id);
         const FieldInfo* field = StructType::LookupField(cx, targetType, name);
         if (!field)
           return false;
 
         js::AutoValueRooter prop(cx);
-        if (!JS_GetPropertyById(cx, obj, id, prop.jsval_addr()))
+        if (!JS_GetPropertyById(cx, valObj, id, prop.jsval_addr()))
           return false;
 
         // Convert the field via ImplicitConvert().
         char* fieldData = intermediate.get() + field->mOffset;
         if (!ImplicitConvert(cx, prop.jsval_value(), field->mType, fieldData, false, NULL))
           return false;
 
         ++i;
@@ -2909,40 +2904,39 @@ CType::ConstructBasic(JSContext* cx,
                       jsval* vp)
 {
   if (argc > 1) {
     JS_ReportError(cx, "CType constructor takes zero or one argument");
     return JS_FALSE;
   }
 
   // construct a CData object
-  RootedObject result(cx, CData::Create(cx, obj, NULL, NULL, true));
+  RootedObject result(cx, CData::Create(cx, obj, NullPtr(), NULL, true));
   if (!result)
     return JS_FALSE;
 
   if (argc == 1) {
     if (!ExplicitConvert(cx, JS_ARGV(cx, vp)[0], obj, CData::GetData(result)))
       return JS_FALSE;
   }
 
   JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(result));
   return JS_TRUE;
 }
 
 JSObject*
 CType::Create(JSContext* cx,
-              JSObject* typeProto,
-              JSObject* dataProto_,
+              HandleObject typeProto,
+              HandleObject dataProto,
               TypeCode type,
               JSString* name_,
               jsval size,
               jsval align,
               ffi_type* ffiType)
 {
-  RootedObject dataProto(cx, dataProto_);
   RootedString name(cx, name_);
   RootedObject parent(cx, JS_GetParent(typeProto));
   JS_ASSERT(parent);
 
   // Create a CType object with the properties and slots common to all CTypes.
   // Each type object 't' has:
   //   * [[Class]] "CType"
   //   * __proto__ === 'typeProto'; one of ctypes.{CType,PointerType,ArrayType,
@@ -3426,17 +3420,17 @@ CType::PtrGetter(JSContext* cx, JSHandle
 
   vp.set(OBJECT_TO_JSVAL(pointerType));
   return JS_TRUE;
 }
 
 JSBool
 CType::CreateArray(JSContext* cx, unsigned argc, jsval* vp)
 {
-  JSObject* baseType = JS_THIS_OBJECT(cx, vp);
+  RootedObject baseType(cx, JS_THIS_OBJECT(cx, vp));
   if (!baseType)
     return JS_FALSE;
   if (!CType::IsCType(baseType)) {
     JS_ReportError(cx, "not a CType");
     return JS_FALSE;
   }
 
   // Construct and return a new ArrayType object.
@@ -3619,45 +3613,44 @@ PointerType::Create(JSContext* cx, unsig
 {
   // Construct and return a new PointerType object.
   if (argc != 1) {
     JS_ReportError(cx, "PointerType takes one argument");
     return JS_FALSE;
   }
 
   jsval arg = JS_ARGV(cx, vp)[0];
-  if (JSVAL_IS_PRIMITIVE(arg) || !CType::IsCType(JSVAL_TO_OBJECT(arg))) {
+  RootedObject obj(cx);
+  if (JSVAL_IS_PRIMITIVE(arg) || !CType::IsCType(obj = JSVAL_TO_OBJECT(arg))) {
     JS_ReportError(cx, "first argument must be a CType");
     return JS_FALSE;
   }
 
-  JSObject* result = CreateInternal(cx, JSVAL_TO_OBJECT(arg));
+  JSObject* result = CreateInternal(cx, obj);
   if (!result)
     return JS_FALSE;
 
   JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(result));
   return JS_TRUE;
 }
 
 JSObject*
-PointerType::CreateInternal(JSContext* cx, JSObject* baseType_)
-{
-  RootedObject baseType(cx, baseType_);
-
+PointerType::CreateInternal(JSContext* cx, HandleObject baseType)
+{
   // check if we have a cached PointerType on our base CType.
   jsval slot = JS_GetReservedSlot(baseType, SLOT_PTR);
   if (!JSVAL_IS_VOID(slot))
     return JSVAL_TO_OBJECT(slot);
 
   // Get ctypes.PointerType.prototype and the common prototype for CData objects
   // of this type, or ctypes.FunctionType.prototype for function pointers.
   CTypeProtoSlot slotId = CType::GetTypeCode(baseType) == TYPE_function ?
     SLOT_FUNCTIONDATAPROTO : SLOT_POINTERDATAPROTO;
-  JSObject* dataProto = CType::GetProtoFromType(baseType, slotId);
-  JSObject* typeProto = CType::GetProtoFromType(baseType, SLOT_POINTERPROTO);
+  RootedObject dataProto(cx, CType::GetProtoFromType(baseType, slotId));
+  RootedObject typeProto(cx, CType::GetProtoFromType(baseType, SLOT_POINTERPROTO));
 
   // Create a new CType object with the common properties and slots.
   JSObject* typeObj = CType::Create(cx, typeProto, dataProto, TYPE_pointer,
                         NULL, INT_TO_JSVAL(sizeof(void*)),
                         INT_TO_JSVAL(ffi_type_pointer.alignment),
                         &ffi_type_pointer);
   if (!typeObj)
     return NULL;
@@ -3682,17 +3675,17 @@ PointerType::ConstructData(JSContext* cx
     return JS_FALSE;
   }
 
   if (argc > 3) {
     JS_ReportError(cx, "constructor takes 0, 1, 2, or 3 arguments");
     return JS_FALSE;
   }
 
-  RootedObject result(cx, CData::Create(cx, obj, NULL, NULL, true));
+  RootedObject result(cx, CData::Create(cx, obj, NullPtr(), NULL, true));
   if (!result)
     return JS_FALSE;
 
   // Set return value early, must not observe *vp after
   JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(result));
 
   // There are 3 things that we might be creating here:
   // 1 - A null pointer (no arguments)
@@ -3811,34 +3804,34 @@ PointerType::OffsetBy(JSContext* cx, int
   JSObject* obj = JS_THIS_OBJECT(cx, vp);
   if (!obj)
     return JS_FALSE;
   if (!CData::IsCData(obj)) {
     JS_ReportError(cx, "not a CData");
     return JS_FALSE;
   }
 
-  JSObject* typeObj = CData::GetCType(obj);
+  RootedObject typeObj(cx, CData::GetCType(obj));
   if (CType::GetTypeCode(typeObj) != TYPE_pointer) {
     JS_ReportError(cx, "not a PointerType");
     return JS_FALSE;
   }
 
-  JSObject* baseType = PointerType::GetBaseType(typeObj);
+  RootedObject baseType(cx, PointerType::GetBaseType(typeObj));
   if (!CType::IsSizeDefined(baseType)) {
     JS_ReportError(cx, "cannot modify pointer of undefined size");
     return JS_FALSE;
   }
 
   size_t elementSize = CType::GetSize(baseType);
   char* data = static_cast<char*>(*static_cast<void**>(CData::GetData(obj)));
   void* address = data + offset * elementSize;
 
   // Create a PointerType CData object containing the new address.
-  JSObject* result = CData::Create(cx, typeObj, NULL, &address, true);
+  JSObject* result = CData::Create(cx, typeObj, NullPtr(), &address, true);
   if (!result)
     return JS_FALSE;
 
   JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(result));
   return JS_TRUE;
 }
 
 JSBool
@@ -3866,30 +3859,30 @@ PointerType::ContentsGetter(JSContext* c
 
   // Get pointer type and base type.
   JSObject* typeObj = CData::GetCType(obj);
   if (CType::GetTypeCode(typeObj) != TYPE_pointer) {
     JS_ReportError(cx, "not a PointerType");
     return JS_FALSE;
   }
 
-  JSObject* baseType = GetBaseType(typeObj);
+  RootedObject baseType(cx, GetBaseType(typeObj));
   if (!CType::IsSizeDefined(baseType)) {
     JS_ReportError(cx, "cannot get contents of undefined size");
     return JS_FALSE;
   }
 
   void* data = *static_cast<void**>(CData::GetData(obj));
   if (data == NULL) {
     JS_ReportError(cx, "cannot read contents of null pointer");
     return JS_FALSE;
   }
 
   jsval result;
-  if (!ConvertToJS(cx, baseType, NULL, data, false, false, &result))
+  if (!ConvertToJS(cx, baseType, NullPtr(), data, false, false, &result))
     return JS_FALSE;
 
   JS_SET_RVAL(cx, vp.address(), result);
   return JS_TRUE;
 }
 
 JSBool
 PointerType::ContentsSetter(JSContext* cx,
@@ -3947,37 +3940,35 @@ ArrayType::Create(JSContext* cx, unsigne
 
   // Convert the length argument to a size_t.
   size_t length = 0;
   if (argc == 2 && !jsvalToSize(cx, argv[1], false, &length)) {
     JS_ReportError(cx, "second argument must be a nonnegative integer");
     return JS_FALSE;
   }
 
-  JSObject* baseType = JSVAL_TO_OBJECT(argv[0]);
+  RootedObject baseType(cx, JSVAL_TO_OBJECT(argv[0]));
   JSObject* result = CreateInternal(cx, baseType, length, argc == 2);
   if (!result)
     return JS_FALSE;
 
   JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(result));
   return JS_TRUE;
 }
 
 JSObject*
 ArrayType::CreateInternal(JSContext* cx,
-                          JSObject* baseType_,
+                          HandleObject baseType,
                           size_t length,
                           bool lengthDefined)
 {
-  RootedObject baseType(cx, baseType_);
-
   // Get ctypes.ArrayType.prototype and the common prototype for CData objects
   // of this type, from ctypes.CType.prototype.
-  JSObject* typeProto = CType::GetProtoFromType(baseType, SLOT_ARRAYPROTO);
-  JSObject* dataProto = CType::GetProtoFromType(baseType, SLOT_ARRAYDATAPROTO);
+  RootedObject typeProto(cx, CType::GetProtoFromType(baseType, SLOT_ARRAYPROTO));
+  RootedObject dataProto(cx, CType::GetProtoFromType(baseType, SLOT_ARRAYDATAPROTO));
 
   // Determine the size of the array from the base type, if possible.
   // The size of the base type must be defined.
   // If our length is undefined, both our size and length will be undefined.
   size_t baseSize;
   if (!CType::GetSafeSize(baseType, &baseSize)) {
     JS_ReportError(cx, "base size must be defined");
     return NULL;
@@ -4015,16 +4006,17 @@ ArrayType::CreateInternal(JSContext* cx,
 }
 
 JSBool
 ArrayType::ConstructData(JSContext* cx,
                          JSHandleObject obj_,
                          unsigned argc,
                          jsval* vp)
 {
+  CallArgs args = CallArgsFromVp(argc, vp);
   RootedObject obj(cx, obj_); // Make a mutable version
 
   if (!CType::IsCType(obj) || CType::GetTypeCode(obj) != TYPE_array) {
     JS_ReportError(cx, "not an ArrayType");
     return JS_FALSE;
   }
 
   // Decide whether we have an object to initialize from. We'll override this
@@ -4042,37 +4034,36 @@ ArrayType::ConstructData(JSContext* cx,
   } else {
     if (argc != 1) {
       JS_ReportError(cx, "constructor takes one argument");
       return JS_FALSE;
     }
 
     RootedObject baseType(cx, GetBaseType(obj));
 
-    jsval* argv = JS_ARGV(cx, vp);
     size_t length;
-    if (jsvalToSize(cx, argv[0], false, &length)) {
+    if (jsvalToSize(cx, args[0], false, &length)) {
       // Have a length, rather than an object to initialize from.
       convertObject = false;
 
-    } else if (!JSVAL_IS_PRIMITIVE(argv[0])) {
+    } else if (!JSVAL_IS_PRIMITIVE(args[0])) {
       // We were given an object with a .length property.
       // This could be a JS array, or a CData array.
-      JSObject* arg = JSVAL_TO_OBJECT(argv[0]);
+      RootedObject arg(cx, JSVAL_TO_OBJECT(args[0]));
       js::AutoValueRooter lengthVal(cx);
       if (!JS_GetProperty(cx, arg, "length", lengthVal.jsval_addr()) ||
           !jsvalToSize(cx, lengthVal.jsval_value(), false, &length)) {
         JS_ReportError(cx, "argument must be an array object or length");
         return JS_FALSE;
       }
 
-    } else if (JSVAL_IS_STRING(argv[0])) {
+    } else if (JSVAL_IS_STRING(args[0])) {
       // We were given a string. Size the array to the appropriate length,
       // including space for the terminator.
-      JSString* sourceString = JSVAL_TO_STRING(argv[0]);
+      JSString* sourceString = JSVAL_TO_STRING(args[0]);
       size_t sourceLength = sourceString->length();
       const jschar* sourceChars = sourceString->getChars(cx);
       if (!sourceChars)
         return false;
 
       switch (CType::GetTypeCode(baseType)) {
       case TYPE_char:
       case TYPE_signed_char:
@@ -4084,41 +4075,41 @@ ArrayType::ConstructData(JSContext* cx,
 
         ++length;
         break;
       }
       case TYPE_jschar:
         length = sourceLength + 1;
         break;
       default:
-        return TypeError(cx, "array", argv[0]);
+        return TypeError(cx, "array", args[0]);
       }
 
     } else {
       JS_ReportError(cx, "argument must be an array object or length");
       return JS_FALSE;
     }
 
     // Construct a new ArrayType of defined length, for the new CData object.
     obj = CreateInternal(cx, baseType, length, true);
     if (!obj)
       return JS_FALSE;
   }
 
   // Root the CType object, in case we created one above.
   js::AutoObjectRooter root(cx, obj);
 
-  JSObject* result = CData::Create(cx, obj, NULL, NULL, true);
+  JSObject* result = CData::Create(cx, obj, NullPtr(), NULL, true);
   if (!result)
     return JS_FALSE;
 
   JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(result));
 
   if (convertObject) {
-    if (!ExplicitConvert(cx, JS_ARGV(cx, vp)[0], obj, CData::GetData(result)))
+    if (!ExplicitConvert(cx, args[0], obj, CData::GetData(result)))
       return JS_FALSE;
   }
 
   return JS_TRUE;
 }
 
 JSObject*
 ArrayType::GetBaseType(JSObject* obj)
@@ -4273,17 +4264,17 @@ ArrayType::Getter(JSContext* cx, JSHandl
     // Chances are it's a regular property lookup, so return.
     return JS_TRUE;
   }
   if (!ok || index >= length) {
     JS_ReportError(cx, "invalid index");
     return JS_FALSE;
   }
 
-  JSObject* baseType = GetBaseType(typeObj);
+  RootedObject baseType(cx, GetBaseType(typeObj));
   size_t elementSize = CType::GetSize(baseType);
   char* data = static_cast<char*>(CData::GetData(obj)) + elementSize * index;
   return ConvertToJS(cx, baseType, obj, data, false, false, vp.address());
 }
 
 JSBool
 ArrayType::Setter(JSContext* cx, JSHandleObject obj, JSHandleId idval, JSBool strict, MutableHandleValue vp)
 {
@@ -4338,23 +4329,22 @@ ArrayType::AddressOfElement(JSContext* c
   }
 
   if (argc != 1) {
     JS_ReportError(cx, "addressOfElement takes one argument");
     return JS_FALSE;
   }
 
   RootedObject baseType(cx, GetBaseType(typeObj));
-  JSObject* pointerType = PointerType::CreateInternal(cx, baseType);
+  RootedObject pointerType(cx, PointerType::CreateInternal(cx, baseType));
   if (!pointerType)
     return JS_FALSE;
-  js::AutoObjectRooter root(cx, pointerType);
 
   // Create a PointerType CData object containing null.
-  JSObject* result = CData::Create(cx, pointerType, NULL, NULL, true);
+  JSObject* result = CData::Create(cx, pointerType, NullPtr(), NULL, true);
   if (!result)
     return JS_FALSE;
 
   JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(result));
 
   // Convert the index to a size_t and bounds-check it.
   size_t index;
   size_t length = GetLength(typeObj);
@@ -4381,17 +4371,17 @@ static JSFlatString*
 ExtractStructField(JSContext* cx, jsval val, JSObject** typeObj)
 {
   if (JSVAL_IS_PRIMITIVE(val)) {
     JS_ReportError(cx, "struct field descriptors require a valid name and type");
     return NULL;
   }
 
   RootedObject obj(cx, JSVAL_TO_OBJECT(val));
-  JSObject* iter = JS_NewPropertyIterator(cx, obj);
+  RootedObject iter(cx, JS_NewPropertyIterator(cx, obj));
   if (!iter)
     return NULL;
   js::AutoObjectRooter iterroot(cx, iter);
 
   jsid nameid;
   if (!JS_NextProperty(cx, iter, &nameid))
     return NULL;
   if (JSID_IS_VOID(nameid)) {
@@ -4459,51 +4449,50 @@ AddFieldToArray(JSContext* cx,
     return false;
 
   return JS_FreezeObject(cx, fieldObj);
 }
 
 JSBool
 StructType::Create(JSContext* cx, unsigned argc, jsval* vp)
 {
+  CallArgs args = CallArgsFromVp(argc, vp);
+
   // Construct and return a new StructType object.
   if (argc < 1 || argc > 2) {
     JS_ReportError(cx, "StructType takes one or two arguments");
     return JS_FALSE;
   }
 
-  jsval* argv = JS_ARGV(cx, vp);
-  jsval name = argv[0];
+  jsval name = args[0];
   if (!JSVAL_IS_STRING(name)) {
     JS_ReportError(cx, "first argument must be a string");
     return JS_FALSE;
   }
 
   // Get ctypes.StructType.prototype from the ctypes.StructType constructor.
-  JSObject* callee = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
-  JSObject* typeProto = CType::GetProtoFromCtor(callee, SLOT_STRUCTPROTO);
+  RootedObject typeProto(cx, CType::GetProtoFromCtor(&args.callee(), SLOT_STRUCTPROTO));
 
   // Create a simple StructType with no defined fields. The result will be
   // non-instantiable as CData, will have no 'prototype' property, and will
   // have undefined size and alignment and no ffi_type.
-  JSObject* result = CType::Create(cx, typeProto, NULL, TYPE_struct,
-                       JSVAL_TO_STRING(name), JSVAL_VOID, JSVAL_VOID, NULL);
+  RootedObject result(cx, CType::Create(cx, typeProto, NullPtr(), TYPE_struct,
+                                        JSVAL_TO_STRING(name), JSVAL_VOID, JSVAL_VOID, NULL));
   if (!result)
     return JS_FALSE;
-  js::AutoObjectRooter root(cx, result);
 
   if (argc == 2) {
-    if (JSVAL_IS_PRIMITIVE(argv[1]) ||
-        !JS_IsArrayObject(cx, JSVAL_TO_OBJECT(argv[1]))) {
+    RootedObject arr(cx, JSVAL_IS_PRIMITIVE(args[1]) ? NULL : &args[1].toObject());
+    if (!arr || !JS_IsArrayObject(cx, arr)) {
       JS_ReportError(cx, "second argument must be an array");
       return JS_FALSE;
     }
 
     // Define the struct fields.
-    if (!DefineInternal(cx, result, JSVAL_TO_OBJECT(argv[1])))
+    if (!DefineInternal(cx, result, arr))
       return JS_FALSE;
   }
 
   JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(result));
   return JS_TRUE;
 }
 
 JSBool
@@ -4512,25 +4501,24 @@ StructType::DefineInternal(JSContext* cx
   RootedObject typeObj(cx, typeObj_);
   RootedObject fieldsObj(cx, fieldsObj_);
 
   uint32_t len;
   ASSERT_OK(JS_GetArrayLength(cx, fieldsObj, &len));
 
   // Get the common prototype for CData objects of this type from
   // ctypes.CType.prototype.
-  JSObject* dataProto = CType::GetProtoFromType(typeObj, SLOT_STRUCTDATAPROTO);
+  RootedObject dataProto(cx, CType::GetProtoFromType(typeObj, SLOT_STRUCTDATAPROTO));
 
   // Set up the 'prototype' and 'prototype.constructor' properties.
   // The prototype will reflect the struct fields as properties on CData objects
   // created from this type.
-  JSObject* prototype = JS_NewObject(cx, &sCDataProtoClass, dataProto, NULL);
+  RootedObject prototype(cx, JS_NewObject(cx, &sCDataProtoClass, dataProto, NULL));
   if (!prototype)
     return JS_FALSE;
-  js::AutoObjectRooter protoroot(cx, prototype);
 
   if (!JS_DefineProperty(cx, prototype, "constructor", OBJECT_TO_JSVAL(typeObj),
          NULL, NULL, JSPROP_READONLY | JSPROP_PERMANENT))
     return JS_FALSE;
 
   // Create a FieldInfoHash to stash on the type object, and an array to root
   // its constituents. (We cannot simply stash the hash in a reserved slot now
   // to get GC safety for free, since if anything in this function fails we
@@ -4721,23 +4709,27 @@ StructType::Define(JSContext* cx, unsign
   }
 
   if (argc != 1) {
     JS_ReportError(cx, "define takes one argument");
     return JS_FALSE;
   }
 
   jsval arg = JS_ARGV(cx, vp)[0];
-  if (JSVAL_IS_PRIMITIVE(arg) ||
-      !JS_IsArrayObject(cx, JSVAL_TO_OBJECT(arg))) {
+  if (JSVAL_IS_PRIMITIVE(arg)) {
     JS_ReportError(cx, "argument must be an array");
     return JS_FALSE;
   }
-
-  return DefineInternal(cx, obj, JSVAL_TO_OBJECT(arg));
+  RootedObject arr(cx, JSVAL_TO_OBJECT(arg));
+  if (!JS_IsArrayObject(cx, arr)) {
+    JS_ReportError(cx, "argument must be an array");
+    return JS_FALSE;
+  }
+
+  return DefineInternal(cx, obj, arr);
 }
 
 JSBool
 StructType::ConstructData(JSContext* cx,
                           HandleObject obj,
                           unsigned argc,
                           jsval* vp)
 {
@@ -4746,17 +4738,17 @@ StructType::ConstructData(JSContext* cx,
     return JS_FALSE;
   }
 
   if (!CType::IsSizeDefined(obj)) {
     JS_ReportError(cx, "cannot construct an opaque StructType");
     return JS_FALSE;
   }
 
-  JSObject* result = CData::Create(cx, obj, NULL, NULL, true);
+  JSObject* result = CData::Create(cx, obj, NullPtr(), NULL, true);
   if (!result)
     return JS_FALSE;
 
   JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(result));
 
   if (argc == 0)
     return JS_TRUE;
 
@@ -4921,17 +4913,18 @@ StructType::FieldGetter(JSContext* cx, J
     return JS_FALSE;
   }
 
   const FieldInfo* field = LookupField(cx, typeObj, JSID_TO_FLAT_STRING(idval));
   if (!field)
     return JS_FALSE;
 
   char* data = static_cast<char*>(CData::GetData(obj)) + field->mOffset;
-  return ConvertToJS(cx, field->mType, obj, data, false, false, vp.address());
+  RootedObject fieldType(cx, field->mType);
+  return ConvertToJS(cx, fieldType, obj, data, false, false, vp.address());
 }
 
 JSBool
 StructType::FieldSetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, JSBool strict, MutableHandleValue vp)
 {
   if (!CData::IsCData(obj)) {
     JS_ReportError(cx, "not a CData");
     return JS_FALSE;
@@ -4976,24 +4969,23 @@ StructType::AddressOfField(JSContext* cx
   JSFlatString *str = JS_FlattenString(cx, JSVAL_TO_STRING(JS_ARGV(cx, vp)[0]));
   if (!str)
     return JS_FALSE;
 
   const FieldInfo* field = LookupField(cx, typeObj, str);
   if (!field)
     return JS_FALSE;
 
-  JSObject* baseType = field->mType;
-  JSObject* pointerType = PointerType::CreateInternal(cx, baseType);
+  RootedObject baseType(cx, field->mType);
+  RootedObject pointerType(cx, PointerType::CreateInternal(cx, baseType));
   if (!pointerType)
     return JS_FALSE;
-  js::AutoObjectRooter root(cx, pointerType);
 
   // Create a PointerType CData object containing null.
-  JSObject* result = CData::Create(cx, pointerType, NULL, NULL, true);
+  JSObject* result = CData::Create(cx, pointerType, NullPtr(), NULL, true);
   if (!result)
     return JS_FALSE;
 
   JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(result));
 
   // Manually set the pointer inside the object, so we skip the conversion step.
   void** data = static_cast<void**>(CData::GetData(result));
   *data = static_cast<char*>(CData::GetData(obj)) + field->mOffset;
@@ -5069,17 +5061,17 @@ PrepareType(JSContext* cx, jsval type)
   }
 
   JSObject* result = JSVAL_TO_OBJECT(type);
   TypeCode typeCode = CType::GetTypeCode(result);
 
   if (typeCode == TYPE_array) {
     // convert array argument types to pointers, just like C.
     // ImplicitConvert will do the same, when passing an array as data.
-    JSObject* baseType = ArrayType::GetBaseType(result);
+    RootedObject baseType(cx, ArrayType::GetBaseType(result));
     result = PointerType::CreateInternal(cx, baseType);
     if (!result)
       return NULL;
 
   } else if (typeCode == TYPE_void_t || typeCode == TYPE_function) {
     // disallow void or function argument types
     JS_ReportError(cx, "Cannot have void or function argument type");
     return NULL;
@@ -5312,27 +5304,27 @@ FunctionType::Create(JSContext* cx, unsi
   // Construct and return a new FunctionType object.
   if (argc < 2 || argc > 3) {
     JS_ReportError(cx, "FunctionType takes two or three arguments");
     return JS_FALSE;
   }
 
   jsval* argv = JS_ARGV(cx, vp);
   Array<jsval, 16> argTypes;
-  JSObject* arrayObj = NULL;
+  RootedObject arrayObj(cx, NULL);
 
   if (argc == 3) {
     // Prepare an array of jsvals for the arguments.
-    if (JSVAL_IS_PRIMITIVE(argv[2]) ||
-        !JS_IsArrayObject(cx, JSVAL_TO_OBJECT(argv[2]))) {
+    if (!JSVAL_IS_PRIMITIVE(argv[2]))
+      arrayObj = JSVAL_TO_OBJECT(argv[2]);
+    if (!arrayObj || !JS_IsArrayObject(cx, arrayObj)) {
       JS_ReportError(cx, "third argument must be an array");
       return JS_FALSE;
     }
 
-    arrayObj = JSVAL_TO_OBJECT(argv[2]);
     uint32_t len;
     ASSERT_OK(JS_GetArrayLength(cx, arrayObj, &len));
 
     if (!argTypes.appendN(JSVAL_VOID, len)) {
       JS_ReportOutOfMemory(cx);
       return JS_FALSE;
     }
   }
@@ -5363,20 +5355,20 @@ FunctionType::CreateInternal(JSContext* 
 {
   // Determine and check the types, and prepare the function CIF.
   AutoPtr<FunctionInfo> fninfo(NewFunctionInfo(cx, abi, rtype, argtypes, arglen));
   if (!fninfo)
     return NULL;
 
   // Get ctypes.FunctionType.prototype and the common prototype for CData objects
   // of this type, from ctypes.CType.prototype.
-  JSObject* typeProto = CType::GetProtoFromType(fninfo->mReturnType,
-                                                SLOT_FUNCTIONPROTO);
-  JSObject* dataProto = CType::GetProtoFromType(fninfo->mReturnType,
-                                                SLOT_FUNCTIONDATAPROTO);
+  RootedObject typeProto(cx, CType::GetProtoFromType(fninfo->mReturnType,
+                                                     SLOT_FUNCTIONPROTO));
+  RootedObject dataProto(cx, CType::GetProtoFromType(fninfo->mReturnType,
+                                                     SLOT_FUNCTIONDATAPROTO));
 
   // Create a new CType object with the common properties and slots.
   JSObject* typeObj = CType::Create(cx, typeProto, dataProto, TYPE_function,
                         NULL, JSVAL_VOID, JSVAL_VOID, NULL);
   if (!typeObj)
     return NULL;
   js::AutoObjectRooter root(cx, typeObj);
 
@@ -5614,18 +5606,18 @@ FunctionType::Call(JSContext* cx,
 #define DEFINE_CHAR_TYPE(x, y, z) DEFINE_INT_TYPE(x, y, z)
 #define DEFINE_JSCHAR_TYPE(x, y, z) DEFINE_INT_TYPE(x, y, z)
 #include "typedefs.h"
   default:
     break;
   }
 
   // prepare a JS object from the result
-  return ConvertToJS(cx, fninfo->mReturnType, NULL, returnValue.mData,
-                     false, true, vp);
+  RootedObject returnType(cx, fninfo->mReturnType);
+  return ConvertToJS(cx, returnType, NullPtr(), returnValue.mData, false, true, vp);
 }
 
 FunctionInfo*
 FunctionType::GetFunctionInfo(JSObject* obj)
 {
   JS_ASSERT(CType::IsCType(obj));
   JS_ASSERT(CType::GetTypeCode(obj) == TYPE_function);
 
@@ -5713,31 +5705,27 @@ FunctionType::IsVariadicGetter(JSContext
 }
 
 /*******************************************************************************
 ** CClosure implementation
 *******************************************************************************/
 
 JSObject*
 CClosure::Create(JSContext* cx,
-                 JSObject* typeObj_,
-                 JSObject* fnObj_,
-                 JSObject* thisObj_,
+                 HandleObject typeObj,
+                 HandleObject fnObj,
+                 HandleObject thisObj,
                  jsval errVal,
                  PRFuncPtr* fnptr)
 {
-  RootedObject typeObj(cx, typeObj_);
-  RootedObject fnObj(cx, fnObj_);
-  RootedObject thisObj(cx, thisObj_);
   JS_ASSERT(fnObj);
 
-  JSObject* result = JS_NewObject(cx, &sCClosureClass, NULL, NULL);
+  RootedObject result(cx, JS_NewObject(cx, &sCClosureClass, NULL, NULL));
   if (!result)
     return NULL;
-  js::AutoObjectRooter root(cx, result);
 
   // Get the FunctionInfo from the FunctionType.
   FunctionInfo* fninfo = FunctionType::GetFunctionInfo(typeObj);
   JS_ASSERT(!fninfo->mIsVariadic);
   JS_ASSERT(GetABICode(fninfo->mABI) != ABI_WINAPI);
 
   AutoPtr<ClosureInfo> cinfo(cx->new_<ClosureInfo>(JS_GetRuntime(cx)));
   if (!cinfo) {
@@ -5921,18 +5909,18 @@ CClosure::ClosureStub(ffi_cif* cif, void
     JS_ReportOutOfMemory(cx);
     return;
   }
 
   js::AutoArrayRooter roots(cx, argv.length(), argv.begin());
   for (uint32_t i = 0; i < cif->nargs; ++i) {
     // Convert each argument, and have any CData objects created depend on
     // the existing buffers.
-    if (!ConvertToJS(cx, fninfo->mArgTypes[i], NULL, args[i], false, false,
-           &argv[i]))
+    RootedObject argType(cx, fninfo->mArgTypes[i]);
+    if (!ConvertToJS(cx, argType, NullPtr(), args[i], false, false, &argv[i]))
       return;
   }
 
   // Call the JS function. 'thisObj' may be NULL, in which case the JS engine
   // will find an appropriate object to use.
   jsval rval;
   JSBool success = JS_CallFunctionValue(cx, thisObj, OBJECT_TO_JSVAL(jsfnObj),
                                         cif->nargs, argv.begin(), &rval);
@@ -6022,39 +6010,38 @@ CClosure::ClosureStub(ffi_cif* cif, void
 //   sized buffer, and free it upon finalization. If 'source' data is
 //   supplied, the data will be copied from 'source' into the buffer;
 //   otherwise, the entirety of the new buffer will be initialized to zero.
 // * If 'ownResult' is false, the new CData's buffer refers to a slice of
 //   another buffer kept alive by 'refObj'. 'source' data must be provided,
 //   and the new CData's buffer will refer to 'source'.
 JSObject*
 CData::Create(JSContext* cx,
-              JSObject* typeObj,
-              JSObject* refObj,
+              HandleObject typeObj,
+              HandleObject refObj,
               void* source,
               bool ownResult)
 {
   JS_ASSERT(typeObj);
   JS_ASSERT(CType::IsCType(typeObj));
   JS_ASSERT(CType::IsSizeDefined(typeObj));
   JS_ASSERT(ownResult || source);
   JS_ASSERT_IF(refObj && CData::IsCData(refObj), !ownResult);
 
   // Get the 'prototype' property from the type.
   jsval slot = JS_GetReservedSlot(typeObj, SLOT_PROTO);
   JS_ASSERT(!JSVAL_IS_PRIMITIVE(slot));
 
-  JSObject* proto = JSVAL_TO_OBJECT(slot);
-  JSObject* parent = JS_GetParent(typeObj);
+  RootedObject proto(cx, JSVAL_TO_OBJECT(slot));
+  RootedObject parent(cx, JS_GetParent(typeObj));
   JS_ASSERT(parent);
 
-  JSObject* dataObj = JS_NewObject(cx, &sCDataClass, proto, parent);
+  RootedObject dataObj(cx, JS_NewObject(cx, &sCDataClass, proto, parent));
   if (!dataObj)
     return NULL;
-  js::AutoObjectRooter root(cx, dataObj);
 
   // set the CData's associated type
   JS_SetReservedSlot(dataObj, SLOT_CTYPE, OBJECT_TO_JSVAL(typeObj));
 
   // Stash the referent object, if any, for GC safety.
   if (refObj)
     JS_SetReservedSlot(dataObj, SLOT_REFERENT, OBJECT_TO_JSVAL(refObj));
 
@@ -6155,17 +6142,18 @@ JSBool
 CData::ValueGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, MutableHandleValue vp)
 {
   if (!IsCData(obj)) {
     JS_ReportError(cx, "not a CData");
     return JS_FALSE;
   }
 
   // Convert the value to a primitive; do not create a new CData object.
-  if (!ConvertToJS(cx, GetCType(obj), NULL, GetData(obj), true, false, vp.address()))
+  RootedObject ctype(cx, GetCType(obj));
+  if (!ConvertToJS(cx, ctype, NullPtr(), GetData(obj), true, false, vp.address()))
     return JS_FALSE;
 
   return JS_TRUE;
 }
 
 JSBool
 CData::ValueSetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, JSBool strict, MutableHandleValue vp)
 {
@@ -6188,24 +6176,23 @@ CData::Address(JSContext* cx, unsigned a
   RootedObject obj(cx, JS_THIS_OBJECT(cx, vp));
   if (!obj)
     return JS_FALSE;
   if (!IsCData(obj)) {
     JS_ReportError(cx, "not a CData");
     return JS_FALSE;
   }
 
-  JSObject* typeObj = CData::GetCType(obj);
-  JSObject* pointerType = PointerType::CreateInternal(cx, typeObj);
+  RootedObject typeObj(cx, CData::GetCType(obj));
+  RootedObject pointerType(cx, PointerType::CreateInternal(cx, typeObj));
   if (!pointerType)
     return JS_FALSE;
-  js::AutoObjectRooter root(cx, pointerType);
 
   // Create a PointerType CData object containing null.
-  JSObject* result = CData::Create(cx, pointerType, NULL, NULL, true);
+  JSObject* result = CData::Create(cx, pointerType, NullPtr(), NULL, true);
   if (!result)
     return JS_FALSE;
 
   JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(result));
 
   // Manually set the pointer inside the object, so we skip the conversion step.
   void** data = static_cast<void**>(GetData(result));
   *data = GetData(obj);
@@ -6221,26 +6208,26 @@ CData::Cast(JSContext* cx, unsigned argc
   }
 
   jsval* argv = JS_ARGV(cx, vp);
   if (JSVAL_IS_PRIMITIVE(argv[0]) ||
       !CData::IsCData(JSVAL_TO_OBJECT(argv[0]))) {
     JS_ReportError(cx, "first argument must be a CData");
     return JS_FALSE;
   }
-  JSObject* sourceData = JSVAL_TO_OBJECT(argv[0]);
+  RootedObject sourceData(cx, JSVAL_TO_OBJECT(argv[0]));
   JSObject* sourceType = CData::GetCType(sourceData);
 
   if (JSVAL_IS_PRIMITIVE(argv[1]) ||
       !CType::IsCType(JSVAL_TO_OBJECT(argv[1]))) {
     JS_ReportError(cx, "second argument must be a CType");
     return JS_FALSE;
   }
 
-  JSObject* targetType = JSVAL_TO_OBJECT(argv[1]);
+  RootedObject targetType(cx, JSVAL_TO_OBJECT(argv[1]));
   size_t targetSize;
   if (!CType::GetSafeSize(targetType, &targetSize) ||
       targetSize > CType::GetSize(sourceType)) {
     JS_ReportError(cx,
       "target CType has undefined or larger size than source CType");
     return JS_FALSE;
   }
 
@@ -6265,26 +6252,26 @@ CData::GetRuntime(JSContext* cx, unsigne
 
   jsval* argv = JS_ARGV(cx, vp);
   if (JSVAL_IS_PRIMITIVE(argv[0]) ||
       !CType::IsCType(JSVAL_TO_OBJECT(argv[0]))) {
     JS_ReportError(cx, "first argument must be a CType");
     return JS_FALSE;
   }
 
-  JSObject* targetType = JSVAL_TO_OBJECT(argv[0]);
+  RootedObject targetType(cx, JSVAL_TO_OBJECT(argv[0]));
   size_t targetSize;
   if (!CType::GetSafeSize(targetType, &targetSize) ||
       targetSize != sizeof(void*)) {
     JS_ReportError(cx, "target CType has non-pointer size");
     return JS_FALSE;
   }
 
   void* data = static_cast<void*>(cx->runtime);
-  JSObject* result = CData::Create(cx, targetType, NULL, &data, true);
+  JSObject* result = CData::Create(cx, targetType, NullPtr(), &data, true);
   if (!result)
     return JS_FALSE;
 
   JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(result));
   return JS_TRUE;
 }
 
 JSBool
@@ -6598,18 +6585,18 @@ CDataFinalizer::GetValue(JSContext *cx, 
   CDataFinalizer::Private *p = (CDataFinalizer::Private *)
     JS_GetPrivate(obj);
 
   if (!p) {
     JS_ReportError(cx, "Attempting to get the value of an empty CDataFinalizer");
     return false;  // We have called |dispose| or |forget| already.
   }
 
-  return ConvertToJS(cx, GetCType(cx, obj),
-                     /*parent*/NULL, p -> cargs, false, true, aResult);
+  RootedObject ctype(cx, GetCType(cx, obj));
+  return ConvertToJS(cx, ctype, /*parent*/NullPtr(), p -> cargs, false, true, aResult);
 }
 
 /*
  * Attach a C function as a finalizer to a JS object.
  *
  * Pseudo-JS signature:
  * function(CData<T>, CData<T -> U>): CDataFinalizer<T>
  *          value,    finalizer
@@ -6618,18 +6605,18 @@ CDataFinalizer::GetValue(JSContext *cx, 
  * - the CType of |value|
  *
  * Note: This function takes advantage of the fact that non-variadic
  * CData functions are initialized during creation.
  */
 JSBool
 CDataFinalizer::Construct(JSContext* cx, unsigned argc, jsval *vp)
 {
-  JSObject* objSelf = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
-  JSObject *objProto;
+  RootedObject objSelf(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));
+  RootedObject objProto(cx);
   if (!GetObjectProperty(cx, objSelf, "prototype", &objProto)) {
     JS_ReportError(cx, "CDataFinalizer.prototype does not exist");
     return JS_FALSE;
   }
 
   // Get arguments
   if (argc == 0) { // Special case: the empty (already finalized) object
     JSObject *objResult = JS_NewObject(cx, &sCDataFinalizerClass, objProto, NULL);
@@ -6863,17 +6850,18 @@ CDataFinalizer::Methods::Forget(JSContex
     JS_GetPrivate(obj);
 
   if (!p) {
     JS_ReportError(cx, "forget called on an empty CDataFinalizer");
     return JS_FALSE;
   }
 
   jsval valJSData;
-  if (!ConvertToJS(cx, GetCType(cx, obj), NULL, p->cargs, false, true, &valJSData)) {
+  RootedObject ctype(cx, GetCType(cx, obj));
+  if (!ConvertToJS(cx, ctype, NullPtr(), p->cargs, false, true, &valJSData)) {
     JS_ReportError(cx, "CDataFinalizer value cannot be represented");
     return JS_FALSE;
   }
 
   CDataFinalizer::Cleanup(p, obj);
 
   JS_SET_RVAL(cx, vp, valJSData);
   return JS_TRUE;
@@ -6920,33 +6908,33 @@ CDataFinalizer::Methods::Dispose(JSConte
   jsval valCodePtrType = JS_GetReservedSlot(obj, SLOT_DATAFINALIZER_CODETYPE);
   JS_ASSERT(!JSVAL_IS_PRIMITIVE(valCodePtrType));
   JSObject *objCodePtrType = JSVAL_TO_OBJECT(valCodePtrType);
 
   JSObject *objCodeType = PointerType::GetBaseType(objCodePtrType);
   JS_ASSERT(objCodeType);
   JS_ASSERT(CType::GetTypeCode(objCodeType) == TYPE_function);
 
-  JSObject *resultType = FunctionType::GetFunctionInfo(objCodeType)->mReturnType;
+  RootedObject resultType(cx, FunctionType::GetFunctionInfo(objCodeType)->mReturnType);
   jsval result = JSVAL_VOID;
 
   int errnoStatus;
 #if defined(XP_WIN)
   int32_t lastErrorStatus;
   CDataFinalizer::CallFinalizer(p, &errnoStatus, &lastErrorStatus);
 #else
   CDataFinalizer::CallFinalizer(p, &errnoStatus, NULL);
 #endif // defined(XP_WIN)
 
   JS_SetReservedSlot(objCTypes, SLOT_ERRNO, INT_TO_JSVAL(errnoStatus));
 #if defined(XP_WIN)
   JS_SetReservedSlot(objCTypes, SLOT_LASTERROR, INT_TO_JSVAL(lastErrorStatus));
 #endif // defined(XP_WIN)
 
-  if (ConvertToJS(cx, resultType, NULL, p->rvalue, false, true, &result)) {
+  if (ConvertToJS(cx, resultType, NullPtr(), p->rvalue, false, true, &result)) {
     CDataFinalizer::Cleanup(p, obj);
     JS_SET_RVAL(cx, vp, result);
     return true;
   }
   CDataFinalizer::Cleanup(p, obj);
   return false;
 }
 
@@ -7010,25 +6998,25 @@ CDataFinalizer::Cleanup(CDataFinalizer::
 
 
 /*******************************************************************************
 ** Int64 and UInt64 implementation
 *******************************************************************************/
 
 JSObject*
 Int64Base::Construct(JSContext* cx,
-                     JSObject* proto,
+                     HandleObject proto,
                      uint64_t data,
                      bool isUnsigned)
 {
   JSClass* clasp = isUnsigned ? &sUInt64Class : &sInt64Class;
-  JSObject* result = JS_NewObject(cx, clasp, proto, JS_GetParent(proto));
+  RootedObject parent(cx, JS_GetParent(proto));
+  RootedObject result(cx, JS_NewObject(cx, clasp, proto, parent));
   if (!result)
     return NULL;
-  js::AutoObjectRooter root(cx, result);
 
   // attach the Int64's data
   uint64_t* buffer = cx->new_<uint64_t>(data);
   if (!buffer) {
     JS_ReportOutOfMemory(cx);
     return NULL;
   }
 
@@ -7127,32 +7115,33 @@ Int64Base::ToSource(JSContext* cx,
   return JS_TRUE;
 }
 
 JSBool
 Int64::Construct(JSContext* cx,
                  unsigned argc,
                  jsval* vp)
 {
+  CallArgs args = CallArgsFromVp(argc, vp);
+
   // Construct and return a new Int64 object.
   if (argc != 1) {
     JS_ReportError(cx, "Int64 takes one argument");
     return JS_FALSE;
   }
 
-  jsval* argv = JS_ARGV(cx, vp);
   int64_t i = 0;
-  if (!jsvalToBigInteger(cx, argv[0], true, &i))
-    return TypeError(cx, "int64", argv[0]);
+  if (!jsvalToBigInteger(cx, args[0], true, &i))
+    return TypeError(cx, "int64", args[0]);
 
   // Get ctypes.Int64.prototype from the 'prototype' property of the ctor.
   jsval slot;
-  ASSERT_OK(JS_GetProperty(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)),
-    "prototype", &slot));
-  JSObject* proto = JSVAL_TO_OBJECT(slot);
+  RootedObject callee(cx, &args.callee());
+  ASSERT_OK(JS_GetProperty(cx, callee, "prototype", &slot));
+  RootedObject proto(cx, JSVAL_TO_OBJECT(slot));
   JS_ASSERT(JS_GetClass(proto) == &sInt64ProtoClass);
 
   JSObject* result = Int64Base::Construct(cx, proto, i, false);
   if (!result)
     return JS_FALSE;
 
   JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(result));
   return JS_TRUE;
@@ -7286,48 +7275,49 @@ Int64::Join(JSContext* cx, unsigned argc
     return TypeError(cx, "uint32", argv[1]);
 
   int64_t i = (int64_t(hi) << 32) + int64_t(lo);
 
   // Get Int64.prototype from the function's reserved slot.
   JSObject* callee = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
 
   jsval slot = js::GetFunctionNativeReserved(callee, SLOT_FN_INT64PROTO);
-  JSObject* proto = JSVAL_TO_OBJECT(slot);
+  RootedObject proto(cx, JSVAL_TO_OBJECT(slot));
   JS_ASSERT(JS_GetClass(proto) == &sInt64ProtoClass);
 
   JSObject* result = Int64Base::Construct(cx, proto, i, false);
   if (!result)
     return JS_FALSE;
 
   JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(result));
   return JS_TRUE;
 }
 
 JSBool
 UInt64::Construct(JSContext* cx,
                   unsigned argc,
                   jsval* vp)
 {
+  CallArgs args = CallArgsFromVp(argc, vp);
+
   // Construct and return a new UInt64 object.
   if (argc != 1) {
     JS_ReportError(cx, "UInt64 takes one argument");
     return JS_FALSE;
   }
 
-  jsval* argv = JS_ARGV(cx, vp);
   uint64_t u = 0;
-  if (!jsvalToBigInteger(cx, argv[0], true, &u))
-    return TypeError(cx, "uint64", argv[0]);
+  if (!jsvalToBigInteger(cx, args[0], true, &u))
+    return TypeError(cx, "uint64", args[0]);
 
   // Get ctypes.UInt64.prototype from the 'prototype' property of the ctor.
   jsval slot;
-  ASSERT_OK(JS_GetProperty(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)),
-    "prototype", &slot));
-  JSObject* proto = JSVAL_TO_OBJECT(slot);
+  RootedObject callee(cx, &args.callee());
+  ASSERT_OK(JS_GetProperty(cx, callee, "prototype", &slot));
+  RootedObject proto(cx, JSVAL_TO_OBJECT(slot));
   JS_ASSERT(JS_GetClass(proto) == &sUInt64ProtoClass);
 
   JSObject* result = Int64Base::Construct(cx, proto, u, true);
   if (!result)
     return JS_FALSE;
 
   JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(result));
   return JS_TRUE;
@@ -7457,17 +7447,17 @@ UInt64::Join(JSContext* cx, unsigned arg
     return TypeError(cx, "uint32_t", argv[1]);
 
   uint64_t u = (uint64_t(hi) << 32) + uint64_t(lo);
 
   // Get UInt64.prototype from the function's reserved slot.
   JSObject* callee = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
 
   jsval slot = js::GetFunctionNativeReserved(callee, SLOT_FN_INT64PROTO);
-  JSObject* proto = JSVAL_TO_OBJECT(slot);
+  RootedObject proto(cx, JSVAL_TO_OBJECT(slot));
   JS_ASSERT(JS_GetClass(proto) == &sUInt64ProtoClass);
 
   JSObject* result = Int64Base::Construct(cx, proto, u, true);
   if (!result)
     return JS_FALSE;
 
   JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(result));
   return JS_TRUE;
--- a/js/src/ctypes/CTypes.h
+++ b/js/src/ctypes/CTypes.h
@@ -316,17 +316,17 @@ struct ClosureInfo
 };
 
 bool IsCTypesGlobal(JSObject* obj);
 
 JSCTypesCallbacks* GetCallbacks(JSObject* obj);
 
 JSBool InitTypeClasses(JSContext* cx, JSHandleObject parent);
 
-JSBool ConvertToJS(JSContext* cx, JSObject* typeObj, JSObject* dataObj,
+JSBool ConvertToJS(JSContext* cx, JSHandleObject typeObj, JSHandleObject dataObj,
   void* data, bool wantPrimitive, bool ownResult, jsval* result);
 
 JSBool ImplicitConvert(JSContext* cx, jsval val, JSObject* targetType,
   void* buffer, bool isArgument, bool* freePointer);
 
 JSBool ExplicitConvert(JSContext* cx, jsval val, JSHandleObject targetType,
   void* buffer);
 
@@ -422,17 +422,17 @@ enum Int64FunctionSlot {
   // JSFunction objects always get exactly two slots.
 };
 
 /*******************************************************************************
 ** Object API definitions
 *******************************************************************************/
 
 namespace CType {
-  JSObject* Create(JSContext* cx, JSObject* typeProto, JSObject* dataProto,
+  JSObject* Create(JSContext* cx, JSHandleObject typeProto, JSHandleObject dataProto,
     TypeCode type, JSString* name, jsval size, jsval align, ffi_type* ffiType);
 
   JSObject* DefineBuiltin(JSContext* cx, JSObject* parent, const char* propName,
     JSObject* typeProto, JSObject* dataProto, const char* name, TypeCode type,
     jsval size, jsval align, ffi_type* ffiType);
 
   bool IsCType(JSObject* obj);
   bool IsCTypeProto(JSObject* obj);
@@ -445,23 +445,23 @@ namespace CType {
   ffi_type* GetFFIType(JSContext* cx, JSObject* obj);
   JSString* GetName(JSContext* cx, JSHandleObject obj);
   JSObject* GetProtoFromCtor(JSObject* obj, CTypeProtoSlot slot);
   JSObject* GetProtoFromType(JSObject* obj, CTypeProtoSlot slot);
   JSCTypesCallbacks* GetCallbacksFromType(JSObject* obj);
 }
 
 namespace PointerType {
-  JSObject* CreateInternal(JSContext* cx, JSObject* baseType);
+  JSObject* CreateInternal(JSContext* cx, JSHandleObject baseType);
 
   JSObject* GetBaseType(JSObject* obj);
 }
 
 namespace ArrayType {
-  JSObject* CreateInternal(JSContext* cx, JSObject* baseType, size_t length,
+  JSObject* CreateInternal(JSContext* cx, JSHandleObject baseType, size_t length,
     bool lengthDefined);
 
   JSObject* GetBaseType(JSObject* obj);
   size_t GetLength(JSObject* obj);
   bool GetSafeLength(JSObject* obj, size_t* result);
   ffi_type* BuildFFIType(JSContext* cx, JSObject* obj);
 }
 
@@ -482,22 +482,22 @@ namespace FunctionType {
     JSObject* refObj, PRFuncPtr fnptr, JSObject* result);
 
   FunctionInfo* GetFunctionInfo(JSObject* obj);
   void BuildSymbolName(JSString* name, JSObject* typeObj,
     AutoCString& result);
 }
 
 namespace CClosure {
-  JSObject* Create(JSContext* cx, JSObject* typeObj, JSObject* fnObj,
-    JSObject* thisObj, jsval errVal, PRFuncPtr* fnptr);
+  JSObject* Create(JSContext* cx, JSHandleObject typeObj, JSHandleObject fnObj,
+    JSHandleObject thisObj, jsval errVal, PRFuncPtr* fnptr);
 }
 
 namespace CData {
-  JSObject* Create(JSContext* cx, JSObject* typeObj, JSObject* refObj,
+  JSObject* Create(JSContext* cx, JSHandleObject typeObj, JSHandleObject refObj,
     void* data, bool ownResult);
 
   JSObject* GetCType(JSObject* dataObj);
   void* GetData(JSObject* dataObj);
   bool IsCData(JSObject* obj);
   bool IsCDataProto(JSObject* obj);
 
   // Attached by JSAPI as the function 'ctypes.cast'
--- a/js/src/ctypes/Library.cpp
+++ b/js/src/ctypes/Library.cpp
@@ -74,20 +74,19 @@ Library::Name(JSContext* cx, unsigned ar
 
   JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(result));
   return JS_TRUE;
 }
 
 JSObject*
 Library::Create(JSContext* cx, jsval path, JSCTypesCallbacks* callbacks)
 {
-  JSObject* libraryObj = JS_NewObject(cx, &sLibraryClass, NULL, NULL);
+  RootedObject libraryObj(cx, JS_NewObject(cx, &sLibraryClass, NULL, NULL));
   if (!libraryObj)
     return NULL;
-  js::AutoObjectRooter root(cx, libraryObj);
 
   // initialize the library
   JS_SetReservedSlot(libraryObj, SLOT_LIBRARY, PRIVATE_TO_JSVAL(NULL));
 
   // attach API functions
   if (!JS_DefineFunctions(cx, libraryObj, sLibraryFunctions))
     return NULL;
 
@@ -230,17 +229,17 @@ Library::Close(JSContext* cx, unsigned a
 
   JS_SET_RVAL(cx, vp, JSVAL_VOID);
   return JS_TRUE;
 }
 
 JSBool
 Library::Declare(JSContext* cx, unsigned argc, jsval* vp)
 {
-  JSObject* obj = JS_THIS_OBJECT(cx, vp);
+  RootedObject obj(cx, JS_THIS_OBJECT(cx, vp));
   if (!obj)
     return JS_FALSE;
   if (!IsLibrary(obj)) {
     JS_ReportError(cx, "not a library");
     return JS_FALSE;
   }
 
   PRLibrary* library = GetLibrary(obj);
@@ -265,35 +264,31 @@ Library::Declare(JSContext* cx, unsigned
   }
 
   jsval* argv = JS_ARGV(cx, vp);
   if (!JSVAL_IS_STRING(argv[0])) {
     JS_ReportError(cx, "first argument must be a string");
     return JS_FALSE;
   }
 
-  JSObject* fnObj = NULL;
-  JSObject* typeObj;
-  js::AutoObjectRooter root(cx);
+  RootedObject fnObj(cx, NULL);
+  RootedObject typeObj(cx);
   bool isFunction = argc > 2;
   if (isFunction) {
     // Case 1).
     // Create a FunctionType representing the function.
     fnObj = FunctionType::CreateInternal(cx,
               argv[1], argv[2], &argv[3], argc - 3);
     if (!fnObj)
       return JS_FALSE;
-    root.setObject(fnObj);
 
     // Make a function pointer type.
     typeObj = PointerType::CreateInternal(cx, fnObj);
     if (!typeObj)
       return JS_FALSE;
-    root.setObject(typeObj);
-
   } else {
     // Case 2).
     if (JSVAL_IS_PRIMITIVE(argv[1]) ||
         !CType::IsCType(JSVAL_TO_OBJECT(argv[1])) ||
         !CType::IsSizeDefined(JSVAL_TO_OBJECT(argv[1]))) {
       JS_ReportError(cx, "second argument must be a type of defined size");
       return JS_FALSE;
     }
@@ -329,17 +324,17 @@ Library::Declare(JSContext* cx, unsigned
 
     data = PR_FindSymbol(library, symbol.begin());
     if (!data) {
       JS_ReportError(cx, "couldn't find symbol in library");
       return JS_FALSE;
     }
   }
 
-  JSObject* result = CData::Create(cx, typeObj, obj, data, isFunction);
+  RootedObject result(cx, CData::Create(cx, typeObj, obj, data, isFunction));
   if (!result)
     return JS_FALSE;
 
   JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(result));
 
   // Seal the CData object, to prevent modification of the function pointer.
   // This permanently associates this object with the library, and avoids
   // having to do things like reset SLOT_REFERENT when someone tries to
--- a/js/src/gc/Root.h
+++ b/js/src/gc/Root.h
@@ -227,16 +227,22 @@ class MutableHandle : public MutableHand
     template <typename S>
     void operator =(S v) MOZ_DELETE;
 };
 
 typedef MutableHandle<JSObject*>    MutableHandleObject;
 typedef MutableHandle<Value>        MutableHandleValue;
 
 /*
+ * Raw pointer used as documentation that a parameter does not need to be
+ * rooted.
+ */
+typedef JSObject *                  RawObject;
+
+/*
  * By default, pointers should use the inheritance hierarchy to find their
  * ThingRootKind. Some pointer types are explicitly set in jspubtd.h so that
  * Rooted<T> may be used without the class definition being available.
  */
 template <typename T>
 struct RootKind<T *> { static ThingRootKind rootKind() { return T::rootKind(); }; };
 
 template <typename T>
--- a/js/src/jsapi-tests/selfTest.cpp
+++ b/js/src/jsapi-tests/selfTest.cpp
@@ -5,21 +5,21 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 
 #include "tests.h"
 
 BEGIN_TEST(selfTest_NaNsAreSame)
 {
-    jsvalRoot v1(cx), v2(cx);
-    EVAL("0/0", v1.addr());  // NaN
+    JS::RootedValue v1(cx), v2(cx);
+    EVAL("0/0", v1.address());  // NaN
     CHECK_SAME(v1, v1);
 
-    EVAL("Math.sin('no')", v2.addr());  // also NaN
+    EVAL("Math.sin('no')", v2.address());  // also NaN
     CHECK_SAME(v1, v2);
     return true;
 }
 END_TEST(selfTest_NaNsAreSame)
 
 BEGIN_TEST(selfTest_globalHasNoParent)
 {
     CHECK(JS_GetParent(global) == NULL);
--- a/js/src/jsapi-tests/testAddPropertyPropcache.cpp
+++ b/js/src/jsapi-tests/testAddPropertyPropcache.cpp
@@ -29,38 +29,36 @@ JSClass addPropertyClass = {
     JS_StrictPropertyStub,   /* setProperty */
     JS_EnumerateStub,
     JS_ResolveStub,
     JS_ConvertStub
 };
 
 BEGIN_TEST(testAddPropertyHook)
 {
-    jsvalRoot proto(cx);
-    JSObject *obj = JS_NewObject(cx, NULL, NULL, NULL);
+    JS::RootedObject obj(cx, JS_NewObject(cx, NULL, NULL, NULL));
     CHECK(obj);
-    proto = OBJECT_TO_JSVAL(obj);
+    JS::RootedValue proto(cx, OBJECT_TO_JSVAL(obj));
     JS_InitClass(cx, global, obj, &addPropertyClass, NULL, 0, NULL, NULL, NULL,
                  NULL);
 
-    jsvalRoot arr(cx);
     obj = JS_NewArrayObject(cx, 0, NULL);
     CHECK(obj);
-    arr = OBJECT_TO_JSVAL(obj);
+    JS::RootedValue arr(cx, OBJECT_TO_JSVAL(obj));
 
     CHECK(JS_DefineProperty(cx, global, "arr", arr,
                             JS_PropertyStub, JS_StrictPropertyStub,
                             JSPROP_ENUMERATE));
 
     for (int i = 0; i < expectedCount; ++i) {
-        jsvalRoot vobj(cx);
         obj = JS_NewObject(cx, &addPropertyClass, NULL, NULL);
         CHECK(obj);
-        vobj = OBJECT_TO_JSVAL(obj);
-        CHECK(JS_DefineElement(cx, JSVAL_TO_OBJECT(arr), i, vobj,
+        JS::RootedValue vobj(cx, OBJECT_TO_JSVAL(obj));
+        JS::RootedObject arrObj(cx, JSVAL_TO_OBJECT(arr));
+        CHECK(JS_DefineElement(cx, arrObj, i, vobj,
                                JS_PropertyStub, JS_StrictPropertyStub,
                                JSPROP_ENUMERATE));
     }
 
     // Now add a prop to each of the objects, but make sure to do
     // so at the same bytecode location so we can hit the propcache.
     EXEC("'use strict';                                     \n"
          "for (var i = 0; i < arr.length; ++i)              \n"
--- a/js/src/jsapi-tests/testBindCallable.cpp
+++ b/js/src/jsapi-tests/testBindCallable.cpp
@@ -9,18 +9,19 @@ BEGIN_TEST(test_BindCallable)
   jsval v;
   EVAL("({ somename : 1717 })", &v);
   CHECK(v.isObject());
 
   jsval func;
   EVAL("(function() { return this.somename; })", &func);
   CHECK(func.isObject());
 
-  JSObject* newCallable = JS_BindCallable(cx, JSVAL_TO_OBJECT(func),
-                                          JSVAL_TO_OBJECT(v));
+  JS::RootedObject funcObj(cx, JSVAL_TO_OBJECT(func));
+  JS::RootedObject vObj(cx, JSVAL_TO_OBJECT(v));
+  JSObject* newCallable = JS_BindCallable(cx, funcObj, vObj);
   CHECK(newCallable);
 
   jsval retval;
   bool called = JS_CallFunctionValue(cx, NULL, OBJECT_TO_JSVAL(newCallable),
                                      0, NULL, &retval);
   CHECK(called);
 
   CHECK(JSVAL_IS_INT(retval));
--- a/js/src/jsapi-tests/testBug604087.cpp
+++ b/js/src/jsapi-tests/testBug604087.cpp
@@ -22,70 +22,76 @@ struct OuterWrapper : js::DirectWrapper
 
     static OuterWrapper singleton;
 };
 
 OuterWrapper
 OuterWrapper::singleton;
 
 static JSObject *
-wrap(JSContext *cx, JSObject *toWrap, JSObject *target)
+wrap(JSContext *cx, JS::HandleObject toWrap, JS::HandleObject target)
 {
     JSAutoEnterCompartment ac;
     if (!ac.enter(cx, target))
         return NULL;
 
-    JSObject *wrapper = toWrap;
-    if (!JS_WrapObject(cx, &wrapper))
+    JS::RootedObject wrapper(cx, toWrap);
+    if (!JS_WrapObject(cx, wrapper.address()))
         return NULL;
     return wrapper;
 }
 
 static JSObject *
-SameCompartmentWrap(JSContext *cx, JSObject *obj)
+SameCompartmentWrap(JSContext *cx, JSObject *objArg)
 {
+    JS::RootedObject obj(cx, objArg);
     JS_GC(JS_GetRuntime(cx));
     return obj;
 }
 
 static JSObject *
-PreWrap(JSContext *cx, JSObject *scope, JSObject *obj, unsigned flags)
+PreWrap(JSContext *cx, JSObject *scopeArg, JSObject *objArg, unsigned flags)
 {
+    JS::RootedObject scope(cx, scopeArg);
+    JS::RootedObject obj(cx, objArg);
     JS_GC(JS_GetRuntime(cx));
     return obj;
 }
 
 static JSObject *
-Wrap(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent, unsigned flags)
+Wrap(JSContext *cx, JSObject *objArg, JSObject *protoArg, JSObject *parentArg, unsigned flags)
 {
+    JS::RootedObject obj(cx, objArg);
+    JS::RootedObject proto(cx, protoArg);
+    JS::RootedObject parent(cx, parentArg);
     return js::Wrapper::New(cx, obj, proto, parent, &js::CrossCompartmentWrapper::singleton);
 }
 
 BEGIN_TEST(testBug604087)
 {
-    JSObject *outerObj = js::Wrapper::New(cx, global, global->getProto(), global,
-                                          &OuterWrapper::singleton);
-    JSObject *compartment2 = JS_NewGlobalObject(cx, getGlobalClass(), NULL);
-    JSObject *compartment3 = JS_NewGlobalObject(cx, getGlobalClass(), NULL);
-    JSObject *compartment4 = JS_NewGlobalObject(cx, getGlobalClass(), NULL);
+    JS::RootedObject outerObj(cx, js::Wrapper::New(cx, global, global->getProto(), global,
+                                               &OuterWrapper::singleton));
+    JS::RootedObject compartment2(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL));
+    JS::RootedObject compartment3(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL));
+    JS::RootedObject compartment4(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL));
 
-    JSObject *c2wrapper = wrap(cx, outerObj, compartment2);
+    JS::RootedObject c2wrapper(cx, wrap(cx, outerObj, compartment2));
     CHECK(c2wrapper);
     js::SetProxyExtra(c2wrapper, 0, js::Int32Value(2));
 
-    JSObject *c3wrapper = wrap(cx, outerObj, compartment3);
+    JS::RootedObject c3wrapper(cx, wrap(cx, outerObj, compartment3));
     CHECK(c3wrapper);
     js::SetProxyExtra(c3wrapper, 0, js::Int32Value(3));
 
-    JSObject *c4wrapper = wrap(cx, outerObj, compartment4);
+    JS::RootedObject c4wrapper(cx, wrap(cx, outerObj, compartment4));
     CHECK(c4wrapper);
     js::SetProxyExtra(c4wrapper, 0, js::Int32Value(4));
     compartment4 = c4wrapper = NULL;
 
-    JSObject *next;
+    JS::RootedObject next(cx);
     {
         JSAutoEnterCompartment ac;
         CHECK(ac.enter(cx, compartment2));
         next = js::Wrapper::New(cx, compartment2, compartment2->getProto(), compartment2,
                                 &OuterWrapper::singleton);
         CHECK(next);
     }
 
--- a/js/src/jsapi-tests/testCallNonGenericMethodOnProxy.cpp
+++ b/js/src/jsapi-tests/testCallNonGenericMethodOnProxy.cpp
@@ -39,52 +39,52 @@ CustomMethod(JSContext *cx, unsigned arg
 {
   CallArgs args = CallArgsFromVp(argc, vp);
   return CallNonGenericMethod(cx, IsCustomClass, CustomMethodImpl, args);
 }
 
 BEGIN_TEST(test_CallNonGenericMethodOnProxy)
 {
   // Create the first global object and compartment
-  JSObject *globalA = JS_NewGlobalObject(cx, getGlobalClass(), NULL);
+  JS::RootedObject globalA(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL));
   CHECK(globalA);
 
-  JSObject *customA = JS_NewObject(cx, &CustomClass, NULL, NULL);
+  JS::RootedObject customA(cx, JS_NewObject(cx, &CustomClass, NULL, NULL));
   CHECK(customA);
   JS_SetReservedSlot(customA, CUSTOM_SLOT, Int32Value(17));
 
   JSFunction *customMethodA = JS_NewFunction(cx, CustomMethod, 0, 0, customA, "customMethodA");
   CHECK(customMethodA);
 
   jsval rval;
   CHECK(JS_CallFunction(cx, customA, customMethodA, 0, NULL, &rval));
   CHECK_SAME(rval, Int32Value(17));
 
   // Now create the second global object and compartment...
   {
-    JSObject *globalB = JS_NewGlobalObject(cx, getGlobalClass(), NULL);
+    JS::RootedObject globalB(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL));
     CHECK(globalB);
 
     // ...and enter it.
     JSAutoEnterCompartment enter;
     CHECK(enter.enter(cx, globalB));
 
-    JSObject *customB = JS_NewObject(cx, &CustomClass, NULL, NULL);
+    JS::RootedObject customB(cx, JS_NewObject(cx, &CustomClass, NULL, NULL));
     CHECK(customB);
     JS_SetReservedSlot(customB, CUSTOM_SLOT, Int32Value(42));
 
     JSFunction *customMethodB = JS_NewFunction(cx, CustomMethod, 0, 0, customB, "customMethodB");
     CHECK(customMethodB);
 
     jsval rval;
     CHECK(JS_CallFunction(cx, customB, customMethodB, 0, NULL, &rval));
     CHECK_SAME(rval, Int32Value(42));
 
-    JSObject *wrappedCustomA = customA;
-    CHECK(JS_WrapObject(cx, &wrappedCustomA));
+    JS::RootedObject wrappedCustomA(cx, customA);
+    CHECK(JS_WrapObject(cx, wrappedCustomA.address()));
 
     jsval rval2;
     CHECK(JS_CallFunction(cx, wrappedCustomA, customMethodB, 0, NULL, &rval2));
     CHECK_SAME(rval, Int32Value(42));
   }
 
   return true;
 }
--- a/js/src/jsapi-tests/testChromeBuffer.cpp
+++ b/js/src/jsapi-tests/testChromeBuffer.cpp
@@ -15,66 +15,72 @@ JSClass global_class = {
     JS_PropertyStub,
     JS_PropertyStub,
     JS_StrictPropertyStub,
     JS_EnumerateStub,
     JS_ResolveStub,
     JS_ConvertStub
 };
 
-JS::Anchor<JSObject *> trusted_glob, trusted_fun;
+JSObject *trusted_glob = NULL;
+JSObject *trusted_fun = NULL;
 
 JSBool
 CallTrusted(JSContext *cx, unsigned argc, jsval *vp)
 {
     if (!JS_SaveFrameChain(cx))
         return JS_FALSE;
 
     JSBool ok = JS_FALSE;
     {
         JSAutoEnterCompartment ac;
-        ok = ac.enter(cx, trusted_glob.get());
+        ok = ac.enter(cx, trusted_glob);
         if (!ok)
             goto out;
-        ok = JS_CallFunctionValue(cx, NULL, OBJECT_TO_JSVAL(trusted_fun.get()),
+        ok = JS_CallFunctionValue(cx, NULL, OBJECT_TO_JSVAL(trusted_fun),
                                   0, NULL, vp);
     }
   out:
     JS_RestoreFrameChain(cx);
     return ok;
 }
 
 BEGIN_TEST(testChromeBuffer)
 {
     JS_SetTrustedPrincipals(rt, &system_principals);
 
-    JSFunction *fun;
-    JSObject *o;
+    trusted_glob = JS_NewGlobalObject(cx, &global_class, &system_principals);
+    CHECK(trusted_glob);
 
-    CHECK(o = JS_NewGlobalObject(cx, &global_class, &system_principals));
-    trusted_glob.set(o);
+    if (!JS_AddNamedObjectRoot(cx, &trusted_glob, "trusted-global"))
+        return false;
+    if (!JS_AddNamedObjectRoot(cx, &trusted_fun, "trusted-function"))
+        return false;
+
+    JSFunction *fun;
 
     /*
      * Check that, even after untrusted content has exhausted the stack, code
      * compiled with "trusted principals" can run using reserved trusted-only
      * buffer space.
      */
     {
         {
             JSAutoEnterCompartment ac;
-            CHECK(ac.enter(cx, trusted_glob.get()));
+            CHECK(ac.enter(cx, trusted_glob));
             const char *paramName = "x";
             const char *bytes = "return x ? 1 + trusted(x-1) : 0";
-            CHECK(fun = JS_CompileFunctionForPrincipals(cx, trusted_glob.get(), &system_principals,
+            JS::HandleObject global = JS::HandleObject::fromMarkedLocation(&trusted_glob);
+            CHECK(fun = JS_CompileFunctionForPrincipals(cx, global, &system_principals,
                                                         "trusted", 1, &paramName, bytes, strlen(bytes),
                                                         "", 0));
-            trusted_fun.set(JS_GetFunctionObject(fun));
+            trusted_fun = JS_GetFunctionObject(fun);
         }
 
-        jsval v = OBJECT_TO_JSVAL(trusted_fun.get());
+        jsval v = OBJECT_TO_JSVAL(trusted_fun);
         CHECK(JS_WrapValue(cx, &v));
 
         const char *paramName = "trusted";
         const char *bytes = "try {                                      "
                             "  return untrusted(trusted);               "
                             "} catch (e) {                              "
                             "  return trusted(100);                     "
                             "}                                          ";
@@ -88,30 +94,31 @@ BEGIN_TEST(testChromeBuffer)
 
     /*
      * Check that content called from chrome in the reserved-buffer space
      * immediately ooms.
      */
     {
         {
             JSAutoEnterCompartment ac;
-            CHECK(ac.enter(cx, trusted_glob.get()));
+            CHECK(ac.enter(cx, trusted_glob));
             const char *paramName = "untrusted";
             const char *bytes = "try {                                  "
                                 "  untrusted();                         "
                                 "} catch (e) {                          "
                                 "  return 'From trusted: ' + e;         "
                                 "}                                      ";
-            CHECK(fun = JS_CompileFunctionForPrincipals(cx, trusted_glob.get(), &system_principals,
+            JS::HandleObject global = JS::HandleObject::fromMarkedLocation(&trusted_glob);
+            CHECK(fun = JS_CompileFunctionForPrincipals(cx, global, &system_principals,
                                                         "trusted", 1, &paramName, bytes, strlen(bytes),
                                                         "", 0));
-            trusted_fun.set(JS_GetFunctionObject(fun));
+            trusted_fun = JS_GetFunctionObject(fun);
         }
 
-        jsval v = OBJECT_TO_JSVAL(trusted_fun.get());
+        jsval v = OBJECT_TO_JSVAL(trusted_fun);
         CHECK(JS_WrapValue(cx, &v));
 
         const char *paramName = "trusted";
         const char *bytes = "try {                                      "
                             "  return untrusted(trusted);               "
                             "} catch (e) {                              "
                             "  return trusted(untrusted);               "
                             "}                                          ";
@@ -127,22 +134,23 @@ BEGIN_TEST(testChromeBuffer)
 
     /*
      * Check that JS_SaveFrameChain called on the way from content to chrome
      * (say, as done by XPCJSContextSTack::Push) works.
      */
     {
         {
             JSAutoEnterCompartment ac;
-            CHECK(ac.enter(cx, trusted_glob.get()));
+            CHECK(ac.enter(cx, trusted_glob));
             const char *bytes = "return 42";
-            CHECK(fun = JS_CompileFunctionForPrincipals(cx, trusted_glob.get(), &system_principals,
+            JS::HandleObject global = JS::HandleObject::fromMarkedLocation(&trusted_glob);
+            CHECK(fun = JS_CompileFunctionForPrincipals(cx, global, &system_principals,
                                                         "trusted", 0, NULL, bytes, strlen(bytes),
                                                         "", 0));
-            trusted_fun.set(JS_GetFunctionObject(fun));
+            trusted_fun = JS_GetFunctionObject(fun);
         }
 
         JSFunction *fun = JS_NewFunction(cx, CallTrusted, 0, 0, global, "callTrusted");
         JS::Anchor<JSObject *> callTrusted(JS_GetFunctionObject(fun));
 
         const char *paramName = "f";
         const char *bytes = "try {                                      "
                             "  return untrusted(trusted);               "
@@ -155,9 +163,14 @@ BEGIN_TEST(testChromeBuffer)
         jsval arg = OBJECT_TO_JSVAL(callTrusted.get());
         jsval rval;
         CHECK(JS_CallFunction(cx, NULL, fun, 1, &arg, &rval));
         CHECK(JSVAL_TO_INT(rval) == 42);
     }
 
     return true;
 }
+virtual void uninit() {
+    JS_RemoveObjectRoot(cx, &trusted_glob);
+    JS_RemoveObjectRoot(cx, &trusted_fun);
+    JSAPITest::uninit();
+}
 END_TEST(testChromeBuffer)
--- a/js/src/jsapi-tests/testClassGetter.cpp
+++ b/js/src/jsapi-tests/testClassGetter.cpp
@@ -52,22 +52,22 @@ static JSBool test_fn(JSContext *cx, uns
 
 static JSFunctionSpec ptestFunctions[] = {
     JS_FS( "test_fn", test_fn, 0, 0 ),
     JS_FS_END
 };
 
 BEGIN_TEST(testClassGetter_isCalled)
 {
-    CHECK(JS_InitClass(cx, JS_GetGlobalObject(cx), NULL, &ptestClass, PTest, 0,
+    CHECK(JS_InitClass(cx, global, NULL, &ptestClass, PTest, 0,
                        NULL, ptestFunctions, NULL, NULL));
 
     EXEC("function check() { var o = new PTest(); o.test_fn(); o.test_value1; o.test_value2; o.test_value1; }");
 
     for (int i = 1; i < 9; i++) {
-        jsvalRoot rval(cx);
-        CHECK(JS_CallFunctionName(cx, global, "check", 0, NULL, rval.addr()));
+        JS::RootedValue rval(cx);
+        CHECK(JS_CallFunctionName(cx, global, "check", 0, NULL, rval.address()));
         CHECK_SAME(INT_TO_JSVAL(called_test_fn), INT_TO_JSVAL(i));
         CHECK_SAME(INT_TO_JSVAL(called_test_prop_get), INT_TO_JSVAL(4 * i));
     }
     return true;
 }
 END_TEST(testClassGetter_isCalled)
--- a/js/src/jsapi-tests/testCloneScript.cpp
+++ b/js/src/jsapi-tests/testCloneScript.cpp
@@ -8,31 +8,32 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 
 #include "tests.h"
 #include "jsdbgapi.h"
 
 BEGIN_TEST(test_cloneScript)
 {
-    JSObject *A, *B;
+    JS::RootedObject A(cx, createGlobal());
+    JS::RootedObject B(cx, createGlobal());
 
-    CHECK(A = createGlobal());
-    CHECK(B = createGlobal());
+    CHECK(A);
+    CHECK(B);
 
     const char *source =
         "var i = 0;\n"
         "var sum = 0;\n"
         "while (i < 10) {\n"
         "    sum += i;\n"
         "    ++i;\n"
         "}\n"
         "(sum);\n";
 
-    JSObject *obj;
+    JS::RootedObject obj(cx);
 
     // compile for A
     {
         JSAutoEnterCompartment a;
         if (!a.enter(cx, A))
             return false;
 
         JSFunction *fun;
@@ -90,25 +91,26 @@ BEGIN_TEST(test_cloneScriptWithPrincipal
 {
     JS_InitDestroyPrincipalsCallback(rt, DestroyPrincipals);
 
     JSPrincipals *principalsA = new Principals();
     AutoDropPrincipals dropA(rt, principalsA);
     JSPrincipals *principalsB = new Principals();
     AutoDropPrincipals dropB(rt, principalsB);
 
-    JSObject *A, *B;
+    JS::RootedObject A(cx, createGlobal(principalsA));
+    JS::RootedObject B(cx, createGlobal(principalsB));
 
-    CHECK(A = createGlobal(principalsA));
-    CHECK(B = createGlobal(principalsB));
+    CHECK(A);
+    CHECK(B);
 
     const char *argnames[] = { "arg" };
     const char *source = "return function() { return arg; }";
 
-    JSObject *obj;
+    JS::RootedObject obj(cx);
 
     // Compile in A
     {
         JSAutoEnterCompartment a;
         if (!a.enter(cx, A))
             return false;
 
         JSFunction *fun;
@@ -124,17 +126,17 @@ BEGIN_TEST(test_cloneScriptWithPrincipal
     }
 
     // Clone into B
     {
         JSAutoEnterCompartment b;
         if (!b.enter(cx, B))
             return false;
 
-        JSObject *cloned;
+        JS::RootedObject cloned(cx);
         CHECK(cloned = JS_CloneFunctionObject(cx, obj, B));
 
         JSFunction *fun;
         CHECK(fun = JS_ValueToFunction(cx, JS::ObjectValue(*cloned)));
 
         JSScript *script;
         CHECK(script = JS_GetFunctionScript(cx, fun));
 
--- a/js/src/jsapi-tests/testConservativeGC.cpp
+++ b/js/src/jsapi-tests/testConservativeGC.cpp
@@ -3,38 +3,39 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "tests.h"
 #include "jsobj.h"
 #include "vm/String.h"
 
 BEGIN_TEST(testConservativeGC)
 {
-    jsval v2;
-    EVAL("({foo: 'bar'});", &v2);
+#ifndef JSGC_USE_EXACT_ROOTING
+    JS::RootedValue v2(cx);
+    EVAL("({foo: 'bar'});", v2.address());
     CHECK(v2.isObject());
     char objCopy[sizeof(JSObject)];
     js_memcpy(&objCopy, JSVAL_TO_OBJECT(v2), sizeof(JSObject));
 
-    jsval v3;
-    EVAL("String(Math.PI);", &v3);
+    JS::RootedValue v3(cx);
+    EVAL("String(Math.PI);", v3.address());
     CHECK(JSVAL_IS_STRING(v3));
     char strCopy[sizeof(JSString)];
     js_memcpy(&strCopy, JSVAL_TO_STRING(v3), sizeof(JSString));
 
     jsval tmp;
     EVAL("({foo2: 'bar2'});", &tmp);
     CHECK(tmp.isObject());
-    JSObject *obj2 = JSVAL_TO_OBJECT(tmp);
+    JS::RootedObject obj2(cx, JSVAL_TO_OBJECT(tmp));
     char obj2Copy[sizeof(JSObject)];
     js_memcpy(&obj2Copy, obj2, sizeof(JSObject));
 
     EVAL("String(Math.sqrt(3));", &tmp);
     CHECK(JSVAL_IS_STRING(tmp));
-    JSString *str2 = JSVAL_TO_STRING(tmp);
+    JS::RootedString str2(cx, JSVAL_TO_STRING(tmp));
     char str2Copy[sizeof(JSString)];
     js_memcpy(&str2Copy, str2, sizeof(JSString));
 
     tmp = JSVAL_NULL;
 
     JS_GC(rt);
 
     EVAL("var a = [];\n"
@@ -44,16 +45,17 @@ BEGIN_TEST(testConservativeGC)
 
     JS_GC(rt);
 
     checkObjectFields((JSObject *)objCopy, JSVAL_TO_OBJECT(v2));
     CHECK(!memcmp(strCopy, JSVAL_TO_STRING(v3), sizeof(strCopy)));
 
     checkObjectFields((JSObject *)obj2Copy, obj2);
     CHECK(!memcmp(str2Copy, str2, sizeof(str2Copy)));
+#endif /* JSGC_USE_EXACT_ROOTING */
 
     return true;
 }
 
 bool checkObjectFields(JSObject *savedCopy, JSObject *obj)
 {
     /* Ignore fields which are unstable across GCs. */
     CHECK(savedCopy->lastProperty() == obj->lastProperty());
--- a/js/src/jsapi-tests/testCustomIterator.cpp
+++ b/js/src/jsapi-tests/testCustomIterator.cpp
@@ -15,17 +15,17 @@ IterNext(JSContext *cx, unsigned argc, j
         return JS_ThrowStopIteration(cx);
     JS_SET_RVAL(cx, vp, INT_TO_JSVAL(count));
     return true;
 }
 
 static JSObject *
 IterHook(JSContext *cx, JS::HandleObject obj, JSBool keysonly)
 {
-    JSObject *iterObj = JS_NewObject(cx, NULL, NULL, NULL);
+    JS::RootedObject iterObj(cx, JS_NewObject(cx, NULL, NULL, NULL));
     if (!iterObj)
         return NULL;
     if (!JS_DefineFunction(cx, iterObj, "next", IterNext, 0, 0))
         return NULL;
     return iterObj;
 }
 
 js::Class HasCustomIterClass = {
@@ -60,17 +60,17 @@ IterClassConstructor(JSContext *cx, unsi
     if (!obj)
         return false;
     JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj));
     return true;
 }
 
 BEGIN_TEST(testCustomIterator_bug612523)
 {
-    CHECK(JS_InitClass(cx, JS_GetGlobalObject(cx), NULL, Jsvalify(&HasCustomIterClass),
+    CHECK(JS_InitClass(cx, global, NULL, Jsvalify(&HasCustomIterClass),
                        IterClassConstructor, 0, NULL, NULL, NULL, NULL));
 
     jsval result;
     EVAL("var o = new HasCustomIter(); \n"
          "var j = 0; \n"
          "for (var i in o) { ++j; }; \n"
          "j;", &result);
 
--- a/js/src/jsapi-tests/testDebugger.cpp
+++ b/js/src/jsapi-tests/testDebugger.cpp
@@ -112,17 +112,17 @@ END_TEST(testDebugger_getThisStrict)
 bool called = false;
 
 static JSTrapStatus
 ThrowHook(JSContext *cx, JSScript *, jsbytecode *, jsval *rval, void *closure)
 {
     JS_ASSERT(!closure);
     called = true;
 
-    JSObject *global = JS_GetGlobalForScopeChain(cx);
+    JS::RootedObject global(cx, JS_GetGlobalForScopeChain(cx));
 
     char text[] = "new Error()";
     jsval _;
     JS_EvaluateScript(cx, global, text, strlen(text), "", 0, &_);
 
     return JSTRAP_CONTINUE;
 }
 
@@ -145,28 +145,28 @@ BEGIN_TEST(testDebugger_throwHook)
     JS_SetOptions(cx, oldopts);
     return true;
 }
 END_TEST(testDebugger_throwHook)
 
 BEGIN_TEST(testDebugger_debuggerObjectVsDebugMode)
 {
     CHECK(JS_DefineDebuggerObject(cx, global));
-    JSObject *debuggee = JS_NewGlobalObject(cx, getGlobalClass(), NULL);
+    JS::RootedObject debuggee(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL));
     CHECK(debuggee);
 
     {
         JSAutoEnterCompartment ae;
         CHECK(ae.enter(cx, debuggee));
         CHECK(JS_SetDebugMode(cx, true));
         CHECK(JS_InitStandardClasses(cx, debuggee));
     }
 
-    JSObject *debuggeeWrapper = debuggee;
-    CHECK(JS_WrapObject(cx, &debuggeeWrapper));
+    JS::RootedObject debuggeeWrapper(cx, debuggee);
+    CHECK(JS_WrapObject(cx, debuggeeWrapper.address()));
     jsval v = OBJECT_TO_JSVAL(debuggeeWrapper);
     CHECK(JS_SetProperty(cx, global, "debuggee", &v));
 
     EVAL("var dbg = new Debugger(debuggee);\n"
          "var hits = 0;\n"
          "dbg.onDebuggerStatement = function () { hits++; };\n"
          "debuggee.eval('debugger;');\n"
          "hits;\n",
@@ -187,27 +187,26 @@ BEGIN_TEST(testDebugger_debuggerObjectVs
     return true;
 }
 END_TEST(testDebugger_debuggerObjectVsDebugMode)
 
 BEGIN_TEST(testDebugger_newScriptHook)
 {
     // Test that top-level indirect eval fires the newScript hook.
     CHECK(JS_DefineDebuggerObject(cx, global));
-    JSObject *g;
-    g = JS_NewGlobalObject(cx, getGlobalClass(), NULL);
+    JS::RootedObject g(cx, JS_NewGlobalObject(cx, getGlobalClass(), NULL));
     CHECK(g);
     {
         JSAutoEnterCompartment ae;
         CHECK(ae.enter(cx, g));
         CHECK(JS_InitStandardClasses(cx, g));
     }
 
-    JSObject *gWrapper = g;
-    CHECK(JS_WrapObject(cx, &gWrapper));
+    JS::RootedObject gWrapper(cx, g);
+    CHECK(JS_WrapObject(cx, gWrapper.address()));
     jsval v = OBJECT_TO_JSVAL(gWrapper);
     CHECK(JS_SetProperty(cx, global, "g", &v));
 
     EXEC("var dbg = Debugger(g);\n"
          "var hits = 0;\n"
          "dbg.onNewScript = function (s) {\n"
          "    hits += Number(s instanceof Debugger.Script);\n"
          "};\n");
@@ -216,17 +215,17 @@ BEGIN_TEST(testDebugger_newScriptHook)
     // what scope object we use to enter the compartment.
     //
     // Scripts are associated with the global where they're compiled, so we
     // deliver them only to debuggers that are watching that particular global.
     //
     return testIndirectEval(g, "Math.abs(0)");
 }
 
-bool testIndirectEval(JSObject *scope, const char *code)
+bool testIndirectEval(JS::HandleObject scope, const char *code)
 {
     EXEC("hits = 0;");
 
     {
         JSAutoEnterCompartment ae;
         CHECK(ae.enter(cx, scope));
         JSString *codestr = JS_NewStringCopyZ(cx, code);
         CHECK(codestr);
--- a/js/src/jsapi-tests/testDeepFreeze.cpp
+++ b/js/src/jsapi-tests/testDeepFreeze.cpp
@@ -7,33 +7,35 @@
 
 
 #include "tests.h"
 
 BEGIN_TEST(testDeepFreeze_bug535703)
 {
     jsval v;
     EVAL("var x = {}; x;", &v);
-    CHECK(JS_DeepFreezeObject(cx, JSVAL_TO_OBJECT(v)));  // don't crash
+    JS::RootedObject obj(cx, JSVAL_TO_OBJECT(v));
+    CHECK(JS_DeepFreezeObject(cx, obj));  // don't crash
     EVAL("Object.isFrozen(x)", &v);
     CHECK_SAME(v, JSVAL_TRUE);
     return true;
 }
 END_TEST(testDeepFreeze_bug535703)
 
 BEGIN_TEST(testDeepFreeze_deep)
 {
     jsval a, o;
     EXEC("var a = {}, o = a;\n"
          "for (var i = 0; i < 5000; i++)\n"
          "    a = {x: a, y: a};\n");
     EVAL("a", &a);
     EVAL("o", &o);
 
-    CHECK(JS_DeepFreezeObject(cx, JSVAL_TO_OBJECT(a)));
+    JS::RootedObject aobj(cx, JSVAL_TO_OBJECT(a));
+    CHECK(JS_DeepFreezeObject(cx, aobj));
 
     jsval b;
     EVAL("Object.isFrozen(a)", &b);
     CHECK_SAME(b, JSVAL_TRUE);
     EVAL("Object.isFrozen(o)", &b);
     CHECK_SAME(b, JSVAL_TRUE);
     return true;
 }
@@ -41,17 +43,18 @@ END_TEST(testDeepFreeze_deep)
 
 BEGIN_TEST(testDeepFreeze_loop)
 {
     jsval x, y;
     EXEC("var x = [], y = {x: x}; y.y = y; x.push(x, y);");
     EVAL("x", &x);
     EVAL("y", &y);
 
-    CHECK(JS_DeepFreezeObject(cx, JSVAL_TO_OBJECT(x)));
+    JS::RootedObject xobj(cx, JSVAL_TO_OBJECT(x));
+    CHECK(JS_DeepFreezeObject(cx, xobj));
 
     jsval b;
     EVAL("Object.isFrozen(x)", &b);
     CHECK_SAME(b, JSVAL_TRUE);
     EVAL("Object.isFrozen(y)", &b);
     CHECK_SAME(b, JSVAL_TRUE);
     return true;
 }
--- a/js/src/jsapi-tests/testDefineGetterSetterNonEnumerable.cpp
+++ b/js/src/jsapi-tests/testDefineGetterSetterNonEnumerable.cpp
@@ -13,49 +13,47 @@ native(JSContext *cx, unsigned argc, jsv
 {
     return JS_TRUE;
 }
 
 static const char PROPERTY_NAME[] = "foo";
 
 BEGIN_TEST(testDefineGetterSetterNonEnumerable)
 {
-    jsvalRoot vobj(cx);
-    JSObject *obj = JS_NewObject(cx, NULL, NULL, NULL);
+    JS::RootedValue vobj(cx);
+    JS::RootedObject obj(cx, JS_NewObject(cx, NULL, NULL, NULL));
     CHECK(obj);
     vobj = OBJECT_TO_JSVAL(obj);
 
-    jsvalRoot vget(cx);
     JSFunction *funGet = JS_NewFunction(cx, native, 0, 0, NULL, "get");
     CHECK(funGet);
-    JSObject *funGetObj = JS_GetFunctionObject(funGet);
-    vget = OBJECT_TO_JSVAL(funGetObj);
+    JS::RootedObject funGetObj(cx, JS_GetFunctionObject(funGet));
+    JS::RootedValue vget(cx, OBJECT_TO_JSVAL(funGetObj));
 
-    jsvalRoot vset(cx);
     JSFunction *funSet = JS_NewFunction(cx, native, 1, 0, NULL, "set");
     CHECK(funSet);
-    JSObject *funSetObj = JS_GetFunctionObject(funSet);
-    vset = OBJECT_TO_JSVAL(funSetObj);
+    JS::RootedObject funSetObj(cx, JS_GetFunctionObject(funSet));
+    JS::RootedValue vset(cx, OBJECT_TO_JSVAL(funSetObj));
 
-    CHECK(JS_DefineProperty(cx, JSVAL_TO_OBJECT(vobj), PROPERTY_NAME,
+    JS::RootedObject vObject(cx, JSVAL_TO_OBJECT(vobj));
+    CHECK(JS_DefineProperty(cx, vObject, PROPERTY_NAME,
                             JSVAL_VOID,
-                            JS_DATA_TO_FUNC_PTR(JSPropertyOp, funGetObj),
-                            JS_DATA_TO_FUNC_PTR(JSStrictPropertyOp, funSetObj),
+                            JS_DATA_TO_FUNC_PTR(JSPropertyOp, (JSObject*) funGetObj),
+                            JS_DATA_TO_FUNC_PTR(JSStrictPropertyOp, (JSObject*) funSetObj),
                             JSPROP_GETTER | JSPROP_SETTER | JSPROP_ENUMERATE));
 
-    CHECK(JS_DefineProperty(cx, JSVAL_TO_OBJECT(vobj), PROPERTY_NAME,
+    CHECK(JS_DefineProperty(cx, vObject, PROPERTY_NAME,
                             JSVAL_VOID,
-                            JS_DATA_TO_FUNC_PTR(JSPropertyOp, funGetObj),
-                            JS_DATA_TO_FUNC_PTR(JSStrictPropertyOp, funSetObj),
+                            JS_DATA_TO_FUNC_PTR(JSPropertyOp, (JSObject*) funGetObj),
+                            JS_DATA_TO_FUNC_PTR(JSStrictPropertyOp, (JSObject*) funSetObj),
                             JSPROP_GETTER | JSPROP_SETTER | JSPROP_PERMANENT));
 
     JSBool found = JS_FALSE;
     unsigned attrs = 0;
-    CHECK(JS_GetPropertyAttributes(cx, JSVAL_TO_OBJECT(vobj), PROPERTY_NAME,
-                                   &attrs, &found));
+    CHECK(JS_GetPropertyAttributes(cx, vObject, PROPERTY_NAME, &attrs, &found));
     CHECK(found);
     CHECK(attrs & JSPROP_GETTER);
     CHECK(attrs & JSPROP_SETTER);
     CHECK(attrs & JSPROP_PERMANENT);
     CHECK(!(attrs & JSPROP_ENUMERATE));
 
     return true;
 }
--- a/js/src/jsapi-tests/testDefineProperty.cpp
+++ b/js/src/jsapi-tests/testDefineProperty.cpp
@@ -5,20 +5,20 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 
 #include "tests.h"
 
 BEGIN_TEST(testDefineProperty_bug564344)
 {
-    jsvalRoot x(cx);
+    JS::RootedValue x(cx);
     EVAL("function f() {}\n"
          "var x = {p: f};\n"
          "x.p();  // brand x's scope\n"
-         "x;", x.addr());
+         "x;", x.address());
 
-    JSObject *obj = JSVAL_TO_OBJECT(x.value());
+    JS::RootedObject obj(cx, JSVAL_TO_OBJECT(x));
     for (int i = 0; i < 2; i++)
         CHECK(JS_DefineProperty(cx, obj, "q", JSVAL_VOID, NULL, NULL, JSPROP_SHARED));
     return true;
 }
 END_TEST(testDefineProperty_bug564344)
--- a/js/src/jsapi-tests/testFunctionProperties.cpp
+++ b/js/src/jsapi-tests/testFunctionProperties.cpp
@@ -5,23 +5,23 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 
 #include "tests.h"
 
 BEGIN_TEST(testFunctionProperties)
 {
-    jsvalRoot x(cx);
-    EVAL("(function f() {})", x.addr());
+    JS::RootedValue x(cx);
+    EVAL("(function f() {})", x.address());
 
-    JSObject *obj = JSVAL_TO_OBJECT(x.value());
-    jsvalRoot y(cx);
+    JS::RootedObject obj(cx, JSVAL_TO_OBJECT(x));
 
-    CHECK(JS_GetProperty(cx, obj, "arguments", y.addr()));
+    JS::RootedValue y(cx);
+    CHECK(JS_GetProperty(cx, obj, "arguments", y.address()));
     CHECK_SAME(y, JSVAL_NULL);
 
-    CHECK(JS_GetProperty(cx, obj, "caller", y.addr()));
+    CHECK(JS_GetProperty(cx, obj, "caller", y.address()));
     CHECK_SAME(y, JSVAL_NULL);
 
     return true;
 }
 END_TEST(testFunctionProperties)
--- a/js/src/jsapi-tests/testGCOutOfMemory.cpp
+++ b/js/src/jsapi-tests/testGCOutOfMemory.cpp
@@ -16,40 +16,40 @@ ErrorCounter(JSContext *cx, const char *
 {
     ++errorCount;
 }
 
 BEGIN_TEST(testGCOutOfMemory)
 {
     JS_SetErrorReporter(cx, ErrorCounter);
 
-    jsvalRoot root(cx);
+    JS::RootedValue root(cx);
 
     static const char source[] =
         "var max = 0; (function() {"
         "    var array = [];"
         "    for (; ; ++max)"
         "        array.push({});"
         "    array = []; array.push(0);"
         "})();";
     JSBool ok = JS_EvaluateScript(cx, global, source, strlen(source), "", 1,
-                                  root.addr());
+                                  root.address());
 
     /* Check that we get OOM. */
     CHECK(!ok);
     CHECK(!JS_IsExceptionPending(cx));
     CHECK_EQUAL(errorCount, 1);
     JS_GC(rt);
     EVAL("(function() {"
          "    var array = [];"
          "    for (var i = max >> 2; i != 0;) {"
          "        --i;"
          "        array.push({});"
          "    }"
-         "})();", root.addr());
+         "})();", root.address());
     CHECK_EQUAL(errorCount, 1);
     return true;
 }
 
 virtual JSRuntime * createRuntime() {
     return JS_NewRuntime(512 * 1024);
 }
 
--- a/js/src/jsapi-tests/testGetPropertyDefault.cpp
+++ b/js/src/jsapi-tests/testGetPropertyDefault.cpp
@@ -21,17 +21,17 @@ stringToId(JSContext *cx, const char *s,
     return JS_ValueToId(cx, STRING_TO_JSVAL(str), idp);
 }
 
 BEGIN_TEST(testGetPropertyDefault_bug594060)
 {
     {
         // Check JS_GetPropertyDefault
 
-        JSObject *obj = JS_NewObject(cx, NULL, NULL, NULL);
+        JS::RootedObject obj(cx, JS_NewObject(cx, NULL, NULL, NULL));
         CHECK(obj);
 
         jsval v0 = JSVAL_TRUE;
         CHECK(JS_SetProperty(cx, obj, "here", &v0));
 
         jsval v1;
         CHECK(JS_GetPropertyDefault(cx, obj, "here", JSVAL_FALSE, &v1));
         CHECK(JSVAL_IS_TRUE(v1));
@@ -39,17 +39,17 @@ BEGIN_TEST(testGetPropertyDefault_bug594
         jsval v2;
         CHECK(JS_GetPropertyDefault(cx, obj, "nothere", JSVAL_FALSE, &v2));
         CHECK(JSVAL_IS_FALSE(v2));
     }
 
     {
         // Check JS_GetPropertyByIdDefault
 
-        JSObject *obj = JS_NewObject(cx, NULL, NULL, NULL);
+        JS::RootedObject obj(cx, JS_NewObject(cx, NULL, NULL, NULL));
         CHECK(obj);
 
         jsid hereid;
         CHECK(stringToId(cx, "here", &hereid));
 
         jsid nothereid;
         CHECK(stringToId(cx, "nothere", &nothereid));
 
--- a/js/src/jsapi-tests/testIntString.cpp
+++ b/js/src/jsapi-tests/testIntString.cpp
@@ -6,39 +6,39 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 
 #include "tests.h"
 #include "vm/String.h"
 
 BEGIN_TEST(testIntString_bug515273)
 {
-    jsvalRoot v(cx);
+    JS::RootedValue v(cx);
 
-    EVAL("'1';", v.addr());
-    JSString *str = JSVAL_TO_STRING(v.value());
+    EVAL("'1';", v.address());
+    JSString *str = JSVAL_TO_STRING(v);
     CHECK(JS_StringHasBeenInterned(cx, str));
     CHECK(JS_FlatStringEqualsAscii(JS_ASSERT_STRING_IS_FLAT(str), "1"));
 
-    EVAL("'42';", v.addr());
-    str = JSVAL_TO_STRING(v.value());
+    EVAL("'42';", v.address());
+    str = JSVAL_TO_STRING(v);
     CHECK(JS_StringHasBeenInterned(cx, str));
     CHECK(JS_FlatStringEqualsAscii(JS_ASSERT_STRING_IS_FLAT(str), "42"));
 
-    EVAL("'111';", v.addr());
-    str = JSVAL_TO_STRING(v.value());
+    EVAL("'111';", v.address());
+    str = JSVAL_TO_STRING(v);
     CHECK(JS_StringHasBeenInterned(cx, str));
     CHECK(JS_FlatStringEqualsAscii(JS_ASSERT_STRING_IS_FLAT(str), "111"));
 
     /* Test other types of static strings. */
-    EVAL("'a';", v.addr());
-    str = JSVAL_TO_STRING(v.value());
+    EVAL("'a';", v.address());
+    str = JSVAL_TO_STRING(v);
     CHECK(JS_StringHasBeenInterned(cx, str));
     CHECK(JS_FlatStringEqualsAscii(JS_ASSERT_STRING_IS_FLAT(str), "a"));
 
-    EVAL("'bc';", v.addr());
-    str = JSVAL_TO_STRING(v.value());
+    EVAL("'bc';", v.address());
+    str = JSVAL_TO_STRING(v);
     CHECK(JS_StringHasBeenInterned(cx, str));
     CHECK(JS_FlatStringEqualsAscii(JS_ASSERT_STRING_IS_FLAT(str), "bc"));
 
     return true;
 }
 END_TEST(testIntString_bug515273)
--- a/js/src/jsapi-tests/testJSEvaluateScript.cpp
+++ b/js/src/jsapi-tests/testJSEvaluateScript.cpp
@@ -1,18 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sw=4 et tw=99:
  */
 
 #include "tests.h"
 
 BEGIN_TEST(testJSEvaluateScript)
 {
-    jsvalRoot proto(cx);
-    JSObject *obj = JS_NewObject(cx, NULL, NULL, global);
+    JS::RootedObject obj(cx, JS_NewObject(cx, NULL, NULL, global));
     CHECK(obj);
 
     uint32_t options = JS_GetOptions(cx);
     CHECK(options & JSOPTION_VAROBJFIX);
 
     static const char src[] = "var x = 5;";
 
     JS::Value retval;
--- a/js/src/jsapi-tests/testLookup.cpp
+++ b/js/src/jsapi-tests/testLookup.cpp
@@ -9,49 +9,49 @@
 #include "tests.h"
 #include "jsfun.h"  // for js::IsInternalFunctionObject
 
 #include "jsobjinlines.h"
 
 BEGIN_TEST(testLookup_bug522590)
 {
     // Define a function that makes method-bearing objects.
-    jsvalRoot x(cx);
+    JS::RootedValue x(cx);
     EXEC("function mkobj() { return {f: function () {return 2;}} }");
 
     // Calling mkobj() multiple times must create multiple functions in ES5.
-    EVAL("mkobj().f !== mkobj().f", x.addr());
+    EVAL("mkobj().f !== mkobj().f", x.address());
     CHECK_SAME(x, JSVAL_TRUE);
 
     // Now make x.f a method.
-    EVAL("mkobj()", x.addr());
-    JSObject *xobj = JSVAL_TO_OBJECT(x);
+    EVAL("mkobj()", x.address());
+    JS::RootedObject xobj(cx, JSVAL_TO_OBJECT(x));
 
     // This lookup must not return an internal function object.
-    jsvalRoot r(cx);
-    CHECK(JS_LookupProperty(cx, xobj, "f", r.addr()));
-    CHECK(r.value().isObject());
-    JSObject *funobj = &r.value().toObject();
+    JS::RootedValue r(cx);
+    CHECK(JS_LookupProperty(cx, xobj, "f", r.address()));
+    CHECK(r.isObject());
+    JSObject *funobj = &r.toObject();
     CHECK(funobj->isFunction());
     CHECK(!js::IsInternalFunctionObject(funobj));
 
     return true;
 }
 END_TEST(testLookup_bug522590)
 
 JSBool
 document_resolve(JSContext *cx, JSHandleObject obj, JSHandleId id, unsigned flags,
                  JSMutableHandleObject objp)
 {
     // If id is "all", and we're not detecting, resolve document.all=true.
-    jsvalRoot v(cx);
-    if (!JS_IdToValue(cx, id, v.addr()))
+    JS::RootedValue v(cx);
+    if (!JS_IdToValue(cx, id, v.address()))
         return false;
-    if (JSVAL_IS_STRING(v.value())) {
-        JSString *str = JSVAL_TO_STRING(v.value());
+    if (JSVAL_IS_STRING(v)) {
+        JSString *str = JSVAL_TO_STRING(v);
         JSFlatString *flatStr = JS_FlattenString(cx, str);
         if (!flatStr)
             return false;
         if (JS_FlatStringEqualsAscii(flatStr, "all") && !(flags & JSRESOLVE_DETECTING)) {
             JSBool ok = JS_DefinePropertyById(cx, obj, id, JSVAL_TRUE, NULL, NULL, 0);
             objp.set(ok ? obj.get() : NULL);
             return ok;
         }
@@ -63,19 +63,19 @@ document_resolve(JSContext *cx, JSHandle
 static JSClass document_class = {
     "document", JSCLASS_NEW_RESOLVE,
     JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
     JS_EnumerateStub, (JSResolveOp) document_resolve, JS_ConvertStub
 };
 
 BEGIN_TEST(testLookup_bug570195)
 {
-    JSObject *obj = JS_NewObject(cx, &document_class, NULL, NULL);
+    JS::RootedObject obj(cx, JS_NewObject(cx, &document_class, NULL, NULL));
     CHECK(obj);
     CHECK(JS_DefineProperty(cx, global, "document", OBJECT_TO_JSVAL(obj), NULL, NULL, 0));
-    jsvalRoot v(cx);
-    EVAL("document.all ? true : false", v.addr());
-    CHECK_SAME(v.value(), JSVAL_FALSE);
-    EVAL("document.hasOwnProperty('all')", v.addr());
-    CHECK_SAME(v.value(), JSVAL_FALSE);
+    JS::RootedValue v(cx);
+    EVAL("document.all ? true : false", v.address());
+    CHECK_SAME(v, JSVAL_FALSE);
+    EVAL("document.hasOwnProperty('all')", v.address());
+    CHECK_SAME(v, JSVAL_FALSE);
     return true;
 }
 END_TEST(testLookup_bug570195)
--- a/js/src/jsapi-tests/testLooselyEqual.cpp
+++ b/js/src/jsapi-tests/testLooselyEqual.cpp
@@ -26,17 +26,17 @@ struct LooseEqualityFixture : public JSA
         if (!JSAPITest::init())
             return false;
         qNaN = DOUBLE_TO_JSVAL(numeric_limits<double>::quiet_NaN());
         sNaN = DOUBLE_TO_JSVAL(numeric_limits<double>::signaling_NaN());
         d42 = DOUBLE_TO_JSVAL(42.0);
         i42 = INT_TO_JSVAL(42);
         undef = JSVAL_VOID;
         null = JSVAL_NULL;
-        obj = OBJECT_TO_JSVAL(global);
+        obj = OBJECT_TO_JSVAL(JS_GetGlobalObject(cx));
         poszero = DOUBLE_TO_JSVAL(0.0);
         negzero = DOUBLE_TO_JSVAL(-0.0);
 #ifdef XP_WIN
 # define copysign _copysign
 #endif
         JS_ASSERT(copysign(1.0, JSVAL_TO_DOUBLE(poszero)) == 1.0);
         JS_ASSERT(copysign(1.0, JSVAL_TO_DOUBLE(negzero)) == -1.0);
 #ifdef XP_WIN
--- a/js/src/jsapi-tests/testNewObject.cpp
+++ b/js/src/jsapi-tests/testNewObject.cpp
@@ -12,17 +12,17 @@
 
 const size_t N = 1000;
 static jsval argv[N];
 
 static JSBool
 constructHook(JSContext *cx, unsigned argc, jsval *vp)
 {
     // Check that arguments were passed properly from JS_New.
-    JSObject *callee = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
+    JS::RootedObject callee(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));
 
     JSObject *obj = JS_NewObjectForConstructor(cx, js::Jsvalify(&js::ObjectClass), vp);
     if (!obj) {
         JS_ReportError(cx, "test failed, could not construct object");
         return false;
     }
     if (strcmp(JS_GetClass(obj)->name, "Object") != 0) {
         JS_ReportError(cx, "test failed, wrong class for 'this'");
@@ -47,24 +47,29 @@ constructHook(JSContext *cx, unsigned ar
 
     *vp = OBJECT_TO_JSVAL(obj);
     argv[0] = argv[1] = argv[2] = JSVAL_VOID;  // trash the argv, perversely
     return true;
 }
 
 BEGIN_TEST(testNewObject_1)
 {
-    jsval v;
-    EVAL("Array", &v);
-    JSObject *Array = JSVAL_TO_OBJECT(v);
+    // Root the global argv test array. Only the first 2 entries really need to
+    // be rooted, since we're only putting integers in the rest.
+    CHECK(JS_AddNamedValueRoot(cx, &argv[0], "argv0"));
+    CHECK(JS_AddNamedValueRoot(cx, &argv[1], "argv1"));
+
+    JS::RootedValue v(cx);
+    EVAL("Array", v.address());
+    JS::RootedObject Array(cx, JSVAL_TO_OBJECT(v));
 
     // With no arguments.
-    JSObject *obj = JS_New(cx, Array, 0, NULL);
+    JS::RootedObject obj(cx, JS_New(cx, Array, 0, NULL));
     CHECK(obj);
-    jsvalRoot rt(cx, OBJECT_TO_JSVAL(obj));
+    JS::RootedValue rt(cx, OBJECT_TO_JSVAL(obj));
     CHECK(JS_IsArrayObject(cx, obj));
     uint32_t len;
     CHECK(JS_GetArrayLength(cx, obj, &len));
     CHECK_EQUAL(len, 0);
 
     // With one argument.
     argv[0] = INT_TO_JSVAL(4);
     obj = JS_New(cx, Array, 1, argv);
@@ -78,29 +83,33 @@ BEGIN_TEST(testNewObject_1)
     for (size_t i = 0; i < N; i++)
         argv[i] = INT_TO_JSVAL(i);
     obj = JS_New(cx, Array, N, argv);
     CHECK(obj);
     rt = OBJECT_TO_JSVAL(obj);
     CHECK(JS_IsArrayObject(cx, obj));
     CHECK(JS_GetArrayLength(cx, obj, &len));
     CHECK_EQUAL(len, N);
-    CHECK(JS_GetElement(cx, obj, N - 1, &v));
+    CHECK(JS_GetElement(cx, obj, N - 1, v.address()));
     CHECK_SAME(v, INT_TO_JSVAL(N - 1));
 
     // With JSClass.construct.
     static JSClass cls = {
         "testNewObject_1",
         0,
         JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
         JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, NULL,
         NULL, NULL, NULL, constructHook
     };
-    JSObject *ctor = JS_NewObject(cx, &cls, NULL, NULL);
+    JS::RootedObject ctor(cx, JS_NewObject(cx, &cls, NULL, NULL));
     CHECK(ctor);
-    jsvalRoot rt2(cx, OBJECT_TO_JSVAL(ctor));
+    JS::RootedValue rt2(cx, OBJECT_TO_JSVAL(ctor));
     obj = JS_New(cx, ctor, 3, argv);
     CHECK(obj);
-    CHECK(JS_GetElement(cx, ctor, 0, &v));
+    CHECK(JS_GetElement(cx, ctor, 0, v.address()));
     CHECK_SAME(v, JSVAL_ZERO);
+
+    JS_RemoveValueRoot(cx, &argv[0]);
+    JS_RemoveValueRoot(cx, &argv[1]);
+
     return true;
 }
 END_TEST(testNewObject_1)
--- a/js/src/jsapi-tests/testOps.cpp
+++ b/js/src/jsapi-tests/testOps.cpp
@@ -48,16 +48,16 @@ static JSFunctionSpec s_functions[] =
 
 BEGIN_TEST(testOps_bug559006)
 {
     CHECK(JS_DefineFunctions(cx, global, s_functions));
 
     EXEC("function main() { while(1) return 0 + createMyObject(); }");
 
     for (int i = 0; i < 9; i++) {
-        jsvalRoot rval(cx);
-        CHECK(JS_CallFunctionName(cx, global, "main", 0, NULL, rval.addr()));
+        JS::RootedValue rval(cx);
+        CHECK(JS_CallFunctionName(cx, global, "main", 0, NULL, rval.address()));
         CHECK_SAME(rval, INT_TO_JSVAL(123));
     }
     return true;
 }
 END_TEST(testOps_bug559006)
 
--- a/js/src/jsapi-tests/testOriginPrincipals.cpp
+++ b/js/src/jsapi-tests/testOriginPrincipals.cpp
@@ -73,16 +73,17 @@ bool
 eval(const char *asciiChars, JSPrincipals *principals, JSPrincipals *originPrincipals, jsval *rval)
 {
     size_t len = strlen(asciiChars);
     jschar *chars = new jschar[len+1];
     for (size_t i = 0; i < len; ++i)
         chars[i] = asciiChars[i];
     chars[len] = 0;
 
+    JS::RootedObject global(cx, JS_GetGlobalObject(cx));
     bool ok = JS_EvaluateUCScriptForPrincipalsVersionOrigin(cx, global,
                                                             principals,
                                                             originPrincipals,
                                                             chars, len, "", 0, rval,
                                                             JSVERSION_DEFAULT);
     delete[] chars;
     return ok;
 }
--- a/js/src/jsapi-tests/testParseJSON.cpp
+++ b/js/src/jsapi-tests/testParseJSON.cpp
@@ -52,17 +52,17 @@ BEGIN_TEST(testParseJSON_success)
     CHECK(TryParse(cx, "0", INT_TO_JSVAL(0)));
     CHECK(TryParse(cx, "1", INT_TO_JSVAL(1)));
     CHECK(TryParse(cx, "-1", INT_TO_JSVAL(-1)));
     CHECK(TryParse(cx, "1", DOUBLE_TO_JSVAL(1)));
     CHECK(TryParse(cx, "1.75", DOUBLE_TO_JSVAL(1.75)));
     CHECK(TryParse(cx, "9e9", DOUBLE_TO_JSVAL(9e9)));
     CHECK(TryParse(cx, "9e99999", DOUBLE_TO_JSVAL(std::numeric_limits<double>::infinity())));
 
-    JSFlatString *str;
+    JS::Rooted<JSFlatString*> str(cx);
 
     const jschar emptystr[] = { '\0' };
     str = js_NewStringCopyN(cx, emptystr, 0);
     CHECK(str);
     CHECK(TryParse(cx, "\"\"", STRING_TO_JSVAL(str)));
 
     const jschar nullstr[] = { '\0' };
     str = NewString(cx, nullstr);
@@ -78,65 +78,66 @@ BEGIN_TEST(testParseJSON_success)
     const jschar newlinestr[] = { '\n', };
     str = NewString(cx, newlinestr);
     CHECK(str);
     CHECK(TryParse(cx, "\"\\n\"", STRING_TO_JSVAL(str)));
     CHECK(TryParse(cx, "\"\\u000A\"", STRING_TO_JSVAL(str)));
 
 
     // Arrays
-    jsval v, v2;
-    JSObject *obj;
+    JS::RootedValue v(cx), v2(cx);
+    JS::RootedObject obj(cx);
 
-    CHECK(Parse(cx, "[]", &v));
+    CHECK(Parse(cx, "[]", v.address()));
     CHECK(!JSVAL_IS_PRIMITIVE(v));
     obj = JSVAL_TO_OBJECT(v);
     CHECK(JS_IsArrayObject(cx, obj));
-    CHECK(JS_GetProperty(cx, obj, "length", &v2));
+    CHECK(JS_GetProperty(cx, obj, "length", v2.address()));
     CHECK_SAME(v2, JSVAL_ZERO);
 
-    CHECK(Parse(cx, "[1]", &v));
+    CHECK(Parse(cx, "[1]", v.address()));
     CHECK(!JSVAL_IS_PRIMITIVE(v));
     obj = JSVAL_TO_OBJECT(v);
     CHECK(JS_IsArrayObject(cx, obj));
-    CHECK(JS_GetProperty(cx, obj, "0", &v2));
+    CHECK(JS_GetProperty(cx, obj, "0", v2.address()));
     CHECK_SAME(v2, JSVAL_ONE);
-    CHECK(JS_GetProperty(cx, obj, "length", &v2));
+    CHECK(JS_GetProperty(cx, obj, "length", v2.address()));
     CHECK_SAME(v2, JSVAL_ONE);
 
 
     // Objects
-    CHECK(Parse(cx, "{}", &v));
+    CHECK(Parse(cx, "{}", v.address()));
     CHECK(!JSVAL_IS_PRIMITIVE(v));
     obj = JSVAL_TO_OBJECT(v);
     CHECK(!JS_IsArrayObject(cx, obj));
 
-    CHECK(Parse(cx, "{ \"f\": 17 }", &v));
+    CHECK(Parse(cx, "{ \"f\": 17 }", v.address()));
     CHECK(!JSVAL_IS_PRIMITIVE(v));
     obj = JSVAL_TO_OBJECT(v);
     CHECK(!JS_IsArrayObject(cx, obj));
-    CHECK(JS_GetProperty(cx, obj, "f", &v2));
+    CHECK(JS_GetProperty(cx, obj, "f", v2.address()));
     CHECK_SAME(v2, INT_TO_JSVAL(17));
 
     return true;
 }
 
 template<size_t N> inline bool
 Parse(JSContext *cx, const char (&input)[N], jsval *vp)
 {
     AutoInflatedString str(cx);
     str = input;
     CHECK(JS_ParseJSON(cx, str.chars(), str.length(), vp));
     return true;
 }
 
 template<size_t N> inline bool
-TryParse(JSContext *cx, const char (&input)[N], const jsval &expected)
+TryParse(JSContext *cx, const char (&input)[N], const jsval &expectedArg)
 {
     AutoInflatedString str(cx);
+    JS::RootedValue expected(cx, expectedArg);
     jsval v;
     str = input;
     CHECK(JS_ParseJSON(cx, str.chars(), str.length(), &v));
     CHECK_SAME(v, expected);
     return true;
 }
 END_TEST(testParseJSON_success)
 
@@ -209,32 +210,32 @@ Censor(JSContext *cx, unsigned argc, jsv
     return true;
 }
 
 BEGIN_TEST(testParseJSON_reviver)
 {
     JSFunction *fun = JS_NewFunction(cx, Censor, 0, 0, global, "censor");
     CHECK(fun);
 
-    jsval filter = OBJECT_TO_JSVAL(JS_GetFunctionObject(fun));
+    JS::RootedValue filter(cx, OBJECT_TO_JSVAL(JS_GetFunctionObject(fun)));
 
     CHECK(TryParse(cx, "true", filter));
     CHECK(TryParse(cx, "false", filter));
     CHECK(TryParse(cx, "null", filter));
     CHECK(TryParse(cx, "1", filter));
     CHECK(TryParse(cx, "1.75", filter));
     CHECK(TryParse(cx, "[]", filter));
     CHECK(TryParse(cx, "[1]", filter));
     CHECK(TryParse(cx, "{}", filter));
     return true;
 }
 
 template<size_t N> inline bool
-TryParse(JSContext *cx, const char (&input)[N], jsval filter)
+TryParse(JSContext *cx, const char (&input)[N], JS::HandleValue filter)
 {
     AutoInflatedString str(cx);
-    jsval v;
+    JS::RootedValue v(cx);
     str = input;
-    CHECK(JS_ParseJSONWithReviver(cx, str.chars(), str.length(), filter, &v));
+    CHECK(JS_ParseJSONWithReviver(cx, str.chars(), str.length(), filter, v.address()));
     CHECK_SAME(v, JSVAL_NULL);
     return true;
 }
 END_TEST(testParseJSON_reviver)
--- a/js/src/jsapi-tests/testProfileStrings.cpp
+++ b/js/src/jsapi-tests/testProfileStrings.cpp
@@ -37,17 +37,18 @@ test_fn(JSContext *cx, unsigned argc, js
     max_stack = size;
     return JS_TRUE;
 }
 
 static JSBool
 test_fn2(JSContext *cx, unsigned argc, jsval *vp)
 {
     jsval r;
-    return JS_CallFunctionName(cx, JS_GetGlobalObject(cx), "d", 0, NULL, &r);
+    JS::RootedObject global(cx, JS_GetGlobalObject(cx));
+    return JS_CallFunctionName(cx, global, "d", 0, NULL, &r);
 }
 
 static JSBool
 enable(JSContext *cx, unsigned argc, jsval *vp)
 {
     js::EnableRuntimeProfilingStack(cx->runtime, true);
     return JS_TRUE;
 }
@@ -76,17 +77,18 @@ static JSFunctionSpec ptestFunctions[] =
     JS_FS("disable", disable, 0, 0),
     JS_FS_END
 };
 
 static JSObject*
 initialize(JSContext *cx)
 {
     js::SetRuntimeProfilingStack(cx->runtime, stack, &size, 10);
-    return JS_InitClass(cx, JS_GetGlobalObject(cx), NULL, &ptestClass, Prof, 0,
+    JS::RootedObject global(cx, JS_GetGlobalObject(cx));
+    return JS_InitClass(cx, global, NULL, &ptestClass, Prof, 0,
                         NULL, ptestFunctions, NULL, NULL);
 }
 
 BEGIN_TEST(testProfileStrings_isCalled)
 {
     CHECK(initialize(cx));
 
     EXEC("function g() { var p = new Prof(); p.test_fn(); }");
@@ -96,44 +98,44 @@ BEGIN_TEST(testProfileStrings_isCalled)
     EXEC("function c() { d(); }");
     EXEC("function b() { c(); }");
     EXEC("function a() { b(); }");
     EXEC("function check() { var p = new Prof(); p.test_fn(); a(); }");
     EXEC("function check2() { var p = new Prof(); p.test_fn2(); }");
 
     reset(cx);
     {
-        jsvalRoot rval(cx);
+        JS::RootedValue rval(cx);
         /* Make sure the stack resets and we have an entry for each stack */
-        CHECK(JS_CallFunctionName(cx, global, "check", 0, NULL, rval.addr()));
+        CHECK(JS_CallFunctionName(cx, global, "check", 0, NULL, rval.address()));
         CHECK(size == 0);
         CHECK(max_stack == 9);
         CHECK(cx->runtime->spsProfiler.stringsCount() == 8);
         /* Make sure the stack resets and we added no new entries */
         max_stack = 0;
-        CHECK(JS_CallFunctionName(cx, global, "check", 0, NULL, rval.addr()));
+        CHECK(JS_CallFunctionName(cx, global, "check", 0, NULL, rval.address()));
         CHECK(size == 0);
         CHECK(max_stack == 9);
         CHECK(cx->runtime->spsProfiler.stringsCount() == 8);
     }
     reset(cx);
     {
-        jsvalRoot rval(cx);
-        CHECK(JS_CallFunctionName(cx, global, "check2", 0, NULL, rval.addr()));
+        JS::RootedValue rval(cx);
+        CHECK(JS_CallFunctionName(cx, global, "check2", 0, NULL, rval.address()));
         CHECK(cx->runtime->spsProfiler.stringsCount() == 5);
         CHECK(max_stack == 7);
         CHECK(size == 0);
     }
     js::EnableRuntimeProfilingStack(cx->runtime, false);
     js::SetRuntimeProfilingStack(cx->runtime, stack, &size, 3);
     reset(cx);
     {
-        jsvalRoot rval(cx);
+        JS::RootedValue rval(cx);
         stack[3].string = (char*) 1234;
-        CHECK(JS_CallFunctionName(cx, global, "check", 0, NULL, rval.addr()));
+        CHECK(JS_CallFunctionName(cx, global, "check", 0, NULL, rval.address()));
         CHECK((size_t) stack[3].string == 1234);
         CHECK(max_stack == 9);
         CHECK(size == 0);
     }
     return true;
 }
 END_TEST(testProfileStrings_isCalled)
 
@@ -150,113 +152,111 @@ BEGIN_TEST(testProfileStrings_isCalledWi
     EXEC("function c() { d(); }");
     EXEC("function b() { c(); }");
     EXEC("function a() { b(); }");
     EXEC("function check() { var p = new Prof(); p.test_fn(); a(); }");
     EXEC("function check2() { var p = new Prof(); p.test_fn2(); }");
 
     reset(cx);
     {
-        jsvalRoot rval(cx);
+        JS::RootedValue rval(cx);
         /* Make sure the stack resets and we have an entry for each stack */
-        CHECK(JS_CallFunctionName(cx, global, "check", 0, NULL, rval.addr()));
+        CHECK(JS_CallFunctionName(cx, global, "check", 0, NULL, rval.address()));
         CHECK(size == 0);
         CHECK(max_stack == 9);
 
         /* Make sure the stack resets and we added no new entries */
         uint32_t cnt = cx->runtime->spsProfiler.stringsCount();
         max_stack = 0;
-        CHECK(JS_CallFunctionName(cx, global, "check", 0, NULL, rval.addr()));
+        CHECK(JS_CallFunctionName(cx, global, "check", 0, NULL, rval.address()));
         CHECK(size == 0);
         CHECK(cx->runtime->spsProfiler.stringsCount() == cnt);
         CHECK(max_stack == 9);
     }
 
     js::EnableRuntimeProfilingStack(cx->runtime, false);
     js::SetRuntimeProfilingStack(cx->runtime, stack, &size, 3);
     reset(cx);
     {
         /* Limit the size of the stack and make sure we don't overflow */
-        jsvalRoot rval(cx);
+        JS::RootedValue rval(cx);
         stack[3].string = (char*) 1234;
-        CHECK(JS_CallFunctionName(cx, global, "check", 0, NULL, rval.addr()));
+        CHECK(JS_CallFunctionName(cx, global, "check", 0, NULL, rval.address()));
         CHECK(size == 0);
         CHECK(max_stack == 9);
         CHECK((size_t) stack[3].string == 1234);
     }
     return true;
 }
 END_TEST(testProfileStrings_isCalledWithJIT)
 
 BEGIN_TEST(testProfileStrings_isCalledWhenError)
 {
     CHECK(initialize(cx));
-    JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_METHODJIT |
-                        JSOPTION_METHODJIT_ALWAYS);
+    JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_METHODJIT | JSOPTION_METHODJIT_ALWAYS);
 
     EXEC("function check2() { throw 'a'; }");
 
     reset(cx);
     {
-        jsvalRoot rval(cx);
+        JS::RootedValue rval(cx);
         /* Make sure the stack resets and we have an entry for each stack */
-        JS_CallFunctionName(cx, global, "check2", 0, NULL, rval.addr());
+        JS_CallFunctionName(cx, global, "check2", 0, NULL, rval.address());
         CHECK(size == 0);
         CHECK(cx->runtime->spsProfiler.stringsCount() == 1);
     }
     return true;
 }
 END_TEST(testProfileStrings_isCalledWhenError)
 
 BEGIN_TEST(testProfileStrings_worksWhenEnabledOnTheFly)
 {
     CHECK(initialize(cx));
-    JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_METHODJIT |
-                      JSOPTION_METHODJIT_ALWAYS);
+    JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_METHODJIT | JSOPTION_METHODJIT_ALWAYS);
 
     EXEC("function b(p) { p.test_fn(); }");
     EXEC("function a() { var p = new Prof(); p.enable(); b(p); }");
     reset(cx);
     js::EnableRuntimeProfilingStack(cx->runtime, false);
     {
         /* enable it in the middle of JS and make sure things check out */
-        jsvalRoot rval(cx);
-        JS_CallFunctionName(cx, global, "a", 0, NULL, rval.addr());
+        JS::RootedValue rval(cx);
+        JS_CallFunctionName(cx, global, "a", 0, NULL, rval.address());
         CHECK(size == 0);
         CHECK(max_stack == 1);
         CHECK(cx->runtime->spsProfiler.stringsCount() == 1);
     }
 
     EXEC("function d(p) { p.disable(); }");
     EXEC("function c() { var p = new Prof(); d(p); }");
     reset(cx);
     {
         /* now disable in the middle of js */
-        jsvalRoot rval(cx);
-        JS_CallFunctionName(cx, global, "c", 0, NULL, rval.addr());
+        JS::RootedValue rval(cx);
+        JS_CallFunctionName(cx, global, "c", 0, NULL, rval.address());
         CHECK(size == 0);
     }
 
     EXEC("function e() { var p = new Prof(); d(p); p.enable(); b(p); }");
     reset(cx);
     {
         /* now disable in the middle of js, but re-enable before final exit */
-        jsvalRoot rval(cx);
-        JS_CallFunctionName(cx, global, "e", 0, NULL, rval.addr());
+        JS::RootedValue rval(cx);
+        JS_CallFunctionName(cx, global, "e", 0, NULL, rval.address());
         CHECK(size == 0);
         CHECK(max_stack == 3);
     }
 
     EXEC("function h() { }");
     EXEC("function g(p) { p.disable(); for (var i = 0; i < 100; i++) i++; }");
     EXEC("function f() { g(new Prof()); }");
     reset(cx);
     cx->runtime->spsProfiler.enableSlowAssertions(false);
     {
-        jsvalRoot rval(cx);
+        JS::RootedValue rval(cx);
         /* disable, and make sure that if we try to re-enter the JIT the pop
          * will still happen */
-        JS_CallFunctionName(cx, global, "f", 0, NULL, rval.addr());
+        JS_CallFunctionName(cx, global, "f", 0, NULL, rval.address());
         CHECK(size == 0);
     }
     return true;
 }
 END_TEST(testProfileStrings_worksWhenEnabledOnTheFly)
--- a/js/src/jsapi-tests/testRegExp.cpp
+++ b/js/src/jsapi-tests/testRegExp.cpp
@@ -1,57 +1,56 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "tests.h"
 
 BEGIN_TEST(testObjectIsRegExp)
 {
-    jsvalRoot val(cx);
-    JSObject *obj;
+    JS::RootedValue val(cx);
 
-    EVAL("new Object", val.addr());
-    obj = JSVAL_TO_OBJECT(val.value());
+    EVAL("new Object", val.address());
+    JS::RootedObject obj(cx, JSVAL_TO_OBJECT(val));
     CHECK(!JS_ObjectIsRegExp(cx, obj));
 
-    EVAL("/foopy/", val.addr());
-    obj = JSVAL_TO_OBJECT(val.value());
+    EVAL("/foopy/", val.address());
+    obj = JSVAL_TO_OBJECT(val);
     CHECK(JS_ObjectIsRegExp(cx, obj));
 
     return true;
 }
 END_TEST(testObjectIsRegExp)
 
 BEGIN_TEST(testGetRegExpFlags)
 {
-    jsvalRoot val(cx);
-    JSObject *obj;
+    JS::RootedValue val(cx);
+    JS::RootedObject obj(cx);
 
-    EVAL("/foopy/", val.addr());
-    obj = JSVAL_TO_OBJECT(val.value());
+    EVAL("/foopy/", val.address());
+    obj = JSVAL_TO_OBJECT(val);
     CHECK_EQUAL(JS_GetRegExpFlags(cx, obj), 0);
 
-    EVAL("/foopy/g", val.addr());
-    obj = JSVAL_TO_OBJECT(val.value());
+    EVAL("/foopy/g", val.address());
+    obj = JSVAL_TO_OBJECT(val);
     CHECK_EQUAL(JS_GetRegExpFlags(cx, obj), JSREG_GLOB);
 
-    EVAL("/foopy/gi", val.addr());
-    obj = JSVAL_TO_OBJECT(val.value());
+    EVAL("/foopy/gi", val.address());
+    obj = JSVAL_TO_OBJECT(val);
     CHECK_EQUAL(JS_GetRegExpFlags(cx, obj), (JSREG_FOLD | JSREG_GLOB));
 
     return true;
 }
 END_TEST(testGetRegExpFlags)
 
 BEGIN_TEST(testGetRegExpSource)
 {
-    jsvalRoot val(cx);
-    JSObject *obj;
+    JS::RootedValue val(cx);
+    JS::RootedObject obj(cx);
 
-    EVAL("/foopy/", val.addr());
-    obj = JSVAL_TO_OBJECT(val.value());
+    EVAL("/foopy/", val.address());
+    obj = JSVAL_TO_OBJECT(val);
     JSString *source = JS_GetRegExpSource(cx, obj);
     CHECK(JS_FlatStringEqualsAscii(JS_ASSERT_STRING_IS_FLAT(source), "foopy"));
 
     return true;
 }
 END_TEST(testGetRegExpSource)
--- a/js/src/jsapi-tests/testResolveRecursion.cpp
+++ b/js/src/jsapi-tests/testResolveRecursion.cpp
@@ -64,17 +64,17 @@ struct AutoIncrCounters {
     ~AutoIncrCounters() {
         t->resolveExitCount++;
     }
 
     cls_testResolveRecursion *t;
 };
 
 bool
-doResolve(JSObject *obj, jsid id, unsigned flags, JSMutableHandleObject objp)
+doResolve(JSHandleObject obj, JSHandleId id, unsigned flags, JSMutableHandleObject objp)
 {
     CHECK_EQUAL(resolveExitCount, 0);
     AutoIncrCounters incr(this);
     CHECK_EQUAL(obj, obj1 || obj == obj2);
 
     CHECK(JSID_IS_STRING(id));
 
     JSFlatString *str = JS_FlattenString(cx, JSID_TO_STRING(id));
--- a/js/src/jsapi-tests/testScriptObject.cpp
+++ b/js/src/jsapi-tests/testScriptObject.cpp
@@ -14,18 +14,19 @@ struct ScriptObjectFixture : public JSAP
     static jschar uc_code[];
 
     ScriptObjectFixture()
     {
         for (int i = 0; i < code_size; i++)
             uc_code[i] = code[i];
     }
 
-    bool tryScript(JSScript *script)
+    bool tryScript(JS::HandleObject global, JSScript *scriptArg)
     {
+        JS::RootedScript script(cx, scriptArg);
         CHECK(script);
 
         JS_GC(rt);
 
         /* After a garbage collection, the script should still work. */
         jsval result;
         CHECK(JS_ExecuteScript(cx, global, script, &result));
 
@@ -35,108 +36,108 @@ struct ScriptObjectFixture : public JSAP
 
 const char ScriptObjectFixture::code[] =
     "(function(a, b){return a+' '+b;}('hello', 'world'))";
 const int ScriptObjectFixture::code_size = sizeof(ScriptObjectFixture::code) - 1;
 jschar ScriptObjectFixture::uc_code[ScriptObjectFixture::code_size];
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_CompileScript)
 {
-    return tryScript(JS_CompileScript(cx, global, code, code_size,
-                                      __FILE__, __LINE__));
+    return tryScript(global, JS_CompileScript(cx, global, code, code_size,
+                                              __FILE__, __LINE__));
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_CompileScript)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_CompileScript_empty)
 {
-    return tryScript(JS_CompileScript(cx, global, "", 0,
-                                      __FILE__, __LINE__));
+    return tryScript(global, JS_CompileScript(cx, global, "", 0,
+                                              __FILE__, __LINE__));
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_CompileScript_empty)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_CompileScriptForPrincipals)
 {
-    return tryScript(JS_CompileScriptForPrincipals(cx, global, NULL,
-                                                   code, code_size,
-                                                   __FILE__, __LINE__));
+    return tryScript(global, JS_CompileScriptForPrincipals(cx, global, NULL,
+                                                           code, code_size,
+                                                           __FILE__, __LINE__));
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_CompileScriptForPrincipals)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileUCScript)
 {
-    return tryScript(JS_CompileUCScript(cx, global,
-                                        uc_code, code_size,
-                                        __FILE__, __LINE__));
+    return tryScript(global, JS_CompileUCScript(cx, global,
+                                                uc_code, code_size,
+                                                __FILE__, __LINE__));
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileUCScript)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileUCScript_empty)
 {
-    return tryScript(JS_CompileUCScript(cx, global,
-                                        uc_code, 0,
-                                        __FILE__, __LINE__));
+    return tryScript(global, JS_CompileUCScript(cx, global,
+                                                uc_code, 0,
+                                                __FILE__, __LINE__));
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileUCScript_empty)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileUCScriptForPrincipals)
 {
-    return tryScript(JS_CompileUCScriptForPrincipals(cx, global, NULL,
-                                                     uc_code, code_size,
-                                                     __FILE__, __LINE__));
+    return tryScript(global, JS_CompileUCScriptForPrincipals(cx, global, NULL,
+                                                             uc_code, code_size,
+                                                             __FILE__, __LINE__));
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileUCScriptForPrincipals)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFile)
 {
     TempFile tempScript;
     static const char script_filename[] = "temp-bug438633_JS_CompileFile";
     FILE *script_stream = tempScript.open(script_filename);
     CHECK(fputs(code, script_stream) != EOF);
     tempScript.close();
     JSScript *script = JS_CompileUTF8File(cx, global, script_filename);
     tempScript.remove();
-    return tryScript(script);
+    return tryScript(global, script);
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFile)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFile_empty)
 {
     TempFile tempScript;
     static const char script_filename[] = "temp-bug438633_JS_CompileFile_empty";
     tempScript.open(script_filename);
     tempScript.close();
     JSScript *script = JS_CompileUTF8File(cx, global, script_filename);
     tempScript.remove();
-    return tryScript(script);
+    return tryScript(global, script);
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFile_empty)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFileHandle)
 {
     TempFile tempScript;
     FILE *script_stream = tempScript.open("temp-bug438633_JS_CompileFileHandle");
     CHECK(fputs(code, script_stream) != EOF);
     CHECK(fseek(script_stream, 0, SEEK_SET) != EOF);
-    return tryScript(JS_CompileUTF8FileHandle(cx, global, "temporary file",
-                                              script_stream));
+    return tryScript(global, JS_CompileUTF8FileHandle(cx, global, "temporary file",
+                                                      script_stream));
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFileHandle)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFileHandle_empty)
 {
     TempFile tempScript;
     FILE *script_stream = tempScript.open("temp-bug438633_JS_CompileFileHandle_empty");
-    return tryScript(JS_CompileUTF8FileHandle(cx, global, "empty temporary file",
+    return tryScript(global, JS_CompileUTF8FileHandle(cx, global, "empty temporary file",
                                               script_stream));
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFileHandle_empty)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFileHandleForPrincipals)
 {
     TempFile tempScript;
     FILE *script_stream = tempScript.open("temp-bug438633_JS_CompileFileHandleForPrincipals");
     CHECK(fputs(code, script_stream) != EOF);
     CHECK(fseek(script_stream, 0, SEEK_SET) != EOF);
-    return tryScript(JS_CompileUTF8FileHandleForPrincipals(cx, global,
-                                                           "temporary file",
-                                                           script_stream, NULL));
+    return tryScript(global, JS_CompileUTF8FileHandleForPrincipals(cx, global,
+                                                                   "temporary file",
+                                                                   script_stream, NULL));
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFileHandleForPrincipals)
--- a/js/src/jsapi-tests/testSetProperty.cpp
+++ b/js/src/jsapi-tests/testSetProperty.cpp
@@ -12,20 +12,19 @@ static JSBool
 nativeGet(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp)
 {
     vp.set(INT_TO_JSVAL(17));
     return JS_TRUE;
 }
 
 BEGIN_TEST(testSetProperty_NativeGetterStubSetter)
 {
-    jsvalRoot vobj(cx);
-    JSObject *obj = JS_NewObject(cx, NULL, NULL, NULL);
+    JS::RootedObject obj(cx, JS_NewObject(cx, NULL, NULL, NULL));
     CHECK(obj);
-    vobj = OBJECT_TO_JSVAL(obj);
+    JS::RootedValue vobj(cx, OBJECT_TO_JSVAL(obj));
 
     CHECK(JS_DefineProperty(cx, global, "globalProp", vobj,
                             JS_PropertyStub, JS_StrictPropertyStub,
                             JSPROP_ENUMERATE));
 
     CHECK(JS_DefineProperty(cx, obj, "prop", JSVAL_VOID,
                             nativeGet, JS_StrictPropertyStub,
                             JSPROP_SHARED));
--- a/js/src/jsapi-tests/testTrap.cpp
+++ b/js/src/jsapi-tests/testTrap.cpp
@@ -29,33 +29,33 @@ BEGIN_TEST(testTrap_gc)
 "while (i < 10) {\n"
 "    sum += i;\n"
 "    ++i;\n"
 "}\n"
 "({ result: sum });\n"
         ;
 
     // compile
-    JSScript *script = JS_CompileScript(cx, global, source, strlen(source), __FILE__, 1);
+    JS::RootedScript script(cx, JS_CompileScript(cx, global, source, strlen(source), __FILE__, 1));
     CHECK(script);
 
     // execute
-    jsvalRoot v2(cx);
-    CHECK(JS_ExecuteScript(cx, global, script, v2.addr()));
-    CHECK(v2.value().isObject());
+    JS::RootedValue v2(cx);
+    CHECK(JS_ExecuteScript(cx, global, script, v2.address()));
+    CHECK(v2.isObject());
     CHECK_EQUAL(emptyTrapCallCount, 0);
 
     // Enable debug mode
     CHECK(JS_SetDebugMode(cx, JS_TRUE));
 
     static const char trapClosureText[] = "some trap closure";
 
     // scope JSScript  usage to make sure that it is not used after
     // JS_ExecuteScript. This way we avoid using Anchor.
-    JSString *trapClosure;
+    JS::RootedString trapClosure(cx);
     {
         jsbytecode *line2 = JS_LineNumberToPC(cx, script, 1);
         CHECK(line2);
 
         jsbytecode *line6 = JS_LineNumberToPC(cx, script, 5);
         CHECK(line2);
 
         trapClosure = JS_NewStringCopyZ(cx, trapClosureText);
@@ -64,17 +64,17 @@ BEGIN_TEST(testTrap_gc)
         JS_SetTrap(cx, script, line6, EmptyTrapHandler, STRING_TO_JSVAL(trapClosure));
 
         JS_GC(rt);
 
         CHECK(JS_FlatStringEqualsAscii(JS_ASSERT_STRING_IS_FLAT(trapClosure), trapClosureText));
     }
 
     // execute
-    CHECK(JS_ExecuteScript(cx, global, script, v2.addr()));
+    CHECK(JS_ExecuteScript(cx, global, script, v2.address()));
     CHECK_EQUAL(emptyTrapCallCount, 11);
 
     JS_GC(rt);
 
     CHECK(JS_FlatStringEqualsAscii(JS_ASSERT_STRING_IS_FLAT(trapClosure), trapClosureText));
 
     return true;
 }
--- a/js/src/jsapi-tests/testTypedArrays.cpp
+++ b/js/src/jsapi-tests/testTypedArrays.cpp
@@ -22,22 +22,22 @@ BEGIN_TEST(testTypedArrays)
         TestPlainTypedArray<JS_NewInt16Array, int16_t, JS_GetInt16ArrayData>(cx) &&
         TestPlainTypedArray<JS_NewUint16Array, uint16_t, JS_GetUint16ArrayData>(cx) &&
         TestPlainTypedArray<JS_NewInt32Array, int32_t, JS_GetInt32ArrayData>(cx) &&
         TestPlainTypedArray<JS_NewUint32Array, uint32_t, JS_GetUint32ArrayData>(cx) &&
         TestPlainTypedArray<JS_NewFloat32Array, float, JS_GetFloat32ArrayData>(cx) &&
         TestPlainTypedArray<JS_NewFloat64Array, double, JS_GetFloat64ArrayData>(cx);
 
     size_t nbytes = sizeof(double) * 8;
-    JSObject *buffer = JS_NewArrayBuffer(cx, nbytes);
+    RootedObject buffer(cx, JS_NewArrayBuffer(cx, nbytes));
     CHECK(JS_IsArrayBufferObject(buffer, cx));
 
-    JSObject *proto = JS_GetPrototype(buffer);
+    RootedObject proto(cx, JS_GetPrototype(buffer));
     CHECK(!JS_IsArrayBufferObject(proto, cx));
-    JSObject *dummy = JS_GetParent(proto);
+    RootedObject dummy(cx, JS_GetParent(proto));
     CHECK(!JS_IsArrayBufferObject(dummy, cx));
 
     CHECK_EQUAL(JS_GetArrayBufferByteLength(buffer, cx), nbytes);
     memset(JS_GetArrayBufferData(buffer, cx), 1, nbytes);
 
     ok = ok &&
         TestArrayFromBuffer<JS_NewInt8ArrayWithBuffer, JS_NewInt8ArrayFromArray, int8_t, JS_GetInt8ArrayData>(cx) &&
         TestArrayFromBuffer<JS_NewUint8ArrayWithBuffer, JS_NewUint8ArrayFromArray, uint8_t, JS_GetUint8ArrayData>(cx) &&
@@ -53,21 +53,21 @@ BEGIN_TEST(testTypedArrays)
 }
 
 template<JSObject *Create(JSContext *, uint32_t),
          typename Element,
          Element *GetData(JSObject *, JSContext *)>
 bool
 TestPlainTypedArray(JSContext *cx)
 {
-    JSObject *array = Create(cx, 7);
+    RootedObject array(cx, Create(cx, 7));
     CHECK(JS_IsTypedArrayObject(array, cx));
-    JSObject *proto = JS_GetPrototype(array);
+    RootedObject proto(cx, JS_GetPrototype(array));
     CHECK(!JS_IsTypedArrayObject(proto, cx));
-    JSObject *dummy = JS_GetParent(proto);
+    RootedObject dummy(cx, JS_GetParent(proto));
     CHECK(!JS_IsTypedArrayObject(dummy, cx));
 
     CHECK_EQUAL(JS_GetTypedArrayLength(array, cx), 7);
     CHECK_EQUAL(JS_GetTypedArrayByteOffset(array, cx), 0);
     CHECK_EQUAL(JS_GetTypedArrayByteLength(array, cx), sizeof(Element) * 7);
 
     Element *data;
     CHECK(data = GetData(array, cx));
@@ -83,40 +83,40 @@ template<JSObject *CreateWithBuffer(JSCo
          JSObject *CreateFromArray(JSContext *, JSObject *),
          typename Element,
          Element *GetData(JSObject *, JSContext *)>
 bool
 TestArrayFromBuffer(JSContext *cx)
 {
     size_t elts = 8;
     size_t nbytes = elts * sizeof(Element);
-    JSObject *buffer = JS_NewArrayBuffer(cx, nbytes);
+    RootedObject buffer(cx, JS_NewArrayBuffer(cx, nbytes));
     uint8_t *bufdata;
     CHECK(bufdata = JS_GetArrayBufferData(buffer, cx));
     memset(bufdata, 1, nbytes);
 
-    JSObject *array = CreateWithBuffer(cx, buffer, 0, -1);
+    RootedObject array(cx, CreateWithBuffer(cx, buffer, 0, -1));
     CHECK_EQUAL(JS_GetTypedArrayLength(array, cx), elts);
     CHECK_EQUAL(JS_GetTypedArrayByteOffset(array, cx), 0);
     CHECK_EQUAL(JS_GetTypedArrayByteLength(array, cx), nbytes);
 
     Element *data;
     CHECK(data = GetData(array, cx));
     CHECK(bufdata = JS_GetArrayBufferData(buffer, cx));
     CHECK_EQUAL((void*) data, (void*) bufdata);
 
     CHECK_EQUAL(*bufdata, 1);
     CHECK_EQUAL(*reinterpret_cast<uint8_t*>(data), 1);
 
-    JSObject *shortArray = CreateWithBuffer(cx, buffer, 0, elts / 2);
+    RootedObject shortArray(cx, CreateWithBuffer(cx, buffer, 0, elts / 2));
     CHECK_EQUAL(JS_GetTypedArrayLength(shortArray, cx), elts / 2);
     CHECK_EQUAL(JS_GetTypedArrayByteOffset(shortArray, cx), 0);
     CHECK_EQUAL(JS_GetTypedArrayByteLength(shortArray, cx), nbytes / 2);
 
-    JSObject *ofsArray = CreateWithBuffer(cx, buffer, nbytes / 2, -1);
+    RootedObject ofsArray(cx, CreateWithBuffer(cx, buffer, nbytes / 2, -1));
     CHECK_EQUAL(JS_GetTypedArrayLength(ofsArray, cx), elts / 2);
     CHECK_EQUAL(JS_GetTypedArrayByteOffset(ofsArray, cx), nbytes / 2);
     CHECK_EQUAL(JS_GetTypedArrayByteLength(ofsArray, cx), nbytes / 2);
 
     // Make sure all 3 views reflect the same buffer at the expected locations
     jsval v = INT_TO_JSVAL(39);
     JS_SetElement(cx, array, 0, &v);
     jsval v2;
@@ -137,17 +137,17 @@ TestArrayFromBuffer(JSContext *cx)
     v = INT_TO_JSVAL(41);
     JS_SetElement(cx, array, elts - 1, &v);
     CHECK(JS_GetElement(cx, array, elts - 1, &v2));
     CHECK_SAME(v, v2);
     CHECK(JS_GetElement(cx, ofsArray, elts / 2 - 1, &v2));
     CHECK_SAME(v, v2);
     CHECK_EQUAL(long(JSVAL_TO_INT(v)), long(reinterpret_cast<Element*>(data)[elts - 1]));
 
-    JSObject *copy = CreateFromArray(cx, array);
+    RootedObject copy(cx, CreateFromArray(cx, array));
     CHECK(JS_GetElement(cx, array, 0, &v));
     CHECK(JS_GetElement(cx, copy, 0, &v2));
     CHECK_SAME(v, v2);
 
     /* The copy should not see changes in the original */
     v2 = INT_TO_JSVAL(42);
     JS_SetElement(cx, array, 0, &v2);
     CHECK(JS_GetElement(cx, copy, 0, &v2));
--- a/js/src/jsapi-tests/testValueABI.cpp
+++ b/js/src/jsapi-tests/testValueABI.cpp
@@ -12,29 +12,29 @@
  *
  * Bug 712289 - jsval alignment was different on 32-bit platforms between C and
  * C++ because the default alignments of js::Value and jsval_layout differ.
  */
 
 extern "C" {
 
 extern JSBool
-C_ValueToObject(JSContext *cx, jsval v, JSObject **obj);
+C_ValueToObject(JSContext *cx, jsval v, JSMutableHandleObject obj);
 
 extern jsval
 C_GetEmptyStringValue(JSContext *cx);
 
 extern size_t
 C_jsvalAlignmentTest();
 
 }
 
 BEGIN_TEST(testValueABI_retparam)
 {
-    JSObject* obj = JS_GetGlobalObject(cx);
+    JS::RootedObject obj(cx, JS_GetGlobalObject(cx));
     jsval v = OBJECT_TO_JSVAL(obj);
     obj = NULL;
     CHECK(C_ValueToObject(cx, v, &obj));
     JSBool equal;
     CHECK(JS_StrictlyEqual(cx, v, OBJECT_TO_JSVAL(obj), &equal));
     CHECK(equal);
 
     v = C_GetEmptyStringValue(cx);
--- a/js/src/jsapi-tests/testVersion.cpp
+++ b/js/src/jsapi-tests/testVersion.cpp
@@ -34,28 +34,30 @@ struct VersionFixture : public JSAPITest
     JSVersion captured;
 
     virtual bool init() {
         if (!JSAPITest::init())
             return false;
         JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_ALLOW_XML);
         callbackData = this;
         captured = JSVERSION_UNKNOWN;
+        JS::RootedObject global(cx, JS_GetGlobalObject(cx));
         return JS_DefineFunction(cx, global, "checkVersionHasMoarXML", CheckVersionHasMoarXML, 0, 0) &&
                JS_DefineFunction(cx, global, "disableMoarXMLOption", DisableMoarXMLOption, 0, 0) &&
                JS_DefineFunction(cx, global, "callSetVersion17", CallSetVersion17, 0, 0) &&
                JS_DefineFunction(cx, global, "checkNewScriptNoXML", CheckNewScriptNoXML, 0, 0) &&
                JS_DefineFunction(cx, global, "overrideVersion15", OverrideVersion15, 0, 0) &&
                JS_DefineFunction(cx, global, "captureVersion", CaptureVersion, 0, 0) &&
                JS_DefineFunction(cx, global, "checkOverride", CheckOverride, 1, 0) &&
                JS_DefineFunction(cx, global, "evalScriptVersion16",
                                  EvalScriptVersion16, 0, 0);
     }
 
     JSScript *fakeScript(const char *contents, size_t length) {
+        JS::RootedObject global(cx, JS_GetGlobalObject(cx));
         return JS_CompileScript(cx, global, contents, length, "<test>", 1);
     }
 
     bool hasMoarXML(unsigned version) {
         return VersionHasMoarXML(JSVersion(version));
     }
 
     bool hasMoarXML(JSScript *script) {
@@ -93,16 +95,17 @@ struct VersionFixture : public JSAPITest
         CHECK(JS_GetVersion(cx) != version);
         JS_SetVersion(cx, version);
         return true;
     }
 
     bool evalVersion(const jschar *chars, size_t len, JSVersion version) {
         CHECK(JS_GetVersion(cx) != version);
         jsval rval;
+        JS::RootedObject global(cx, JS_GetGlobalObject(cx));
         CHECK(JS_EvaluateUCScriptForPrincipalsVersion(
                 cx, global, NULL, chars, len, "<test>", 0, &rval, version));
         return true;
     }
 
     bool toggleMoarXML(bool shouldEnable) {
         CHECK_EQUAL(hasMoarXML(), !shouldEnable);
         JS_ToggleOptions(cx, JSOPTION_MOAR_XML);
--- a/js/src/jsapi-tests/testXDR.cpp
+++ b/js/src/jsapi-tests/testXDR.cpp
@@ -5,17 +5,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 
 #include "tests.h"
 #include "jsscript.h"
 
 static JSScript *
-CompileScriptForPrincipalsVersionOrigin(JSContext *cx, JSObject *obj,
+CompileScriptForPrincipalsVersionOrigin(JSContext *cx, JS::HandleObject obj,
                                         JSPrincipals *principals, JSPrincipals *originPrincipals,
                                         const char *bytes, size_t nbytes,
                                         const char *filename, unsigned lineno,
                                         JSVersion version)
 {
     size_t nchars;
     if (!JS_DecodeBytes(cx, bytes, nbytes, NULL, &nchars))
         return NULL;
@@ -42,36 +42,36 @@ FreezeThaw(JSContext *cx, JSScript *scri
 
     // thaw
     script = JS_DecodeScript(cx, memory, nbytes, script->principals, script->originPrincipals);
     js_free(memory);
     return script;
 }
 
 static JSScript *
-GetScript(JSContext *cx, JSObject *funobj)
+GetScript(JSContext *cx, JS::HandleObject funobj)
 {
     return JS_GetFunctionScript(cx, JS_GetObjectFunction(funobj));
 }
 
 JSObject *
-FreezeThaw(JSContext *cx, JSObject *funobj)
+FreezeThaw(JSContext *cx, JS::HandleObject funobj)
 {
     // freeze
     uint32_t nbytes;
     void *memory = JS_EncodeInterpretedFunction(cx, funobj, &nbytes);
     if (!memory)
         return NULL;
 
     // thaw
     JSScript *script = GetScript(cx, funobj);
-    funobj = JS_DecodeInterpretedFunction(cx, memory, nbytes,
+    JSObject *funobj2 = JS_DecodeInterpretedFunction(cx, memory, nbytes,
                                           script->principals, script->originPrincipals);
     js_free(memory);
-    return funobj;
+    return funobj2;
 }
 
 static JSPrincipals testPrincipals[] = {
     { 1 },
     { 1 },
 };
 
 BEGIN_TEST(testXDR_principals)
@@ -121,16 +121,17 @@ enum TestCase {
 };
 
 JSScript *createScriptViaXDR(JSPrincipals *prin, JSPrincipals *orig, int testCase)
 {
     const char src[] =
         "function f() { return 1; }\n"
         "f;\n";
 
+    JS::RootedObject global(cx, JS_GetGlobalObject(cx));
     JSScript *script = CompileScriptForPrincipalsVersionOrigin(cx, global, prin, orig,
                                                                src, strlen(src), "test", 1,
                                                                JSVERSION_DEFAULT);
     if (!script)
         return NULL;
 
     if (testCase == TEST_SCRIPT || testCase == TEST_SERIALIZED_FUNCTION) {
         script = FreezeThaw(cx, script);
@@ -139,17 +140,17 @@ JSScript *createScriptViaXDR(JSPrincipal
         if (testCase == TEST_SCRIPT)
             return script;
     }
 
     JS::Value v;
     JSBool ok = JS_ExecuteScript(cx, global, script, &v);
     if (!ok || !v.isObject())
         return NULL;
-    JSObject *funobj = &v.toObject();
+    JS::RootedObject funobj(cx, &v.toObject());
     if (testCase == TEST_FUNCTION) {
         funobj = FreezeThaw(cx, funobj);
         if (!funobj)
             return NULL;
     }
     return GetScript(cx, funobj);
 }
 
@@ -171,17 +172,17 @@ BEGIN_TEST(testXDR_atline)
     CHECK(script = FreezeThaw(cx, script));
     CHECK(!strcmp("bar", JS_GetScriptFilename(cx, script)));
 
     JS::Value v;
     JSBool ok = JS_ExecuteScript(cx, global, script, &v);
     CHECK(ok);
     CHECK(v.isObject());
 
-    JSObject *funobj = &v.toObject();
+    JS::RootedObject funobj(cx, &v.toObject());
     script = JS_GetFunctionScript(cx, JS_GetObjectFunction(funobj));
     CHECK(!strcmp("foo", JS_GetScriptFilename(cx, script)));
 
     return true;
 }
 
 END_TEST(testXDR_atline)
 
@@ -197,25 +198,25 @@ BEGIN_TEST(testXDR_bug506491)
     // compile
     JSScript *script = JS_CompileScript(cx, global, s, strlen(s), __FILE__, __LINE__);
     CHECK(script);
 
     script = FreezeThaw(cx, script);
     CHECK(script);
 
     // execute
-    jsvalRoot v2(cx);
-    CHECK(JS_ExecuteScript(cx, global, script, v2.addr()));
+    JS::RootedValue v2(cx);
+    CHECK(JS_ExecuteScript(cx, global, script, v2.address()));
 
     // try to break the Block object that is the parent of f
     JS_GC(rt);
 
     // confirm
-    EVAL("f() === 'ok';\n", v2.addr());
-    jsvalRoot trueval(cx, JSVAL_TRUE);
+    EVAL("f() === 'ok';\n", v2.address());
+    JS::RootedValue trueval(cx, JSVAL_TRUE);
     CHECK_SAME(v2, trueval);
     return true;
 }
 END_TEST(testXDR_bug506491)
 
 BEGIN_TEST(testXDR_bug516827)
 {
     // compile an empty script
--- a/js/src/jsapi-tests/tests.cpp
+++ b/js/src/jsapi-tests/tests.cpp
@@ -1,20 +1,82 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sw=4 et tw=78:
  *
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "tests.h"
+#include "gc/Root.h"
+#include "jsobj.h"
 #include <stdio.h>
 
 JSAPITest *JSAPITest::list;
 
+bool JSAPITest::init()
+{
+    rt = createRuntime();
+    if (!rt)
+        return false;
+    cx = createContext();
+    if (!cx)
+        return false;
+#ifdef JS_GC_ZEAL
+    JS_SetGCZeal(cx, 0, 0);
+#endif
+    JS_BeginRequest(cx);
+    JS::RootedObject global(cx, createGlobal());
+    if (!global)
+        return false;
+    call = JS_EnterCrossCompartmentCall(cx, global);
+    return call != NULL;
+}
+
+bool JSAPITest::exec(const char *bytes, const char *filename, int lineno)
+{
+    JS::RootedValue v(cx);
+    JS::HandleObject global = JS::HandleObject::fromMarkedLocation(&this->global);
+    return JS_EvaluateScript(cx, global, bytes, strlen(bytes), filename, lineno, v.address()) ||
+        fail(bytes, filename, lineno);
+}
+
+bool JSAPITest::evaluate(const char *bytes, const char *filename, int lineno, jsval *vp)
+{
+    JS::HandleObject global = JS::HandleObject::fromMarkedLocation(&this->global);
+    return JS_EvaluateScript(cx, global, bytes, strlen(bytes), filename, lineno, vp) ||
+        fail(bytes, filename, lineno);
+}
+
+bool JSAPITest::definePrint()
+{
+    JS::HandleObject global = JS::HandleObject::fromMarkedLocation(&this->global);
+    return JS_DefineFunction(cx, global, "print", (JSNative) print, 0, 0);
+}
+
+JSObject * JSAPITest::createGlobal(JSPrincipals *principals)
+{
+    /* Create the global object. */
+    global = JS_NewGlobalObject(cx, getGlobalClass(), principals);
+    if (!global)
+        return NULL;
+    JS_AddNamedObjectRoot(cx, &global, "test-global");
+    JS::HandleObject globalHandle = JS::HandleObject::fromMarkedLocation(&global);
+
+    JSAutoEnterCompartment ac;
+    if (!ac.enter(cx, globalHandle))
+        return NULL;
+
+    /* Populate the global object with the standard globals, like Object and
+       Array. */
+    if (!JS_InitStandardClasses(cx, globalHandle))
+        return NULL;
+    return global;
+}
+
 int main(int argc, char *argv[])
 {
     int total = 0;
     int failures = 0;
     const char *filter = (argc == 2) ? argv[1] : NULL;
 
     JS_SetCStringsAreUTF8();
 
@@ -27,17 +89,18 @@ int main(int argc, char *argv[])
 
         printf("%s\n", name);
         if (!test->init()) {
             printf("TEST-UNEXPECTED-FAIL | %s | Failed to initialize.\n", name);
             failures++;
             continue;
         }
 
-        if (test->run()) {
+        JS::HandleObject global = JS::HandleObject::fromMarkedLocation(&test->global);
+        if (test->run(global)) {
             printf("TEST-PASS | %s | ok\n", name);
         } else {
             JSAPITestString messages = test->messages();
             printf("%s | %s | %.*s\n",
                    (test->knownFail ? "TEST-KNOWN-FAIL" : "TEST-UNEXPECTED-FAIL"),
                    name, (int) messages.length(), messages.begin());
             if (!test->knownFail)
                 failures++;
--- a/js/src/jsapi-tests/tests.h
+++ b/js/src/jsapi-tests/tests.h
@@ -13,45 +13,16 @@
 
 #include "js/Vector.h"
 
 #include <errno.h>
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
 
-class jsvalRoot
-{
-  public:
-    explicit jsvalRoot(JSContext *context, jsval value = JSVAL_NULL)
-        : cx(context), v(value)
-    {
-        if (!JS_AddValueRoot(cx, &v)) {
-            fprintf(stderr, "Out of memory in jsvalRoot constructor, aborting\n");
-            abort();
-        }
-    }
-
-    ~jsvalRoot() { JS_RemoveValueRoot(cx, &v); }
-
-    operator jsval() const { return value(); }
-
-    jsvalRoot & operator=(jsval value) {
-        v = value;
-        return *this;
-    }
-
-    jsval * addr() { return &v; }
-    jsval value() const { return v; }
-
-  private:
-    JSContext *cx;
-    jsval v;
-};
-
 /* Note: Aborts on OOM. */
 class JSAPITestString {
     js::Vector<char, 0, js::SystemAllocPolicy> chars;
   public:
     JSAPITestString() {}
     JSAPITestString(const char *s) { *this += s; }
     JSAPITestString(const JSAPITestString &s) { *this += s; }
 
@@ -90,64 +61,45 @@ class JSAPITest
 
     JSAPITest() : rt(NULL), cx(NULL), global(NULL), knownFail(false), call(NULL) {
         next = list;
         list = this;
     }
 
     virtual ~JSAPITest() { uninit(); }
 
-    virtual bool init() {
-        rt = createRuntime();
-        if (!rt)
-            return false;
-        cx = createContext();
-        if (!cx)
-            return false;
-        JS_BeginRequest(cx);
-        global = createGlobal();
-        if (!global)
-            return false;
-        call = JS_EnterCrossCompartmentCall(cx, global);
-        return call != NULL;
-    }
+    virtual bool init();
 
     virtual void uninit() {
         if (call) {
             JS_LeaveCrossCompartmentCall(call);
             call = NULL;
         }
         if (cx) {
+            JS_RemoveObjectRoot(cx, &global);
             JS_EndRequest(cx);
             JS_DestroyContext(cx);
             cx = NULL;
         }
         if (rt) {
             destroyRuntime();
             rt = NULL;
         }
     }
 
     virtual const char * name() = 0;
-    virtual bool run() = 0;
+    virtual bool run(JS::HandleObject global) = 0;
 
 #define EXEC(s) do { if (!exec(s, __FILE__, __LINE__)) return false; } while (false)
 
-    bool exec(const char *bytes, const char *filename, int lineno) {
-        jsvalRoot v(cx);
-        return JS_EvaluateScript(cx, global, bytes, strlen(bytes), filename, lineno, v.addr()) ||
-               fail(bytes, filename, lineno);
-    }
+    bool exec(const char *bytes, const char *filename, int lineno);
 
 #define EVAL(s, vp) do { if (!evaluate(s, __FILE__, __LINE__, vp)) return false; } while (false)
 
-    bool evaluate(const char *bytes, const char *filename, int lineno, jsval *vp) {
-        return JS_EvaluateScript(cx, global, bytes, strlen(bytes), filename, lineno, vp) ||
-               fail(bytes, filename, lineno);
-    }
+    bool evaluate(const char *bytes, const char *filename, int lineno, jsval *vp);
 
     JSAPITestString jsvalToSource(jsval v) {
         JSString *str = JS_ValueToSource(cx, v);
         if (str) {
             JSAutoByteString bytes(cx, str);
             if (!!bytes)
                 return JSAPITestString(bytes.ptr());
         }
@@ -246,18 +198,18 @@ class JSAPITest
 #define CHECK(expr) \
     do { \
         if (!(expr)) \
             return fail("CHECK failed: " #expr, __FILE__, __LINE__); \
     } while (false)
 
     bool fail(JSAPITestString msg = JSAPITestString(), const char *filename = "-", int lineno = 0) {
         if (JS_IsExceptionPending(cx)) {
-            jsvalRoot v(cx);
-            JS_GetPendingException(cx, v.addr());
+            JS::RootedValue v(cx);
+            JS_GetPendingException(cx, v.address());
             JS_ClearPendingException(cx);
             JSString *s = JS_ValueToString(cx, v);
             if (s) {
                 JSAutoByteString bytes(cx, s);
                 if (!!bytes)
                     msg += bytes.ptr();
             }
         }
@@ -294,19 +246,17 @@ class JSAPITest
         }
 
         putchar('\n');
         fflush(stdout);
         JS_SET_RVAL(cx, vp, JSVAL_VOID);
         return JS_TRUE;
     }
 
-    bool definePrint() {
-        return JS_DefineFunction(cx, global, "print", (JSNative) print, 0, 0);
-    }
+    bool definePrint();
 
     virtual JSRuntime * createRuntime() {
         JSRuntime *rt = JS_NewRuntime(8L * 1024 * 1024);
         if (!rt)
             return NULL;
 
         const size_t MAX_STACK_SIZE =
 /* Assume we can't use more than 5e5 bytes of C stack by default. */
@@ -347,39 +297,24 @@ class JSAPITest
         JS_SetErrorReporter(cx, &reportError);
         return cx;
     }
 
     virtual JSClass * getGlobalClass() {
         return basicGlobalClass();
     }
 
-    virtual JSObject * createGlobal(JSPrincipals *principals = NULL) {
-        /* Create the global object. */
-        JSObject *global = JS_NewGlobalObject(cx, getGlobalClass(), principals);
-        if (!global)
-            return NULL;
-
-        JSAutoEnterCompartment ac;
-        if (!ac.enter(cx, global))
-            return NULL;
-
-        /* Populate the global object with the standard globals,
-           like Object and Array. */
-        if (!JS_InitStandardClasses(cx, global))
-            return NULL;
-        return global;
-    }
+    virtual JSObject * createGlobal(JSPrincipals *principals = NULL);
 };
 
 #define BEGIN_TEST(testname)                                            \
     class cls_##testname : public JSAPITest {                           \
       public:                                                           \
         virtual const char * name() { return #testname; }               \
-        virtual bool run()
+        virtual bool run(JS::HandleObject global)
 
 #define END_TEST(testname)                                              \
     };                                                                  \
     static cls_##testname cls_##testname##_instance;
 
 /*
  * A "fixture" is a subclass of JSAPITest that holds common definitions for a
  * set of tests. Each test that wants to use the fixture should use
@@ -387,17 +322,17 @@ class JSAPITest
  * END_TEST, but include the fixture class as the first argument. The fixture
  * class's declarations are then in scope for the test bodies.
  */
 
 #define BEGIN_FIXTURE_TEST(fixture, testname)                           \
     class cls_##testname : public fixture {                             \
       public:                                                           \
         virtual const char * name() { return #testname; }               \
-        virtual bool run()
+        virtual bool run(JS::HandleObject global)
 
 #define END_FIXTURE_TEST(fixture, testname)                             \
     };                                                                  \
     static cls_##testname cls_##testname##_instance;
 
 /*
  * A class for creating and managing one temporary file.
  *
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -286,17 +286,17 @@ JS_ConvertArguments(JSContext *cx, unsig
 JS_PUBLIC_API(JSBool)
 JS_ConvertArgumentsVA(JSContext *cx, unsigned argc, jsval *argv, const char *format, va_list ap)
 {
     jsval *sp;
     JSBool required;
     char c;
     double d;
     JSString *str;
-    JSObject *obj;
+    RootedObject obj(cx);
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, JSValueArray(argv - 2, argc + 2));
     sp = argv;
     required = JS_TRUE;
     while ((c = *format++) != '\0') {
         if (isspace(c))
@@ -441,17 +441,17 @@ JS_RemoveArgumentFormatter(JSContext *cx
         mpp = &map->next;
     }
 }
 
 JS_PUBLIC_API(JSBool)
 JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp)
 {
     JSBool ok;
-    JSObject *obj;
+    RootedObject obj(cx);
     JSString *str;
     double d;
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, v);
     switch (type) {
       case JSTYPE_VOID:
@@ -489,22 +489,26 @@ JS_ConvertValue(JSContext *cx, jsval v, 
         ok = JS_FALSE;
         break;
       }
     }
     return ok;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_ValueToObject(JSContext *cx, jsval v, JSObject **objp)
-{
+JS_ValueToObject(JSContext *cx, jsval v, JSObject **objpArg)
+{
+    RootedObject objp(cx, *objpArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, v);
-    return js_ValueToObjectOrNull(cx, v, objp);
+    if (!js_ValueToObjectOrNull(cx, v, &objp))
+        return false;
+    *objpArg = objp;
+    return true;
 }
 
 JS_PUBLIC_API(JSFunction *)
 JS_ValueToFunction(JSContext *cx, jsval v)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, v);
@@ -1420,17 +1424,17 @@ JS_SetWrapObjectCallbacks(JSRuntime *rt,
     JSWrapObjectCallback old = rt->wrapObjectCallback;
     rt->wrapObjectCallback = callback;
     rt->sameCompartmentWrapObjectCallback = sccallback;
     rt->preWrapObjectCallback = precallback;
     return old;
 }
 
 JS_PUBLIC_API(JSCrossCompartmentCall *)
-JS_EnterCrossCompartmentCall(JSContext *cx, JSObject *target)
+JS_EnterCrossCompartmentCall(JSContext *cx, JSRawObject target)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
 
     JS_ASSERT(target);
     AutoCompartment *call = cx->new_<AutoCompartment>(cx, target);
     if (!call)
         return NULL;
@@ -1451,31 +1455,32 @@ JS_EnterCrossCompartmentCallScript(JSCon
 }
 
 JS_PUBLIC_API(JSCrossCompartmentCall *)
 JS_EnterCrossCompartmentCallStackFrame(JSContext *cx, JSStackFrame *target)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
 
-    return JS_EnterCrossCompartmentCall(cx, &Valueify(target)->global());
+    HandleObject global(HandleObject::fromMarkedLocation((JSObject**) &Valueify(target)->global()));
+    return JS_EnterCrossCompartmentCall(cx, global);
 }
 
 JS_PUBLIC_API(void)
 JS_LeaveCrossCompartmentCall(JSCrossCompartmentCall *call)
 {
     AutoCompartment *realcall = reinterpret_cast<AutoCompartment *>(call);
     AssertHeapIsIdle(realcall->context);
     CHECK_REQUEST(realcall->context);
     realcall->leave();
     Foreground::delete_(realcall);
 }
 
 bool
-JSAutoEnterCompartment::enter(JSContext *cx, JSObject *target)
+JSAutoEnterCompartment::enter(JSContext *cx, JSRawObject target)
 {
     AssertHeapIsIdleOrIterating(cx);
     JS_ASSERT(state == STATE_UNENTERED);
     if (cx->compartment == target->compartment()) {
         state = STATE_SAME_COMPARTMENT;
         return true;
     }
 
@@ -1485,17 +1490,17 @@ JSAutoEnterCompartment::enter(JSContext 
     if (call->enter()) {
         state = STATE_OTHER_COMPARTMENT;
         return true;
     }
     return false;
 }
 
 void
-JSAutoEnterCompartment::enterAndIgnoreErrors(JSContext *cx, JSObject *target)
+JSAutoEnterCompartment::enterAndIgnoreErrors(JSContext *cx, JSRawObject target)
 {
     (void) enter(cx, target);
 }
 
 void
 JSAutoEnterCompartment::leave()
 {
     JS_ASSERT(entered());
@@ -1593,18 +1598,20 @@ JS_WrapValue(JSContext *cx, jsval *vp)
  * itself is used. To avoid ambiguity, JS_TransplantObject always returns the
  * new identity.
  *
  * Second, the new identity object's contents will be those of |target|. A swap()
  * is used to make this happen if an object other than |target| is used.
  */
 
 JS_PUBLIC_API(JSObject *)
-JS_TransplantObject(JSContext *cx, JSObject *origobj, JSObject *target)
-{
+JS_TransplantObject(JSContext *cx, JSObject *origobjArg, JSObject *targetArg)
+{
+    RootedObject origobj(cx, origobjArg);
+    RootedObject target(cx, targetArg);
     AssertHeapIsIdle(cx);
     JS_ASSERT(origobj != target);
     JS_ASSERT(!IsCrossCompartmentWrapper(origobj));
     JS_ASSERT(!IsCrossCompartmentWrapper(target));
 
     /*
      * Transplantation typically allocates new wrappers in every compartment. If
      * an incremental GC is active, this causes every compartment to be leaked
@@ -1650,18 +1657,18 @@ JS_TransplantObject(JSContext *cx, JSObj
     // Now, iterate through other scopes looking for references to the
     // old object, and update the relevant cross-compartment wrappers.
     if (!RemapAllWrappersForObject(cx, origobj, newIdentity))
         return NULL;
 
     // Lastly, update the original object to point to the new one.
     if (origobj->compartment() != destination) {
         AutoCompartment ac(cx, origobj);
-        JSObject *newIdentityWrapper = newIdentity;
-        if (!ac.enter() || !JS_WrapObject(cx, &newIdentityWrapper))
+        RootedObject newIdentityWrapper(cx, newIdentity);
+        if (!ac.enter() || !JS_WrapObject(cx, newIdentityWrapper.address()))
             return NULL;
         if (!origobj->swap(cx, newIdentityWrapper))
             return NULL;
         origobj->compartment()->crossCompartmentWrappers.put(ObjectValue(*newIdentity), origv);
     }
 
     // The new identity object might be one of several things. Return it to avoid
     // ambiguity.
@@ -1673,21 +1680,26 @@ JS_TransplantObject(JSContext *cx, JSObj
  * then the location object wrapper. Because there are no direct references to
  * the location object itself, we don't want the old obj (|origobj| here) to
  * become the new wrapper but the wrapper itself instead. This leads to very
  * subtle differences between js_TransplantObjectWithWrapper and
  * JS_TransplantObject.
  */
 JS_FRIEND_API(JSObject *)
 js_TransplantObjectWithWrapper(JSContext *cx,
-                               JSObject *origobj,
-                               JSObject *origwrapper,
-                               JSObject *targetobj,
-                               JSObject *targetwrapper)
-{
+                               JSObject *origobjArg,
+                               JSObject *origwrapperArg,
+                               JSObject *targetobjArg,
+                               JSObject *targetwrapperArg)
+{
+    RootedObject origobj(cx, origobjArg);
+    RootedObject origwrapper(cx, origwrapperArg);
+    RootedObject targetobj(cx, targetobjArg);
+    RootedObject targetwrapper(cx, targetwrapperArg);
+
     AssertHeapIsIdle(cx);
     JS_ASSERT(!IsCrossCompartmentWrapper(origobj));
     JS_ASSERT(!IsCrossCompartmentWrapper(origwrapper));
     JS_ASSERT(!IsCrossCompartmentWrapper(targetobj));
     JS_ASSERT(!IsCrossCompartmentWrapper(targetwrapper));
 
     JSObject *newWrapper;
     JSCompartment *destination = targetobj->compartment();
@@ -1724,59 +1736,61 @@ js_TransplantObjectWithWrapper(JSContext
 
     // Lastly, update things in the original compartment. Our invariants dictate
     // that the original compartment can only have one cross-compartment wrapper
     // to the new object. So we choose to update |origwrapper|, not |origobj|,
     // since theoretically there should have been no direct intra-compartment
     // references to |origobj|.
     {
         AutoCompartment ac(cx, origobj);
-        JSObject *wrapperGuts = targetobj;
-        if (!ac.enter() || !JS_WrapObject(cx, &wrapperGuts))
+        RootedObject wrapperGuts(cx, targetobj);
+        if (!ac.enter() || !JS_WrapObject(cx, wrapperGuts.address()))
             return NULL;
         if (!origwrapper->swap(cx, wrapperGuts))
             return NULL;
         origwrapper->compartment()->crossCompartmentWrappers.put(ObjectValue(*targetobj),
                                                                  ObjectValue(*origwrapper));
     }
 
     return newWrapper;
 }
 
 /*
  * Recompute all cross-compartment wrappers for an object, resetting state.
  * Gecko uses this to clear Xray wrappers when doing a navigation that reuses
  * the inner window and global object.
  */
 JS_PUBLIC_API(JSBool)
-JS_RefreshCrossCompartmentWrappers(JSContext *cx, JSObject *obj)
-{
+JS_RefreshCrossCompartmentWrappers(JSContext *cx, JSObject *objArg)
+{
+    RootedObject obj(cx, objArg);
     return RemapAllWrappersForObject(cx, obj, obj);
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_GetGlobalObject(JSContext *cx)
 {
     return cx->globalObject;
 }
 
 JS_PUBLIC_API(void)
-JS_SetGlobalObject(JSContext *cx, JSObject *obj)
+JS_SetGlobalObject(JSContext *cx, JSRawObject obj)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
 
     cx->globalObject = obj;
     if (!cx->hasfp())
         cx->resetCompartment();
 }
 
 JS_PUBLIC_API(JSBool)
-JS_InitStandardClasses(JSContext *cx, JSObject *obj)
-{
+JS_InitStandardClasses(JSContext *cx, JSObject *objArg)
+{
+    RootedObject obj(cx, objArg);
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
 
     /*
      * JS_SetGlobalObject might or might not change cx's compartment, so call
      * it before assertSameCompartment. (The API contract is that *after* this,
      * cx and obj must be in the same compartment.)
@@ -1925,43 +1939,42 @@ static JSStdName object_prototype_names[
     {js_InitObjectClass,        EAGER_ATOM(lookupGetter), CLASP(Object)},
     {js_InitObjectClass,        EAGER_ATOM(lookupSetter), CLASP(Object)},
 #endif
 
     {NULL,                      0, NULL}
 };
 
 JS_PUBLIC_API(JSBool)
-JS_ResolveStandardClass(JSContext *cx, JSObject *obj_, jsid id, JSBool *resolved)
-{
+JS_ResolveStandardClass(JSContext *cx, JSObject *objArg, jsid id, JSBool *resolved)
+{
+    RootedObject obj(cx, objArg);
     JSString *idstr;
     JSRuntime *rt;
     JSAtom *atom;
     JSStdName *stdnm;
     unsigned i;
 
-    RootedObject obj(cx, obj_);
-
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, id);
     *resolved = false;
 
     rt = cx->runtime;
     if (!rt->hasContexts() || !JSID_IS_ATOM(id))
         return true;
 
     idstr = JSID_TO_STRING(id);
 
     /* Check whether we're resolving 'undefined', and define it if so. */
     atom = rt->atomState.typeAtoms[JSTYPE_VOID];
     if (idstr == atom) {
         *resolved = true;
-        RootedValue value(cx, UndefinedValue());
-        return obj->defineProperty(cx, atom->asPropertyName(), value,
+        RootedValue undefinedValue(cx, UndefinedValue());
+        return obj->defineProperty(cx, atom->asPropertyName(), undefinedValue,
                                    JS_PropertyStub, JS_StrictPropertyStub,
                                    JSPROP_PERMANENT | JSPROP_READONLY);
     }
 
     /* Try for class constructors/prototypes named by well-known atoms. */
     stdnm = NULL;
     for (i = 0; standard_class_atoms[i].init; i++) {
         JS_ASSERT(standard_class_atoms[i].clasp);
@@ -2029,23 +2042,22 @@ JS_ResolveStandardClass(JSContext *cx, J
         if (!stdnm->init(cx, obj))
             return false;
         *resolved = true;
     }
     return true;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_EnumerateStandardClasses(JSContext *cx, JSObject *obj_)
-{
-    AssertHeapIsIdle(cx);
-    CHECK_REQUEST(cx);
-    assertSameCompartment(cx, obj_);
-
-    RootedObject obj(cx, obj_);
+JS_EnumerateStandardClasses(JSContext *cx, JSObject *objArg)
+{
+    RootedObject obj(cx, objArg);
+    AssertHeapIsIdle(cx);
+    CHECK_REQUEST(cx);
+    assertSameCompartment(cx, obj);
 
     /*
      * Check whether we need to bind 'undefined' and define it if so.
      * Since ES5 15.1.1.3 undefined can't be deleted.
      */
     RootedPropertyName undefinedName(cx, cx->runtime->atomState.typeAtoms[JSTYPE_VOID]);
     RootedId undefinedId(cx, NameToId(undefinedName));
     RootedValue undefinedValue(cx, UndefinedValue());
@@ -2119,29 +2131,30 @@ AddNameToArray(JSContext *cx, PropertyNa
         JS_ASSERT(i < ida->length);
     }
     ida->vector[i].init(NameToId(name));
     *ip = i + 1;
     return ida;
 }
 
 static JSIdArray *
-EnumerateIfResolved(JSContext *cx, JSObject *obj, PropertyName *name, JSIdArray *ida,
+EnumerateIfResolved(JSContext *cx, JSHandleObject obj, PropertyName *name, JSIdArray *ida,
                     int *ip, JSBool *foundp)
 {
     RootedId id(cx, NameToId(name));
     *foundp = obj->nativeContains(cx, id);
     if (*foundp)
         ida = AddNameToArray(cx, name, ida, ip);
     return ida;
 }
 
 JS_PUBLIC_API(JSIdArray *)
-JS_EnumerateResolvedStandardClasses(JSContext *cx, JSObject *obj, JSIdArray *ida)
-{
+JS_EnumerateResolvedStandardClasses(JSContext *cx, JSObject *objArg, JSIdArray *ida)
+{
+    RootedObject obj(cx, objArg);
     JSRuntime *rt;
     int i, j, k;
     PropertyName *name;
     JSBool found;
     JSClassInitializerOp init;
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
@@ -2197,26 +2210,27 @@ JS_EnumerateResolvedStandardClasses(JSCo
 }
 
 #undef CLASP
 #undef EAGER_ATOM
 #undef EAGER_CLASS_ATOM
 #undef EAGER_ATOM_CLASP
 
 JS_PUBLIC_API(JSBool)
-JS_GetClassObject(JSContext *cx, JSObject *obj_, JSProtoKey key, JSObject **objp_)
-{
-    AssertHeapIsIdle(cx);
-    CHECK_REQUEST(cx);
-    RootedObject obj(cx, obj_);
-    RootedObject objp(cx);
+JS_GetClassObject(JSContext *cx, JSRawObject obj, JSProtoKey key, JSObject **objpArg)
+{
+    RootedObject objp(cx, *objpArg);
+    AssertHeapIsIdle(cx);
+    CHECK_REQUEST(cx);
+
     assertSameCompartment(cx, obj);
-    bool result = js_GetClassObject(cx, obj, key, &objp);
-    *objp_ = objp;
-    return result;
+    if (!js_GetClassObject(cx, obj, key, &objp))
+        return false;
+    *objpArg = objp;
+    return true;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_GetClassPrototype(JSContext *cx, JSProtoKey key, JSObject **objp_)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     RootedObject global(cx, cx->compartment->maybeGlobal());
@@ -2234,33 +2248,33 @@ JS_IdentifyClassPrototype(JSContext *cx,
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     JS_ASSERT(!IsCrossCompartmentWrapper(obj));
     return js_IdentifyClassPrototype(obj);
 }
 
 JS_PUBLIC_API(JSObject *)
-JS_GetObjectPrototype(JSContext *cx, JSObject *forObj)
+JS_GetObjectPrototype(JSContext *cx, JSRawObject forObj)
 {
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, forObj);
     return forObj->global().getOrCreateObjectPrototype(cx);
 }
 
 JS_PUBLIC_API(JSObject *)
-JS_GetFunctionPrototype(JSContext *cx, JSObject *forObj)
+JS_GetFunctionPrototype(JSContext *cx, JSRawObject forObj)
 {
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, forObj);
     return forObj->global().getOrCreateFunctionPrototype(cx);
 }
 
 JS_PUBLIC_API(JSObject *)
-JS_GetGlobalForObject(JSContext *cx, JSObject *obj)
+JS_GetGlobalForObject(JSContext *cx, JSRawObject obj)
 {
     AssertHeapIsIdle(cx);
     assertSameCompartment(cx, obj);
     return &obj->global();
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_GetGlobalForCompartmentOrNull(JSContext *cx, JSCompartment *c)
@@ -3186,18 +3200,19 @@ JS_IdToValue(JSContext *cx, jsid id, jsv
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     *vp = IdToJsval(id);
     assertSameCompartment(cx, *vp);
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp)
-{
+JS_DefaultValue(JSContext *cx, JSObject *objArg, JSType hint, jsval *vp)
+{
+    RootedObject obj(cx, objArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     JS_ASSERT(obj != NULL);
     JS_ASSERT(hint == JSTYPE_VOID || hint == JSTYPE_STRING || hint == JSTYPE_NUMBER);
 
     RootedValue value(cx);
     if (!obj->defaultValue(cx, hint, &value))
         return false;
@@ -3234,45 +3249,48 @@ JS_PUBLIC_API(JSBool)
 JS_ConvertStub(JSContext *cx, JSHandleObject obj, JSType type, JSMutableHandleValue vp)
 {
     JS_ASSERT(type != JSTYPE_OBJECT && type != JSTYPE_FUNCTION);
     JS_ASSERT(obj);
     return DefaultValue(cx, obj, type, vp);
 }
 
 JS_PUBLIC_API(JSObject *)
-JS_InitClass(JSContext *cx, JSObject *obj_, JSObject *parent_proto,
+JS_InitClass(JSContext *cx, JSObject *objArg, JSObject *parent_protoArg,
              JSClass *clasp, JSNative constructor, unsigned nargs,
              JSPropertySpec *ps, JSFunctionSpec *fs,
              JSPropertySpec *static_ps, JSFunctionSpec *static_fs)
 {
-    RootedObject obj(cx, obj_);
-
+    RootedObject obj(cx, objArg);
+    RootedObject parent_proto(cx, parent_protoArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, parent_proto);
     return js_InitClass(cx, obj, parent_proto, Valueify(clasp), constructor,
                         nargs, ps, fs, static_ps, static_fs);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_LinkConstructorAndPrototype(JSContext *cx, JSObject *ctor, JSObject *proto)
-{
+JS_LinkConstructorAndPrototype(JSContext *cx, JSObject *ctorArg, JSObject *protoArg)
+{
+    RootedObject ctor(cx, ctorArg);
+    RootedObject proto(cx, protoArg);
     return LinkConstructorAndPrototype(cx, ctor, proto);
 }
 
 JS_PUBLIC_API(JSClass *)
-JS_GetClass(JSObject *obj)
+JS_GetClass(RawObject obj)
 {
     return obj->getJSClass();
 }
 
 JS_PUBLIC_API(JSBool)
-JS_InstanceOf(JSContext *cx, JSObject *obj, JSClass *clasp, jsval *argv)
-{
+JS_InstanceOf(JSContext *cx, JSObject *objArg, JSClass *clasp, jsval *argv)
+{
+    RootedObject obj(cx, objArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
 #ifdef DEBUG
     if (argv) {
         assertSameCompartment(cx, obj);
         assertSameCompartment(cx, JSValueArray(argv - 2, 2));
     }
 #endif
@@ -3280,89 +3298,90 @@ JS_InstanceOf(JSContext *cx, JSObject *o
         if (argv)
             ReportIncompatibleMethod(cx, CallReceiverFromArgv(argv), Valueify(clasp));
         return false;
     }
     return true;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_HasInstance(JSContext *cx, JSObject *obj_, jsval v, JSBool *bp)
-{
-    RootedObject obj(cx, obj_);
-
+JS_HasInstance(JSContext *cx, JSObject *objArg, jsval v, JSBool *bp)
+{
+    RootedObject obj(cx, objArg);
     AssertHeapIsIdle(cx);
     assertSameCompartment(cx, obj, v);
     return HasInstance(cx, obj, &v, bp);
 }
 
 JS_PUBLIC_API(void *)
-JS_GetPrivate(JSObject *obj)
+JS_GetPrivate(RawObject obj)
 {
     /* This function can be called by a finalizer. */
     return obj->getPrivate();
 }
 
 JS_PUBLIC_API(void)
-JS_SetPrivate(JSObject *obj, void *data)
+JS_SetPrivate(RawObject obj, void *data)
 {
     /* This function can be called by a finalizer. */
     obj->setPrivate(data);
 }
 
 JS_PUBLIC_API(void *)
-JS_GetInstancePrivate(JSContext *cx, JSObject *obj, JSClass *clasp, jsval *argv)
-{
+JS_GetInstancePrivate(JSContext *cx, JSObject *objArg, JSClass *clasp, jsval *argv)
+{
+    RootedObject obj(cx, objArg);
     if (!JS_InstanceOf(cx, obj, clasp, argv))
         return NULL;
     return obj->getPrivate();
 }
 
 JS_PUBLIC_API(JSObject *)
-JS_GetPrototype(JSObject *obj)
+JS_GetPrototype(RawObject obj)
 {
     return obj->getProto();
 }
 
 JS_PUBLIC_API(JSBool)
-JS_SetPrototype(JSContext *cx, JSObject *obj_, JSObject *proto_)
-{
-    AssertHeapIsIdle(cx);
-    CHECK_REQUEST(cx);
-    assertSameCompartment(cx, obj_, proto_);
-
-    Rooted<JSObject*> obj(cx, obj_);
-    Rooted<JSObject*> proto(cx, proto_);
+JS_SetPrototype(JSContext *cx, JSObject *objArg, JSObject *protoArg)
+{
+    RootedObject obj(cx, objArg);
+    RootedObject proto(cx, protoArg);
+    AssertHeapIsIdle(cx);
+    CHECK_REQUEST(cx);
+    assertSameCompartment(cx, obj, proto);
+
     return SetProto(cx, obj, proto, JS_FALSE);
 }
 
 JS_PUBLIC_API(JSObject *)
-JS_GetParent(JSObject *obj)
+JS_GetParent(RawObject obj)
 {
     JS_ASSERT(!obj->isScope());
     return obj->getParent();
 }
 
 JS_PUBLIC_API(JSBool)
-JS_SetParent(JSContext *cx, JSObject *obj_, JSObject *parent_)
-{
-    AssertHeapIsIdle(cx);
-    CHECK_REQUEST(cx);
-    JS_ASSERT(!obj_->isScope());
-    JS_ASSERT(parent_ || !obj_->getParent());
-    assertSameCompartment(cx, obj_, parent_);
-
-    Rooted<JSObject*> obj(cx, obj_);
-    Rooted<JSObject*> parent(cx, parent_);
+JS_SetParent(JSContext *cx, JSObject *objArg, JSObject *parentArg)
+{
+    RootedObject obj(cx, objArg);
+    RootedObject parent(cx, parentArg);
+    AssertHeapIsIdle(cx);
+    CHECK_REQUEST(cx);
+    JS_ASSERT(!obj->isScope());
+    JS_ASSERT(parent || !obj->getParent());
+    assertSameCompartment(cx, obj, parent);
+
     return JSObject::setParent(cx, obj, parent);
 }
 
 JS_PUBLIC_API(JSObject *)
-JS_GetConstructor(JSContext *cx, JSObject *proto)
-{
+JS_GetConstructor(JSContext *cx, JSObject *protoArg)
+{
+    RootedObject proto(cx, protoArg);
     RootedValue cval(cx);
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, proto);
     {
         JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
 
@@ -3373,17 +3392,17 @@ JS_GetConstructor(JSContext *cx, JSObjec
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_CONSTRUCTOR,
                              proto->getClass()->name);
         return NULL;
     }
     return &cval.toObject();
 }
 
 JS_PUBLIC_API(JSBool)
-JS_GetObjectId(JSContext *cx, JSObject *obj, jsid *idp)
+JS_GetObjectId(JSContext *cx, JSRawObject obj, jsid *idp)
 {
     AssertHeapIsIdle(cx);
     assertSameCompartment(cx, obj);
     *idp = OBJECT_TO_JSID(obj);
     return JS_TRUE;
 }
 
 class AutoHoldCompartment {
@@ -3420,21 +3439,20 @@ JS_NewGlobalObject(JSContext *cx, JSClas
     cx->setCompartment(compartment);
     GlobalObject *global = GlobalObject::create(cx, Valueify(clasp));
     cx->setCompartment(saved);
 
     return global;
 }
 
 JS_PUBLIC_API(JSObject *)
-JS_NewObject(JSContext *cx, JSClass *jsclasp, JSObject *proto_, JSObject *parent_)
-{
-    RootedObject proto(cx, proto_);
-    RootedObject parent(cx, parent_);
-
+JS_NewObject(JSContext *cx, JSClass *jsclasp, JSObject *protoArg, JSObject *parentArg)
+{
+    RootedObject proto(cx, protoArg);
+    RootedObject parent(cx, parentArg);
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, proto, parent);
 
     Class *clasp = Valueify(jsclasp);
     if (!clasp)
         clasp = &ObjectClass;    /* default class is Object */
@@ -3449,18 +3467,20 @@ JS_NewObject(JSContext *cx, JSClass *jsc
             MarkTypeObjectFlags(cx, obj, OBJECT_FLAG_SPECIAL_EQUALITY);
     }
 
     JS_ASSERT_IF(obj, obj->getParent());
     return obj;
 }
 
 JS_PUBLIC_API(JSObject *)
-JS_NewObjectWithGivenProto(JSContext *cx, JSClass *jsclasp, JSObject *proto, JSObject *parent)
-{
+JS_NewObjectWithGivenProto(JSContext *cx, JSClass *jsclasp, JSObject *protoArg, JSObject *parentArg)
+{
+    RootedObject proto(cx, protoArg);
+    RootedObject parent(cx, parentArg);
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, proto, parent);
 
     Class *clasp = Valueify(jsclasp);
     if (!clasp)
         clasp = &ObjectClass;    /* default class is Object */
@@ -3482,64 +3502,66 @@ JS_NewObjectForConstructor(JSContext *cx
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, *vp);
 
     RootedObject obj(cx, JSVAL_TO_OBJECT(*vp));
     return js_CreateThis(cx, Valueify(clasp), obj);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_IsExtensible(JSObject *obj)
+JS_IsExtensible(JSRawObject obj)
 {
     return obj->isExtensible();
 }
 
 JS_PUBLIC_API(JSBool)
-JS_IsNative(JSObject *obj)
+JS_IsNative(JSRawObject obj)
 {
     return obj->isNative();
 }
 
 JS_PUBLIC_API(JSRuntime *)
-JS_GetObjectRuntime(JSObject *obj)
+JS_GetObjectRuntime(JSRawObject obj)
 {
     return obj->compartment()->rt;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_FreezeObject(JSContext *cx, JSObject *obj)
-{
+JS_FreezeObject(JSContext *cx, JSObject *objArg)
+{
+    RootedObject obj(cx, objArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
 
     return obj->freeze(cx);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_DeepFreezeObject(JSContext *cx, JSObject *obj_)
-{
-    RootedObject obj(cx, obj_);
+JS_DeepFreezeObject(JSContext *cx, JSObject *objArg)
+{
+    RootedObject obj(cx, objArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
 
     /* Assume that non-extensible objects are already deep-frozen, to avoid divergence. */
     if (!obj->isExtensible())
         return true;
 
     if (!obj->freeze(cx))
         return false;
 
     /* Walk slots in obj and if any value is a non-null object, seal it. */
     for (uint32_t i = 0, n = obj->slotSpan(); i < n; ++i) {
         const Value &v = obj->getSlot(i);
         if (v.isPrimitive())
             continue;
-        if (!JS_DeepFreezeObject(cx, &v.toObject()))
+        RootedObject obj(cx, &v.toObject());
+        if (!JS_DeepFreezeObject(cx, obj))
             return false;
     }
 
     return true;
 }
 
 static JSBool
 LookupPropertyById(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
@@ -3586,129 +3608,133 @@ LookupResult(JSContext *cx, HandleObject
     }
 
     /* XXX bad API: no way to return "defined but value unknown" */
     vp->setBoolean(true);
     return true;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_LookupPropertyById(JSContext *cx, JSObject *obj_, jsid id_, jsval *vp)
-{
-    RootedId id(cx, id_);
-    RootedObject obj(cx, obj_);
+JS_LookupPropertyById(JSContext *cx, JSObject *objArg, jsid idArg, jsval *vp)
+{
+    RootedId id(cx, idArg);
+    RootedObject obj(cx, objArg);
     RootedObject obj2(cx);
     RootedShape prop(cx);
 
     return LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &prop) &&
            LookupResult(cx, obj, obj2, id, prop, vp);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_LookupElement(JSContext *cx, JSObject *obj, uint32_t index, jsval *vp)
-{
+JS_LookupElement(JSContext *cx, JSObject *objArg, uint32_t index, jsval *vp)
+{
+    RootedObject obj(cx, objArg);
     CHECK_REQUEST(cx);
     jsid id;
     if (!IndexToId(cx, index, &id))
         return false;
     return JS_LookupPropertyById(cx, obj, id, vp);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_LookupProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
-{
+JS_LookupProperty(JSContext *cx, JSObject *objArg, const char *name, jsval *vp)
+{
+    RootedObject obj(cx, objArg);
     JSAtom *atom = js_Atomize(cx, name, strlen(name));
     return atom && JS_LookupPropertyById(cx, obj, AtomToId(atom), vp);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_LookupUCProperty(JSContext *cx, JSObject *obj_, const jschar *name, size_t namelen, jsval *vp)
-{
-    RootedObject obj(cx, obj_);
+JS_LookupUCProperty(JSContext *cx, JSObject *objArg, const jschar *name, size_t namelen, jsval *vp)
+{
+    RootedObject obj(cx, objArg);
     JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
     return atom && JS_LookupPropertyById(cx, obj, AtomToId(atom), vp);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_LookupPropertyWithFlagsById(JSContext *cx, JSObject *obj_, jsid id_, unsigned flags,
-                               JSObject **objp_, jsval *vp)
-{
-    RootedObject obj(cx, obj_);
-    RootedObject objp(cx, *objp_);
+JS_LookupPropertyWithFlagsById(JSContext *cx, JSObject *objArg, jsid id_, unsigned flags,
+                               JSObject **objpArg, jsval *vp)
+{
+    RootedObject obj(cx, objArg);
+    RootedObject objp(cx, *objpArg);
     RootedId id(cx, id_);
     RootedShape prop(cx);
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, id);
     if (!(obj->isNative()
           ? LookupPropertyWithFlags(cx, obj, id, flags, &objp, &prop)
           : obj->lookupGeneric(cx, id, &objp, &prop)))
         return false;
 
     if (!LookupResult(cx, obj, objp, id, prop, vp))
         return false;
 
-    *objp_ = objp;
+    *objpArg = objp;
     return true;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, const char *name, unsigned flags, jsval *vp)
-{
+JS_LookupPropertyWithFlags(JSContext *cx, JSObject *objArg, const char *name, unsigned flags, jsval *vp)
+{
+    RootedObject obj(cx, objArg);
     JSObject *obj2;
     JSAtom *atom = js_Atomize(cx, name, strlen(name));
     return atom && JS_LookupPropertyWithFlagsById(cx, obj, AtomToId(atom), flags, &obj2, vp);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_HasPropertyById(JSContext *cx, JSObject *obj_, jsid id_, JSBool *foundp)
-{
-    RootedObject obj(cx, obj_);
-    RootedId id(cx, id_);
+JS_HasPropertyById(JSContext *cx, JSObject *objArg, jsid idArg, JSBool *foundp)
+{
+    RootedObject obj(cx, objArg);
+    RootedId id(cx, idArg);
     RootedObject obj2(cx);
     RootedShape prop(cx);
     JSBool ok = LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING,
                                    &obj2, &prop);
     *foundp = (prop != NULL);
     return ok;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_HasElement(JSContext *cx, JSObject *obj, uint32_t index, JSBool *foundp)
-{
+JS_HasElement(JSContext *cx, JSObject *objArg, uint32_t index, JSBool *foundp)
+{
+    RootedObject obj(cx, objArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     jsid id;
     if (!IndexToId(cx, index, &id))
         return false;
     return JS_HasPropertyById(cx, obj, id, foundp);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_HasProperty(JSContext *cx, JSObject *obj, const char *name, JSBool *foundp)
-{
+JS_HasProperty(JSContext *cx, JSObject *objArg, const char *name, JSBool *foundp)
+{
+    RootedObject obj(cx, objArg);
     JSAtom *atom = js_Atomize(cx, name, strlen(name));
     return atom && JS_HasPropertyById(cx, obj, AtomToId(atom), foundp);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_HasUCProperty(JSContext *cx, JSObject *obj_, const jschar *name, size_t namelen, JSBool *foundp)
-{
-    RootedObject obj(cx, obj_);
+JS_HasUCProperty(JSContext *cx, JSObject *objArg, const jschar *name, size_t namelen, JSBool *foundp)
+{
+    RootedObject obj(cx, objArg);
     JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
     return atom && JS_HasPropertyById(cx, obj, AtomToId(atom), foundp);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_AlreadyHasOwnPropertyById(JSContext *cx, JSObject *obj_, jsid id_, JSBool *foundp)
-{
+JS_AlreadyHasOwnPropertyById(JSContext *cx, JSObject *objArg, jsid id_, JSBool *foundp)
+{
+    RootedObject obj(cx, objArg);
     RootedId id(cx, id_);
-    RootedObject obj(cx, obj_);
-
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, id);
 
     if (!obj->isNative()) {
         RootedObject obj2(cx);
         RootedShape prop(cx);
 
@@ -3720,38 +3746,40 @@ JS_AlreadyHasOwnPropertyById(JSContext *
         return JS_TRUE;
     }
 
     *foundp = obj->nativeContains(cx, id);
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_AlreadyHasOwnElement(JSContext *cx, JSObject *obj, uint32_t index, JSBool *foundp)
-{
+JS_AlreadyHasOwnElement(JSContext *cx, JSObject *objArg, uint32_t index, JSBool *foundp)
+{
+    RootedObject obj(cx, objArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     jsid id;
     if (!IndexToId(cx, index, &id))
         return false;
     return JS_AlreadyHasOwnPropertyById(cx, obj, id, foundp);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_AlreadyHasOwnProperty(JSContext *cx, JSObject *obj, const char *name, JSBool *foundp)
-{
+JS_AlreadyHasOwnProperty(JSContext *cx, JSObject *objArg, const char *name, JSBool *foundp)
+{
+    RootedObject obj(cx, objArg);
     JSAtom *atom = js_Atomize(cx, name, strlen(name));
     return atom && JS_AlreadyHasOwnPropertyById(cx, obj, AtomToId(atom), foundp);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_AlreadyHasOwnUCProperty(JSContext *cx, JSObject *obj_, const jschar *name, size_t namelen,
+JS_AlreadyHasOwnUCProperty(JSContext *cx, JSObject *objArg, const jschar *name, size_t namelen,
                            JSBool *foundp)
 {
-    RootedObject obj(cx, obj_);
+    RootedObject obj(cx, objArg);
     JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
     return atom && JS_AlreadyHasOwnPropertyById(cx, obj, AtomToId(atom), foundp);
 }
 
 static JSBool
 DefinePropertyById(JSContext *cx, HandleObject obj, HandleId id, HandleValue value,
                    PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
                    unsigned flags, int tinyid)
@@ -3770,26 +3798,28 @@ DefinePropertyById(JSContext *cx, Handle
      * than JSNatives. However, we might be pulling this property descriptor off
      * of something with JSNative property descriptors. If we are, wrap them in
      * JS Function objects.
      */
     if (attrs & JSPROP_NATIVE_ACCESSORS) {
         JS_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
         attrs &= ~JSPROP_NATIVE_ACCESSORS;
         if (getter) {
-            JSObject *getobj = JS_NewFunction(cx, (Native) getter, 0, 0, &obj->global(), NULL);
+            RootedObject global(cx, (JSObject*) &obj->global());
+            JSObject *getobj = JS_NewFunction(cx, (Native) getter, 0, 0, global, NULL);
             if (!getobj)
                 return false;
             getter = JS_DATA_TO_FUNC_PTR(PropertyOp, getobj);
             attrs |= JSPROP_GETTER;
         }
         if (setter) {
             // Root just the getter, since the setter is not yet a JSObject.
             AutoRooterGetterSetter getRoot(cx, JSPROP_GETTER, &getter, NULL);
-            JSObject *setobj = JS_NewFunction(cx, (Native) setter, 1, 0, &obj->global(), NULL);
+            RootedObject global(cx, (JSObject*) &obj->global());
+            JSObject *setobj = JS_NewFunction(cx, (Native) setter, 1, 0, global, NULL);
             if (!setobj)
                 return false;
             setter = JS_DATA_TO_FUNC_PTR(StrictPropertyOp, setobj);
             attrs |= JSPROP_SETTER;
         }
     }
 
 
@@ -3807,46 +3837,45 @@ DefinePropertyById(JSContext *cx, Handle
     if (flags != 0 && obj->isNative()) {
         return !!DefineNativeProperty(cx, obj, id, value, getter, setter,
                                       attrs, flags, tinyid);
     }
     return obj->defineGeneric(cx, id, value, getter, setter, attrs);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_DefinePropertyById(JSContext *cx, JSObject *obj_, jsid id_, jsval value_,
+JS_DefinePropertyById(JSContext *cx, JSObject *objArg, jsid idArg, jsval value_,
                       JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
 {
-    RootedObject obj(cx, obj_);
-    RootedId id(cx, id_);
+    RootedObject obj(cx, objArg);
+    RootedId id(cx, idArg);
     RootedValue value(cx, value_);
     return DefinePropertyById(cx, obj, id, value, getter, setter, attrs, 0, 0);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_DefineElement(JSContext *cx, JSObject *obj_, uint32_t index, jsval value_,
+JS_DefineElement(JSContext *cx, JSObject *objArg, uint32_t index, jsval valueArg,
                  JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
 {
-    RootedObject obj(cx, obj_);
-    RootedValue value(cx, value_);
+    RootedObject obj(cx, objArg);
+    RootedValue value(cx, valueArg);
     AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     RootedId id(cx);
     if (!IndexToId(cx, index, id.address()))
         return false;
     return DefinePropertyById(cx, obj, id, value, getter, setter, attrs, 0, 0);
 }
 
 static JSBool
-DefineProperty(JSContext *cx, JSObject *obj_, const char *name, const Value &value_,
+DefineProperty(JSContext *cx, JSHandleObject obj, const char *name, const Value &value_,
                PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
                unsigned flags, int tinyid)
 {
-    RootedObject obj(cx, obj_);
     RootedValue value(cx, value_);
     AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
     RootedId id(cx);
 
     if (attrs & JSPROP_INDEX) {
         id = INT_TO_JSID(intptr_t(name));
         attrs &= ~JSPROP_INDEX;
     } else {
@@ -3855,101 +3884,103 @@ DefineProperty(JSContext *cx, JSObject *
             return JS_FALSE;
         id = AtomToId(atom);
     }
 
     return DefinePropertyById(cx, obj, id, value, getter, setter, attrs, flags, tinyid);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_DefineProperty(JSContext *cx, JSObject *obj, const char *name, jsval value,
+JS_DefineProperty(JSContext *cx, JSObject *objArg, const char *name, jsval value,
                   PropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
 {
+    RootedObject obj(cx, objArg);
     return DefineProperty(cx, obj, name, value, getter, setter, attrs, 0, 0);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_DefinePropertyWithTinyId(JSContext *cx, JSObject *obj, const char *name, int8_t tinyid,
+JS_DefinePropertyWithTinyId(JSContext *cx, JSObject *objArg, const char *name, int8_t tinyid,
                             jsval value, PropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
 {
+    RootedObject obj(cx, objArg);
     return DefineProperty(cx, obj, name, value, getter, setter, attrs, Shape::HAS_SHORTID, tinyid);
 }
 
 static JSBool
-DefineUCProperty(JSContext *cx, JSObject *obj_, const jschar *name, size_t namelen,
+DefineUCProperty(JSContext *cx, JSHandleObject obj, const jschar *name, size_t namelen,
                  const Value &value_, PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
                  unsigned flags, int tinyid)
 {
-    RootedObject obj(cx, obj_);
     RootedValue value(cx, value_);
     AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
     JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
     if (!atom)
         return false;
     RootedId id(cx, AtomToId(atom));
     return DefinePropertyById(cx, obj, id, value, getter, setter, attrs, flags, tinyid);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_DefineUCProperty(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen,
+JS_DefineUCProperty(JSContext *cx, JSObject *objArg, const jschar *name, size_t namelen,
                     jsval value, JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
 {
+    RootedObject obj(cx, objArg);
     return DefineUCProperty(cx, obj, name, namelen, value, getter, setter, attrs, 0, 0);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_DefineUCPropertyWithTinyId(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen,
+JS_DefineUCPropertyWithTinyId(JSContext *cx, JSObject *objArg, const jschar *name, size_t namelen,
                               int8_t tinyid, jsval value,
                               JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
 {
+    RootedObject obj(cx, objArg);
     return DefineUCProperty(cx, obj, name, namelen, value, getter, setter, attrs,
                             Shape::HAS_SHORTID, tinyid);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_DefineOwnProperty(JSContext *cx, JSObject *obj_, jsid id_, jsval descriptor, JSBool *bp)
-{
-    AssertHeapIsIdle(cx);
-    CHECK_REQUEST(cx);
-    assertSameCompartment(cx, obj_, id_, descriptor);
-
-    Rooted<JSObject*> obj(cx, obj_);
-    Rooted<jsid> id(cx, id_);
+JS_DefineOwnProperty(JSContext *cx, JSObject *objArg, jsid idArg, jsval descriptor, JSBool *bp)
+{
+    RootedObject obj(cx, objArg);
+    RootedId id(cx, idArg);
+    AssertHeapIsIdle(cx);
+    CHECK_REQUEST(cx);
+    assertSameCompartment(cx, obj, id, descriptor);
+
     return js_DefineOwnProperty(cx, obj, id, descriptor, bp);
 }
 
 JS_PUBLIC_API(JSObject *)
-JS_DefineObject(JSContext *cx, JSObject *obj_, const char *name, JSClass *jsclasp,
-                JSObject *proto, unsigned attrs)
-{
-    RootedObject obj(cx, obj_), nobj(cx);
-
+JS_DefineObject(JSContext *cx, JSObject *objArg, const char *name, JSClass *jsclasp,
+                JSObject *protoArg, unsigned attrs)
+{
+    RootedObject obj(cx, objArg);
+    RootedObject proto(cx, protoArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, proto);
 
     Class *clasp = Valueify(jsclasp);
     if (!clasp)
         clasp = &ObjectClass;    /* default class is Object */
 
-    nobj = NewObjectWithClassProto(cx, clasp, proto, obj);
+    JSObject *nobj = NewObjectWithClassProto(cx, clasp, proto, obj);
     if (!nobj)
         return NULL;
 
     if (!DefineProperty(cx, obj, name, ObjectValue(*nobj), NULL, NULL, attrs, 0, 0))
         return NULL;
 
     return nobj;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_DefineConstDoubles(JSContext *cx, JSObject *obj_, JSConstDoubleSpec *cds)
-{
-    RootedObject obj(cx, obj_);
-
+JS_DefineConstDoubles(JSContext *cx, JSObject *objArg, JSConstDoubleSpec *cds)
+{
+    RootedObject obj(cx, objArg);
     JSBool ok;
     unsigned attrs;
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     for (ok = JS_TRUE; cds->name; cds++) {
         Value value = DoubleValue(cds->dval);
         attrs = cds->flags;
@@ -3958,21 +3989,20 @@ JS_DefineConstDoubles(JSContext *cx, JSO
         ok = DefineProperty(cx, obj, cds->name, value, NULL, NULL, attrs, 0, 0);
         if (!ok)
             break;
     }
     return ok;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_DefineProperties(JSContext *cx, JSObject *obj_, JSPropertySpec *ps)
-{
+JS_DefineProperties(JSContext *cx, JSObject *objArg, JSPropertySpec *ps)
+{
+    RootedObject obj(cx, objArg);
     JSBool ok;
-    RootedObject obj(cx, obj_);
-
     for (ok = true; ps->name; ps++) {
         ok = DefineProperty(cx, obj, ps->name, UndefinedValue(), ps->getter, ps->setter,
                             ps->flags, Shape::HAS_SHORTID, ps->tinyid);
         if (!ok)
             break;
     }
     return ok;
 }
@@ -4017,97 +4047,99 @@ GetPropertyDescriptorById(JSContext *cx,
         desc->getter = NULL;
         desc->setter = NULL;
         desc->value.setUndefined();
     }
     return true;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_GetPropertyDescriptorById(JSContext *cx, JSObject *obj_, jsid id_, unsigned flags,
+JS_GetPropertyDescriptorById(JSContext *cx, JSObject *objArg, jsid idArg, unsigned flags,
                              JSPropertyDescriptor *desc_)
 {
-    RootedId id(cx, id_);
-    RootedObject obj(cx, obj_);
+    RootedObject obj(cx, objArg);
+    RootedId id(cx, idArg);
     AutoPropertyDescriptorRooter desc(cx);
     if (!GetPropertyDescriptorById(cx, obj, id, flags, JS_FALSE, &desc))
         return false;
     *desc_ = desc;
     return true;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_GetPropertyAttrsGetterAndSetterById(JSContext *cx, JSObject *obj_, jsid id_,
+JS_GetPropertyAttrsGetterAndSetterById(JSContext *cx, JSObject *objArg, jsid idArg,
                                        unsigned *attrsp, JSBool *foundp,
                                        JSPropertyOp *getterp, JSStrictPropertyOp *setterp)
 {
-    RootedObject obj(cx, obj_);
-    RootedId id(cx, id_);
+    RootedObject obj(cx, objArg);
+    RootedId id(cx, idArg);
     AutoPropertyDescriptorRooter desc(cx);
     if (!GetPropertyDescriptorById(cx, obj, id, JSRESOLVE_QUALIFIED, JS_FALSE, &desc))
         return false;
 
     *attrsp = desc.attrs;
     *foundp = (desc.obj != NULL);
     if (getterp)
         *getterp = desc.getter;
     if (setterp)
         *setterp = desc.setter;
     return true;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_GetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
+JS_GetPropertyAttributes(JSContext *cx, JSObject *objArg, const char *name,
                          unsigned *attrsp, JSBool *foundp)
 {
+    RootedObject obj(cx, objArg);
     JSAtom *atom = js_Atomize(cx, name, strlen(name));
     return atom && JS_GetPropertyAttrsGetterAndSetterById(cx, obj, AtomToId(atom),
                                                           attrsp, foundp, NULL, NULL);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_GetUCPropertyAttributes(JSContext *cx, JSObject *obj_, const jschar *name, size_t namelen,
+JS_GetUCPropertyAttributes(JSContext *cx, JSObject *objArg, const jschar *name, size_t namelen,
                            unsigned *attrsp, JSBool *foundp)
 {
-    RootedObject obj(cx, obj_);
+    RootedObject obj(cx, objArg);
     JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
     return atom && JS_GetPropertyAttrsGetterAndSetterById(cx, obj, AtomToId(atom),
                                                           attrsp, foundp, NULL, NULL);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_GetPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *obj, const char *name,
+JS_GetPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *objArg, const char *name,
                                    unsigned *attrsp, JSBool *foundp,
                                    JSPropertyOp *getterp, JSStrictPropertyOp *setterp)
 {
+    RootedObject obj(cx, objArg);
     JSAtom *atom = js_Atomize(cx, name, strlen(name));
     return atom && JS_GetPropertyAttrsGetterAndSetterById(cx, obj, AtomToId(atom),
                                                           attrsp, foundp, getterp, setterp);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_GetUCPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *obj_,
+JS_GetUCPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *objArg,
                                      const jschar *name, size_t namelen,
                                      unsigned *attrsp, JSBool *foundp,
                                      JSPropertyOp *getterp, JSStrictPropertyOp *setterp)
 {
-    RootedObject obj(cx, obj_);
+    RootedObject obj(cx, objArg);
     JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
     return atom && JS_GetPropertyAttrsGetterAndSetterById(cx, obj, AtomToId(atom),
                                                           attrsp, foundp, getterp, setterp);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj_, jsid id_, jsval *vp)
-{
-    AssertHeapIsIdle(cx);
-    CHECK_REQUEST(cx);
-
-    Rooted<JSObject*> obj(cx, obj_);
-    Rooted<jsid> id(cx, id_);
+JS_GetOwnPropertyDescriptor(JSContext *cx, JSObject *objArg, jsid idArg, jsval *vp)
+{
+    RootedObject obj(cx, objArg);
+    RootedId id(cx, idArg);
+    AssertHeapIsIdle(cx);
+    CHECK_REQUEST(cx);
+
     return GetOwnPropertyDescriptor(cx, obj, id, vp);
 }
 
 static JSBool
 SetPropertyAttributesById(JSContext *cx, HandleObject obj, HandleId id, unsigned attrs, JSBool *foundp)
 {
     RootedObject obj2(cx);
     RootedShape shape(cx);
@@ -4122,227 +4154,225 @@ SetPropertyAttributesById(JSContext *cx,
                 ? obj->changePropertyAttributes(cx, shape, attrs)
                 : obj->setGenericAttributes(cx, id, &attrs);
     if (ok)
         *foundp = true;
     return ok;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_SetPropertyAttributes(JSContext *cx, JSObject *obj_, const char *name,
+JS_SetPropertyAttributes(JSContext *cx, JSObject *objArg, const char *name,
                          unsigned attrs, JSBool *foundp)
 {
-    RootedObject obj(cx, obj_);
+    RootedObject obj(cx, objArg);
     JSAtom *atom = js_Atomize(cx, name, strlen(name));
-    Rooted<jsid> id(cx, AtomToId(atom));
+    RootedId id(cx, AtomToId(atom));
     return atom && SetPropertyAttributesById(cx, obj, id, attrs, foundp);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_SetUCPropertyAttributes(JSContext *cx, JSObject *obj_, const jschar *name, size_t namelen,
+JS_SetUCPropertyAttributes(JSContext *cx, JSObject *objArg, const jschar *name, size_t namelen,
                            unsigned attrs, JSBool *foundp)
 {
-    RootedObject obj(cx, obj_);
+    RootedObject obj(cx, objArg);
     JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
-    Rooted<jsid> id(cx, AtomToId(atom));
+    RootedId id(cx, AtomToId(atom));
     return atom && SetPropertyAttributesById(cx, obj, id, attrs, foundp);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_GetPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
-{
-    return JS_ForwardGetPropertyTo(cx, obj, id, obj, vp);
-}
-
-JS_PUBLIC_API(JSBool)
-JS_ForwardGetPropertyTo(JSContext *cx, JSObject *obj, jsid id_, JSObject *onBehalfOf_, jsval *vp)
-{
-    RootedId id(cx, id_);
-    RootedObject onBehalfOf(cx, onBehalfOf_);
+JS_GetPropertyById(JSContext *cx, JSObject *objArg, jsid idArg, jsval *vp)
+{
+    return JS_ForwardGetPropertyTo(cx, objArg, idArg, objArg, vp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ForwardGetPropertyTo(JSContext *cx, JSObject *objArg, jsid idArg, JSObject *onBehalfOfArg, jsval *vp)
+{
+    RootedObject obj(cx, objArg);
+    RootedObject onBehalfOf(cx, onBehalfOfArg);
+    RootedId id(cx, idArg);
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, id);
     assertSameCompartment(cx, onBehalfOf);
     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
 
     RootedValue value(cx);
     if (!obj->getGeneric(cx, onBehalfOf, id, &value))
         return false;
 
     *vp = value;
     return true;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_GetPropertyByIdDefault(JSContext *cx, JSObject *obj_, jsid id_, jsval def_, jsval *vp)
-{
-    Rooted<JSObject*> obj(cx, obj_);
-    Rooted<jsid> id(cx, id_);
-    RootedValue def(cx, def_);
+JS_GetPropertyByIdDefault(JSContext *cx, JSObject *objArg, jsid idArg, jsval defArg, jsval *vp)
+{
+    RootedObject obj(cx, objArg);
+    RootedId id(cx, idArg);
+    RootedValue def(cx, defArg);
 
     RootedValue value(cx);
     if (!baseops::GetPropertyDefault(cx, obj, id, def, &value))
         return false;
 
     *vp = value;
     return true;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_GetElement(JSContext *cx, JSObject *obj, uint32_t index, jsval *vp)
-{
-    return JS_ForwardGetElementTo(cx, obj, index, obj, vp);
-}
-
-JS_PUBLIC_API(JSBool)
-JS_ForwardGetElementTo(JSContext *cx, JSObject *obj, uint32_t index, JSObject *onBehalfOf_, jsval *vp)
-{
-    RootedObject onBehalfOf(cx, onBehalfOf_);
-
+JS_GetElement(JSContext *cx, JSObject *objArg, uint32_t index, jsval *vp)
+{
+    return JS_ForwardGetElementTo(cx, objArg, index, objArg, vp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ForwardGetElementTo(JSContext *cx, JSObject *objArg, uint32_t index, JSObject *onBehalfOfArg, jsval *vp)
+{
+    RootedObject obj(cx, objArg);
+    RootedObject onBehalfOf(cx, onBehalfOfArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
 
     RootedValue value(cx);
     if (!obj->getElement(cx, onBehalfOf, index, &value))
         return false;
 
     *vp = value;
     return true;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_GetElementIfPresent(JSContext *cx, JSObject *obj, uint32_t index, JSObject *onBehalfOf_, jsval *vp, JSBool* present)
-{
-    RootedObject onBehalfOf(cx, onBehalfOf_);
-
+JS_GetElementIfPresent(JSContext *cx, JSObject *objArg, uint32_t index, JSObject *onBehalfOfArg, jsval *vp, JSBool* present)
+{
+    RootedObject obj(cx, objArg);
+    RootedObject onBehalfOf(cx, onBehalfOfArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
 
     RootedValue value(cx);
     bool isPresent;
     if (!obj->getElementIfPresent(cx, onBehalfOf, index, &value, &isPresent))
         return false;
 
     *vp = value;
     *present = isPresent;
     return true;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_GetProperty(JSContext *cx, JSObject *obj_, const char *name, jsval *vp)
-{
-    RootedObject obj(cx, obj_);
+JS_GetProperty(JSContext *cx, JSObject *objArg, const char *name, jsval *vp)
+{
+    RootedObject obj(cx, objArg);
     JSAtom *atom = js_Atomize(cx, name, strlen(name));
     return atom && JS_GetPropertyById(cx, obj, AtomToId(atom), vp);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_GetPropertyDefault(JSContext *cx, JSObject *obj_, const char *name, jsval def, jsval *vp)
-{
-    RootedObject obj(cx, obj_);
+JS_GetPropertyDefault(JSContext *cx, JSObject *objArg, const char *name, jsval def, jsval *vp)
+{
+    RootedObject obj(cx, objArg);
     JSAtom *atom = js_Atomize(cx, name, strlen(name));
     return atom && JS_GetPropertyByIdDefault(cx, obj, AtomToId(atom), def, vp);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_GetUCProperty(JSContext *cx, JSObject *obj_, const jschar *name, size_t namelen, jsval *vp)
-{
-    RootedObject obj(cx, obj_);
+JS_GetUCProperty(JSContext *cx, JSObject *objArg, const jschar *name, size_t namelen, jsval *vp)
+{
+    RootedObject obj(cx, objArg);
     JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
     return atom && JS_GetPropertyById(cx, obj, AtomToId(atom), vp);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_GetMethodById(JSContext *cx, JSObject *obj_, jsid id_, JSObject **objp, jsval *vp)
-{
-    RootedObject obj(cx, obj_);
-    RootedId id(cx, id_);
+JS_GetMethodById(JSContext *cx, JSObject *objArg, jsid idArg, JSObject **objp, jsval *vp)
+{
+    RootedObject obj(cx, objArg);
+    RootedId id(cx, idArg);
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, id);
 
     RootedValue value(cx);
     if (!GetMethod(cx, obj, id, 0, &value))
         return JS_FALSE;
     *vp = value;
 
     if (objp)
         *objp = obj;
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_GetMethod(JSContext *cx, JSObject *obj, const char *name, JSObject **objp, jsval *vp)
+JS_GetMethod(JSContext *cx, JSObject *objArg, const char *name, JSObject **objp, jsval *vp)
 {
     JSAtom *atom = js_Atomize(cx, name, strlen(name));
-    return atom && JS_GetMethodById(cx, obj, AtomToId(atom), objp, vp);
-}
-
-JS_PUBLIC_API(JSBool)
-JS_SetPropertyById(JSContext *cx, JSObject *objArg, jsid id_, jsval *vp)
-{
-    RootedId id(cx, id_);
-    Rooted<JSObject*> obj(cx, objArg);
-
+    return atom && JS_GetMethodById(cx, objArg, AtomToId(atom), objp, vp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetPropertyById(JSContext *cx, JSObject *objArg, jsid idArg, jsval *vp)
+{
+    RootedObject obj(cx, objArg);
+    RootedId id(cx, idArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, id);
     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING);
 
     RootedValue value(cx, *vp);
     if (!obj->setGeneric(cx, obj, id, &value, false))
         return false;
 
     *vp = value;
     return true;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_SetElement(JSContext *cx, JSObject *obj_, uint32_t index, jsval *vp)
-{
-    RootedObject obj(cx, obj_);
-
+JS_SetElement(JSContext *cx, JSObject *objArg, uint32_t index, jsval *vp)
+{
+    RootedObject obj(cx, objArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, *vp);
     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING);
 
     RootedValue value(cx, *vp);
     if (!obj->setElement(cx, obj, index, &value, false))
         return false;
 
     *vp = value;
     return true;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_SetProperty(JSContext *cx, JSObject *obj_, const char *name, jsval *vp)
-{
-    RootedObject obj(cx, obj_);
+JS_SetProperty(JSContext *cx, JSObject *objArg, const char *name, jsval *vp)
+{
     JSAtom *atom = js_Atomize(cx, name, strlen(name));
-    return atom && JS_SetPropertyById(cx, obj, AtomToId(atom), vp);
-}
-
-JS_PUBLIC_API(JSBool)
-JS_SetUCProperty(JSContext *cx, JSObject *obj_, const jschar *name, size_t namelen, jsval *vp)
-{
-    RootedObject obj(cx, obj_);
+    return atom && JS_SetPropertyById(cx, objArg, AtomToId(atom), vp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetUCProperty(JSContext *cx, JSObject *objArg, const jschar *name, size_t namelen, jsval *vp)
+{
     JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
-    return atom && JS_SetPropertyById(cx, obj, AtomToId(atom), vp);
-}
-
-JS_PUBLIC_API(JSBool)
-JS_DeletePropertyById2(JSContext *cx, JSObject *obj, jsid id, jsval *rval)
-{
+    return atom && JS_SetPropertyById(cx, objArg, AtomToId(atom), vp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DeletePropertyById2(JSContext *cx, JSObject *objArg, jsid id, jsval *rval)
+{
+    RootedObject obj(cx, objArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, id);
     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
 
     RootedValue value(cx);
 
     if (JSID_IS_SPECIAL(id)) {
@@ -4354,36 +4384,36 @@ JS_DeletePropertyById2(JSContext *cx, JS
             return false;
     }
 
     *rval = value;
     return true;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_DeleteElement2(JSContext *cx, JSObject *obj, uint32_t index, jsval *rval)
-{
+JS_DeleteElement2(JSContext *cx, JSObject *objArg, uint32_t index, jsval *rval)
+{
+    RootedObject obj(cx, objArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
 
     RootedValue value(cx);
     if (!obj->deleteElement(cx, index, &value, false))
         return false;
 
     *rval = value;
     return true;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_DeleteProperty2(JSContext *cx, JSObject *obj_, const char *name, jsval *rval)
-{
-    RootedObject obj(cx, obj_);
-
+JS_DeleteProperty2(JSContext *cx, JSObject *objArg, const char *name, jsval *rval)
+{
+    RootedObject obj(cx, objArg);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
 
     JSAtom *atom = js_Atomize(cx, name, strlen(name));
     if (!atom)
         return false;
 
@@ -4391,20 +4421,19 @@ JS_DeleteProperty2(JSContext *cx, JSObje
     if (!obj->deleteByValue(cx, StringValue(atom), &value, false))
         return false;
 
     *rval = value;
     return true;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_DeleteUCProperty2(JSContext *cx, JSObject *obj_, const jschar *name, size_t namelen, jsval *rval)
-{
-    RootedObject obj(cx, obj_);
-
+JS_DeleteUCProperty2(JSContext *cx, JSObject *objArg, const jschar *name, size_t namelen, jsval *rval)
+{
+    RootedObject obj(cx, objArg);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
 
     JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
     if (!atom)
         return false;
 
@@ -4412,41 +4441,40 @@ JS_DeleteUCProperty2(JSContext *cx, JSOb
     if (!obj->deleteByValue(cx, StringValue(atom), &value, false))
         return false;
 
     *rval = value;
     return true;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_DeletePropertyById(JSContext *cx, JSObject *obj, jsid id)
+JS_DeletePropertyById(JSContext *cx, JSObject *objArg, jsid idArg)
 {
     jsval junk;
-    return JS_DeletePropertyById2(cx, obj, id, &junk);
-}
-
-JS_PUBLIC_API(JSBool)
-JS_DeleteElement(JSContext *cx, JSObject *obj, uint32_t index)
+    return JS_DeletePropertyById2(cx, objArg, idArg, &junk);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DeleteElement(JSContext *cx, JSObject *objArg, uint32_t index)
 {
     jsval junk;
-    return JS_DeleteElement2(cx, obj, index, &junk);
-}
-
-JS_PUBLIC_API(JSBool)
-JS_DeleteProperty(JSContext *cx, JSObject *obj, const char *name)
+    return JS_DeleteElement2(cx, objArg, index, &junk);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DeleteProperty(JSContext *cx, JSObject *objArg, const char *name)
 {
     jsval junk;
-    return JS_DeleteProperty2(cx, obj, name, &junk);
+    return JS_DeleteProperty2(cx, objArg, name, &junk);
 }
 
 JS_PUBLIC_API(void)
-JS_ClearScope(JSContext *cx, JSObject *obj_)
-{
-    RootedObject obj(cx, obj_);
-
+JS_ClearScope(JSContext *cx, JSObject *objArg)
+{
+    RootedObject obj(cx, objArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
 
     ClearOp clearOp = obj->getOps()->clear;
     if (clearOp)
         clearOp(cx, obj);
 
@@ -4456,18 +4484,19 @@ JS_ClearScope(JSContext *cx, JSObject *o
     /* Clear cached class objects on the global object. */
     if (obj->isGlobal())
         obj->asGlobal().clear(cx);
 
     js_InitRandom(cx);
 }
 
 JS_PUBLIC_API(JSIdArray *)
-JS_Enumerate(JSContext *cx, JSObject *obj)
-{
+JS_Enumerate(JSContext *cx, JSObject *objArg)
+{
+    RootedObject obj(cx, objArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
 
     AutoIdVector props(cx);
     JSIdArray *ida;
     if (!GetPropertyNames(cx, obj, JSITER_OWNONLY, &props) || !VectorToIdArray(cx, props, &ida))
         return NULL;
@@ -4534,19 +4563,19 @@ static Class prop_iter_class = {
     NULL,           /* checkAccess */
     NULL,           /* call        */
     NULL,           /* construct   */
     NULL,           /* hasInstance */
     prop_iter_trace
 };
 
 JS_PUBLIC_API(JSObject *)
-JS_NewPropertyIterator(JSContext *cx, JSObject *obj_)
-{
-    RootedObject obj(cx, obj_);
+JS_NewPropertyIterator(JSContext *cx, JSObject *objArg)
+{
+    RootedObject obj(cx, objArg);
     JSObject *iterobj;
     void *pdata;
     int index;
     JSIdArray *ida;
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
@@ -4575,18 +4604,19 @@ JS_NewPropertyIterator(JSContext *cx, JS
 
     /* iterobj cannot escape to other threads here. */
     iterobj->setPrivate(pdata);
     iterobj->setSlot(JSSLOT_ITER_INDEX, Int32Value(index));
     return iterobj;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp)
-{
+JS_NextProperty(JSContext *cx, JSObject *iterobjArg, jsid *idp)
+{
+    RootedObject iterobj(cx, iterobjArg);
     AssertRootingUnnecessary safe(cx);
     int32_t i;
     Shape *shape;
     JSIdArray *ida;
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, iterobj);
@@ -4621,77 +4651,84 @@ JS_NextProperty(JSContext *cx, JSObject 
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_ArrayIterator(JSContext *cx, unsigned argc, jsval *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     Rooted<Value> target(cx, args.thisv());
+    AssertHeapIsIdle(cx);
+    assertSameCompartment(cx, target);
+    CHECK_REQUEST(cx);
+
     JSObject *iterobj = ElementIteratorObject::create(cx, target);
     if (!iterobj)
         return false;
     vp->setObject(*iterobj);
     return true;
 }
 
 JS_PUBLIC_API(jsval)
-JS_GetReservedSlot(JSObject *obj, uint32_t index)
+JS_GetReservedSlot(RawObject obj, uint32_t index)
 {
     return obj->getReservedSlot(index);
 }
 
 JS_PUBLIC_API(void)
-JS_SetReservedSlot(JSObject *obj, uint32_t index, jsval v)
+JS_SetReservedSlot(RawObject obj, uint32_t index, jsval v)
 {
     obj->setReservedSlot(index, v);
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_NewArrayObject(JSContext *cx, int length, jsval *vector)
 {
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
 
     assertSameCompartment(cx, JSValueArray(vector, vector ? (uint32_t)length : 0));
     return NewDenseCopiedArray(cx, (uint32_t)length, vector);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_IsArrayObject(JSContext *cx, JSObject *obj)
-{
+JS_IsArrayObject(JSContext *cx, JSObject *objArg)
+{
+    RootedObject obj(cx, objArg);
     assertSameCompartment(cx, obj);
     return ObjectClassIs(*obj, ESClass_Array, cx);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_GetArrayLength(JSContext *cx, JSObject *obj, uint32_t *lengthp)
-{
+JS_GetArrayLength(JSContext *cx, JSObject *objArg, uint32_t *lengthp)
+{
+    RootedObject obj(cx, objArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     return js_GetLengthProperty(cx, obj, lengthp);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_SetArrayLength(JSContext *cx, JSObject *objArg, uint32_t length)
 {
-    AssertHeapIsIdle(cx);
-    CHECK_REQUEST(cx);
-    assertSameCompartment(cx, objArg);
     RootedObject obj(cx, objArg);
+    AssertHeapIsIdle(cx);
+    CHECK_REQUEST(cx);
+    assertSameCompartment(cx, obj);
     return js_SetLengthProperty(cx, obj, length);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_CheckAccess(JSContext *cx, JSObject *obj, jsid id_, JSAccessMode mode,
+JS_CheckAccess(JSContext *cx, JSObject *objArg, jsid idArg, JSAccessMode mode,
                jsval *vp, unsigned *attrsp)
 {
-    RootedId id(cx, id_);
+    RootedObject obj(cx, objArg);
+    RootedId id(cx, idArg);
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, id);
     return CheckAccess(cx, obj, id, mode, vp, attrsp);
 }
 
 JS_PUBLIC_API(void)
@@ -4732,61 +4769,59 @@ JS_InitDestroyPrincipalsCallback(JSRunti
 {
     JS_ASSERT(destroyPrincipals);
     JS_ASSERT(!rt->destroyPrincipals);
     rt->destroyPrincipals = destroyPrincipals;
 }
 
 JS_PUBLIC_API(JSFunction *)
 JS_NewFunction(JSContext *cx, JSNative native, unsigned nargs, unsigned flags,
-               JSObject *parent_, const char *name)
-{
+               JSObject *parentArg, const char *name)
+{
+    RootedObject parent(cx, parentArg);
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     JSAtom *atom;
 
-    RootedObject parent(cx, parent_);
-
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, parent);
 
     if (!name) {
         atom = NULL;
     } else {
         atom = js_Atomize(cx, name, strlen(name));
         if (!atom)
             return NULL;
     }
 
     return js_NewFunction(cx, NULL, native, nargs, flags, parent, atom);
 }
 
 JS_PUBLIC_API(JSFunction *)
-JS_NewFunctionById(JSContext *cx, JSNative native, unsigned nargs, unsigned flags, JSObject *parent_,
+JS_NewFunctionById(JSContext *cx, JSNative native, unsigned nargs, unsigned flags, JSObject *parentArg,
                    jsid id)
 {
-    RootedObject parent(cx, parent_);
-
+    RootedObject parent(cx, parentArg);
     JS_ASSERT(JSID_IS_STRING(id));
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, parent);
 
     return js_NewFunction(cx, NULL, native, nargs, flags, parent, JSID_TO_ATOM(id));
 }
 
 JS_PUBLIC_API(JSObject *)
-JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent_)
-{
-    AssertHeapIsIdle(cx);
-    CHECK_REQUEST(cx);
-    assertSameCompartment(cx, parent_);  // XXX no funobj for now
-
-    RootedObject parent(cx, parent_);
+JS_CloneFunctionObject(JSContext *cx, JSObject *funobjArg, JSRawObject parentArg)
+{
+    RootedObject funobj(cx, funobjArg);
+    RootedObject parent(cx, parentArg);
+    AssertHeapIsIdle(cx);
+    CHECK_REQUEST(cx);
+    assertSameCompartment(cx, parent);  // XXX no funobj for now
 
     if (!parent) {
         if (cx->hasfp())
             parent = cx->fp()->scopeChain();
         if (!parent)
             parent = cx->globalObject;
         JS_ASSERT(parent);
     }
@@ -4839,40 +4874,40 @@ JS_GetFunctionFlags(JSFunction *fun)
 
 JS_PUBLIC_API(uint16_t)
 JS_GetFunctionArity(JSFunction *fun)
 {
     return fun->nargs;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_ObjectIsFunction(JSContext *cx, JSObject *obj)
+JS_ObjectIsFunction(JSContext *cx, RawObject obj)
 {
     return obj->isFunction();
 }
 
 JS_PUBLIC_API(JSBool)
-JS_ObjectIsCallable(JSContext *cx, JSObject *obj)
+JS_ObjectIsCallable(JSContext *cx, RawObject obj)
 {
     return obj->isCallable();
 }
 
 JS_PUBLIC_API(JSBool)
-JS_IsNativeFunction(JSObject *funobj, JSNative call)
+JS_IsNativeFunction(JSRawObject funobj, JSNative call)
 {
     if (!funobj->isFunction())
         return false;
     JSFunction *fun = funobj->toFunction();
     return fun->isNative() && fun->native() == call;
 }
 
 JS_PUBLIC_API(JSObject*)
-JS_BindCallable(JSContext *cx, JSObject *callable, JSObject *newThis)
-{
-    RootedObject target(cx, callable);
+JS_BindCallable(JSContext *cx, JSObject *targetArg, JSRawObject newThis)
+{
+    RootedObject target(cx, targetArg);
     RootedValue thisArg(cx, ObjectValue(*newThis));
     return js_fun_bind(cx, target, thisArg, NULL, 0);
 }
 
 JSBool
 js_generic_native_method_dispatcher(JSContext *cx, unsigned argc, Value *vp)
 {
     JSFunctionSpec *fs = (JSFunctionSpec *)
@@ -4894,20 +4929,19 @@ js_generic_native_method_dispatcher(JSCo
 
     /* Clear the last parameter in case too few arguments were passed. */
     vp[2 + --argc].setUndefined();
 
     return fs->call(cx, argc, vp);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_DefineFunctions(JSContext *cx, JSObject *obj_, JSFunctionSpec *fs)
-{
-    RootedObject obj(cx, obj_);
-
+JS_DefineFunctions(JSContext *cx, JSObject *objArg, JSFunctionSpec *fs)
+{
+    RootedObject obj(cx, objArg);
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     unsigned flags;
     RootedObject ctor(cx);
     JSFunction *fun;
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
@@ -4947,55 +4981,53 @@ JS_DefineFunctions(JSContext *cx, JSObje
         fun = js_DefineFunction(cx, obj, id, fs->call, fs->nargs, flags);
         if (!fun)
             return JS_FALSE;
     }
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSFunction *)
-JS_DefineFunction(JSContext *cx, JSObject *obj_, const char *name, JSNative call,
+JS_DefineFunction(JSContext *cx, JSObject *objArg, const char *name, JSNative call,
                   unsigned nargs, unsigned attrs)
 {
-    RootedObject obj(cx, obj_);
-
+    RootedObject obj(cx, objArg);
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     JSAtom *atom = js_Atomize(cx, name, strlen(name));
     if (!atom)
         return NULL;
     Rooted<jsid> id(cx, AtomToId(atom));
     return js_DefineFunction(cx, obj, id, call, nargs, attrs);
 }
 
 JS_PUBLIC_API(JSFunction *)
-JS_DefineUCFunction(JSContext *cx, JSObject *obj_,
+JS_DefineUCFunction(JSContext *cx, JSObject *objArg,
                     const jschar *name, size_t namelen, JSNative call,
                     unsigned nargs, unsigned attrs)
 {
-    RootedObject obj(cx, obj_);
-
+    RootedObject obj(cx, objArg);
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
     if (!atom)
         return NULL;
     Rooted<jsid> id(cx, AtomToId(atom));
     return js_DefineFunction(cx, obj, id, call, nargs, attrs);
 }
 
 extern JS_PUBLIC_API(JSFunction *)
-JS_DefineFunctionById(JSContext *cx, JSObject *obj_, jsid id_, JSNative call,
+JS_DefineFunctionById(JSContext *cx, JSObject *objArg, jsid id_, JSNative call,
                       unsigned nargs, unsigned attrs)
 {
-    RootedObject obj(cx, obj_);
+    RootedObject obj(cx, objArg);
     RootedId id(cx, id_);
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     return js_DefineFunction(cx, obj, id, call, nargs, attrs);
 }
 
@@ -5169,127 +5201,118 @@ JS::Compile(JSContext *cx, HandleObject 
     if (!file.open(cx, filename))
         return NULL;
     options = options.setFileAndLine(filename, 1);
     JSScript *script = Compile(cx, obj, options, file.fp());
     return script;
 }
 
 extern JS_PUBLIC_API(JSScript *)
-JS_CompileUCScriptForPrincipalsVersion(JSContext *cx, JSObject *obj_,
+JS_CompileUCScriptForPrincipalsVersion(JSContext *cx, JSObject *objArg,
                                        JSPrincipals *principals,
                                        const jschar *chars, size_t length,
                                        const char *filename, unsigned lineno,
                                        JSVersion version)
 {
-    RootedObject obj(cx, obj_);
-
+    RootedObject obj(cx, objArg);
     CompileOptions options(cx);
     options.setPrincipals(principals)
            .setFileAndLine(filename, lineno)
            .setVersion(version);
 
     return Compile(cx, obj, options, chars, length);
 }
 
 extern JS_PUBLIC_API(JSScript *)
-JS_CompileUCScriptForPrincipalsVersionOrigin(JSContext *cx, JSObject *obj_,
+JS_CompileUCScriptForPrincipalsVersionOrigin(JSContext *cx, JSObject *objArg,
                                              JSPrincipals *principals,
                                              JSPrincipals *originPrincipals,
                                              const jschar *chars, size_t length,
                                              const char *filename, unsigned lineno,
                                              JSVersion version)
 {
-    RootedObject obj(cx, obj_);
-
+    RootedObject obj(cx, objArg);
     CompileOptions options(cx);
     options.setPrincipals(principals)
            .setOriginPrincipals(originPrincipals)
            .setFileAndLine(filename, lineno)
            .setVersion(version);
 
     return Compile(cx, obj, options, chars, length);
 }
 
 JS_PUBLIC_API(JSScript *)
-JS_CompileUCScriptForPrincipals(JSContext *cx, JSObject *obj_, JSPrincipals *principals,
+JS_CompileUCScriptForPrincipals(JSContext *cx, JSObject *objArg, JSPrincipals *principals,
                                 const jschar *chars, size_t length,
                                 const char *filename, unsigned lineno)
 {
-    RootedObject obj(cx, obj_);
-
+    RootedObject obj(cx, objArg);
     CompileOptions options(cx);
     options.setPrincipals(principals)
            .setFileAndLine(filename, lineno);
 
     return Compile(cx, obj, options, chars, length);
 }
 
 JS_PUBLIC_API(JSScript *)
-JS_CompileUCScript(JSContext *cx, JSObject *obj_, const jschar *chars, size_t length,
+JS_CompileUCScript(JSContext *cx, JSObject *objArg, const jschar *chars, size_t length,
                    const char *filename, unsigned lineno)
 {
-    RootedObject obj(cx, obj_);
-
+    RootedObject obj(cx, objArg);
     CompileOptions options(cx);
     options.setFileAndLine(filename, lineno);
 
     return Compile(cx, obj, options, chars, length);
 }
 
 JS_PUBLIC_API(JSScript *)
-JS_CompileScriptForPrincipalsVersion(JSContext *cx, JSObject *obj_,
+JS_CompileScriptForPrincipalsVersion(JSContext *cx, JSObject *objArg,
                                      JSPrincipals *principals,
                                      const char *bytes, size_t length,
                                      const char *filename, unsigned lineno,
                                      JSVersion version)
 {
-    RootedObject obj(cx, obj_);
-
+    RootedObject obj(cx, objArg);
     CompileOptions options(cx);
     options.setPrincipals(principals)
            .setFileAndLine(filename, lineno)
            .setVersion(version);
 
     return Compile(cx, obj, options, bytes, length);
 }
 
 JS_PUBLIC_API(JSScript *)
-JS_CompileScriptForPrincipals(JSContext *cx, JSObject *obj_,
+JS_CompileScriptForPrincipals(JSContext *cx, JSObject *objArg,
                               JSPrincipals *principals,
                               const char *bytes, size_t length,
                               const char *filename, unsigned lineno)
 {
-    RootedObject obj(cx, obj_);
-
+    RootedObject obj(cx, objArg);
     CompileOptions options(cx);
     options.setPrincipals(principals)
            .setFileAndLine(filename, lineno);
 
     return Compile(cx, obj, options, bytes, length);
 }
 
 JS_PUBLIC_API(JSScript *)
-JS_CompileScript(JSContext *cx, JSObject *obj_, const char *bytes, size_t length,
+JS_CompileScript(JSContext *cx, JSObject *objArg, const char *bytes, size_t length,
                  const char *filename, unsigned lineno)
 {
-    RootedObject obj(cx, obj_);
-
+    RootedObject obj(cx, objArg);
     CompileOptions options(cx);
     options.setFileAndLine(filename, lineno);
 
     return Compile(cx, obj, options, bytes, length);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_BufferIsCompilableUnit(JSContext *cx, JSBool bytes_are_utf8, JSObject *obj_,
-                          const char *bytes, size_t length)
-{
-    RootedObject obj(cx, obj_);
-
+JS_BufferIsCompilableUnit(JSContext *cx, JSBool bytes_are_utf8, JSObject *objArg, const char *bytes, size_t length)
+{
+    RootedObject obj(cx, objArg);
     jschar *chars;
     JSBool result;
     JSExceptionState *exnState;
     JSErrorReporter older;
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
@@ -5325,61 +5348,57 @@ JS_BufferIsCompilableUnit(JSContext *cx,
         }
     }
     cx->free_(chars);
     JS_RestoreExceptionState(cx, exnState);
     return result;
 }
 
 JS_PUBLIC_API(JSScript *)
-JS_CompileUTF8File(JSContext *cx, JSObject *obj_, const char *filename)
-{
-    RootedObject obj(cx, obj_);
-
+JS_CompileUTF8File(JSContext *cx, JSObject *objArg, const char *filename)
+{
+    RootedObject obj(cx, objArg);
     CompileOptions options(cx);
     options.setUTF8(true)
            .setFileAndLine(filename, 1);
 
     return Compile(cx, obj, options, filename);
 }
 
 JS_PUBLIC_API(JSScript *)
-JS_CompileUTF8FileHandleForPrincipals(JSContext *cx, JSObject *obj_, const char *filename,
+JS_CompileUTF8FileHandleForPrincipals(JSContext *cx, JSObject *objArg, const char *filename,
                                       FILE *file, JSPrincipals *principals)
 {
-    RootedObject obj(cx, obj_);
-
+    RootedObject obj(cx, objArg);
     CompileOptions options(cx);
     options.setUTF8(true)
            .setFileAndLine(filename, 1)
            .setPrincipals(principals);
 
     return Compile(cx, obj, options, file);
 }
 
 JS_PUBLIC_API(JSScript *)
-JS_CompileUTF8FileHandleForPrincipalsVersion(JSContext *cx, JSObject *obj_, const char *filename,
+JS_CompileUTF8FileHandleForPrincipalsVersion(JSContext *cx, JSObject *objArg, const char *filename,
                                              FILE *file, JSPrincipals *principals, JSVersion version)
 {
-    RootedObject obj(cx, obj_);
-
+    RootedObject obj(cx, objArg);
     CompileOptions options(cx);
     options.setUTF8(true)
            .setFileAndLine(filename, 1)
            .setPrincipals(principals)
            .setVersion(version);
 
     return Compile(cx, obj, options, file);
 }
 
 JS_PUBLIC_API(JSScript *)
-JS_CompileUTF8FileHandle(JSContext *cx, JSObject *obj_, const char *filename, FILE *file)
-{
-    RootedObject obj(cx, obj_);
-
+JS_CompileUTF8FileHandle(JSContext *cx, JSObject *objArg, const char *filename, FILE *file)
+{
+    RootedObject obj(cx, objArg);
     CompileOptions options(cx);
     options.setUTF8(true)
            .setFileAndLine(filename, 1);
 
     return Compile(cx, obj, options, file);
 }
 
 JS_PUBLIC_API(JSObject *)
@@ -5471,69 +5490,65 @@ JS_CompileUCFunctionForPrincipalsVersion
     options.setPrincipals(principals)
            .setFileAndLine(filename, lineno)
            .setVersion(version);
 
     return CompileFunction(cx, obj, options, name, nargs, argnames, chars, length);
 }
 
 JS_PUBLIC_API(JSFunction *)
-JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj_,
+JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *objArg,
                                   JSPrincipals *principals, const char *name,
                                   unsigned nargs, const char **argnames,
                                   const jschar *chars, size_t length,
                                   const char *filename, unsigned lineno)
 {
-    RootedObject obj(cx, obj_);
-
+    RootedObject obj(cx, objArg);
     CompileOptions options(cx);
     options.setPrincipals(principals)
            .setFileAndLine(filename, lineno);
 
     return CompileFunction(cx, obj, options, name, nargs, argnames, chars, length);
 }
 
 JS_PUBLIC_API(JSFunction *)
-JS_CompileUCFunction(JSContext *cx, JSObject *obj_, const char *name,
+JS_CompileUCFunction(JSContext *cx, JSObject *objArg, const char *name,
                      unsigned nargs, const char **argnames,
                      const jschar *chars, size_t length,
                      const char *filename, unsigned lineno)
 {
-    RootedObject obj(cx, obj_);
-
+    RootedObject obj(cx, objArg);
     CompileOptions options(cx);
     options.setFileAndLine(filename, lineno);
 
     return CompileFunction(cx, obj, options, name, nargs, argnames, chars, length);
 }
 
 JS_PUBLIC_API(JSFunction *)
-JS_CompileFunctionForPrincipals(JSContext *cx, JSObject *obj_,
+JS_CompileFunctionForPrincipals(JSContext *cx, JSObject *objArg,
                                 JSPrincipals *principals, const char *name,
                                 unsigned nargs, const char **argnames,
                                 const char *bytes, size_t length,
                                 const char *filename, unsigned lineno)
 {
-    RootedObject obj(cx, obj_);
-
+    RootedObject obj(cx, objArg);
     CompileOptions options(cx);
     options.setPrincipals(principals)
            .setFileAndLine(filename, lineno);
 
     return CompileFunction(cx, obj, options, name, nargs, argnames, bytes, length);
 }
 
 JS_PUBLIC_API(JSFunction *)
-JS_CompileFunction(JSContext *cx, JSObject *obj_, const char *name,
+JS_CompileFunction(JSContext *cx, JSObject *objArg, const char *name,
                    unsigned nargs, const char **argnames,
                    const char *bytes, size_t length,
                    const char *filename, unsigned lineno)
 {
-    RootedObject obj(cx, obj_);
-
+    RootedObject obj(cx, objArg);
     CompileOptions options(cx);
     options.setFileAndLine(filename, lineno);
 
     return CompileFunction(cx, obj, options, name, nargs, argnames, bytes, length);
 }
 
 JS_PUBLIC_API(JSString *)
 JS_DecompileScript(JSContext *cx, JSScript *script, const char *name, unsigned indent)
@@ -5566,53 +5581,53 @@ JS_DecompileFunctionBody(JSContext *cx, 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, funArg);
     RootedFunction fun(cx, funArg);
     return FunctionToString(cx, fun, true, !(indent & JS_DONT_PRETTY_PRINT));
 }
 
 JS_NEVER_INLINE JS_PUBLIC_API(JSBool)
-JS_ExecuteScript(JSContext *cx, JSObject *obj, JSScript *scriptArg_, jsval *rval)
-{
-    RootedScript scriptArg(cx, scriptArg_);
+JS_ExecuteScript(JSContext *cx, JSObject *objArg, JSScript *scriptArg, jsval *rval)
+{
+    RootedObject obj(cx, objArg);
+    RootedScript script(cx, scriptArg);
 
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     if (cx->compartment != obj->compartment())
         *(volatile int *) 0 = 0xf0;
     AutoLastFrameCheck lfc(cx);
 
-    JS::Anchor<JSScript *> script(NULL);
-
     /*
      * Mozilla caches pre-compiled scripts (e.g., in the XUL prototype cache)
      * and runs them against multiple globals. With a compartment per global,
      * this requires cloning the pre-compiled script into each new global.
      * Since each script gets run once, there is no point in trying to cache
      * this clone. Ideally, this would be handled at some pinch point in
      * mozilla, but there doesn't seem to be one, so we handle it here.
      */
-    if (scriptArg->compartment() != obj->compartment()) {
-        script = CloneScript(cx, NullPtr(), NullPtr(), scriptArg);
+    if (script->compartment() != obj->compartment()) {
+        script = CloneScript(cx, NullPtr(), NullPtr(), script);
         if (!script.get())
             return false;
     } else {
         script = scriptArg;
     }
 
-    return Execute(cx, script.get(), *obj, rval);
-}
-
-JS_PUBLIC_API(JSBool)
-JS_ExecuteScriptVersion(JSContext *cx, JSObject *obj, JSScript *script, jsval *rval,
+    return Execute(cx, script, *obj, rval);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ExecuteScriptVersion(JSContext *cx, JSObject *objArg, JSScript *script, jsval *rval,
                         JSVersion version)
 {
+    RootedObject obj(cx, objArg);
     AutoVersionAPI ava(cx, version);
     return JS_ExecuteScript(cx, obj, script, rval);
 }
 
 extern JS_PUBLIC_API(bool)
 JS::Evaluate(JSContext *cx, HandleObject obj, CompileOptions options,
              const jschar *chars, size_t length, jsval *rval)
 {
@@ -5626,17 +5641,17 @@ JS::Evaluate(JSContext *cx, HandleObject
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, options.principals, options.originPrincipals);
     AutoLastFrameCheck lfc(cx);
 
     options.setCompileAndGo(true);
     options.setNoScriptRval(!rval);
-    JSScript *script = frontend::CompileScript(cx, obj, NULL, options, chars, length);
+    RootedScript script(cx, frontend::CompileScript(cx, obj, NULL, options, chars, length));
     if (!script)
         return false;
 
     JS_ASSERT(script->getVersion() == options.version);
 
     return Execute(cx, script, *obj, rval);
 }
 
@@ -5668,161 +5683,155 @@ JS::Evaluate(JSContext *cx, HandleObject
             return NULL;
     }
 
     options = options.setFileAndLine(filename, 1);
     return Evaluate(cx, obj, options, buffer.begin(), buffer.length(), rval);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_EvaluateUCScriptForPrincipals(JSContext *cx, JSObject *obj_,
+JS_EvaluateUCScriptForPrincipals(JSContext *cx, JSObject *objArg,
                                  JSPrincipals *principals,
                                  const jschar *chars, unsigned length,
                                  const char *filename, unsigned lineno,
                                  jsval *rval)
 {
-    RootedObject obj(cx, obj_);
-
+    RootedObject obj(cx, objArg);
     CompileOptions options(cx);
     options.setPrincipals(principals)
            .setFileAndLine(filename, lineno);
 
     return Evaluate(cx, obj, options, chars, length, rval);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_EvaluateUCScriptForPrincipalsVersion(JSContext *cx, JSObject *obj_,
+JS_EvaluateUCScriptForPrincipalsVersion(JSContext *cx, JSObject *objArg,
                                         JSPrincipals *principals,
                                         const jschar *chars, unsigned length,
                                         const char *filename, unsigned lineno,
                                         jsval *rval, JSVersion version)
 {
-    RootedObject obj(cx, obj_);
-
+    RootedObject obj(cx, objArg);
     CompileOptions options(cx);
     options.setPrincipals(principals)
            .setFileAndLine(filename, lineno)
            .setVersion(version);
 
     return Evaluate(cx, obj, options, chars, length, rval);
 }
 
 extern JS_PUBLIC_API(JSBool)
-JS_EvaluateUCScriptForPrincipalsVersionOrigin(JSContext *cx, JSObject *obj_,
+JS_EvaluateUCScriptForPrincipalsVersionOrigin(JSContext *cx, JSObject *objArg,
                                               JSPrincipals *principals,
                                               JSPrincipals *originPrincipals,
                                               const jschar *chars, unsigned length,
                                               const char *filename, unsigned lineno,
                                               jsval *rval, JSVersion version)
 {
-    RootedObject obj(cx, obj_);
-
+    RootedObject obj(cx, objArg);
     CompileOptions options(cx);
     options.setPrincipals(principals)
            .setOriginPrincipals(originPrincipals)
            .setFileAndLine(filename, lineno)
            .setVersion(version);
 
     return Evaluate(cx, obj, options, chars, length, rval);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_EvaluateUCScript(JSContext *cx, JSObject *obj_, const jschar *chars, unsigned length,
+JS_EvaluateUCScript(JSContext *cx, JSObject *objArg, const jschar *chars, unsigned length,
                     const char *filename, unsigned lineno, jsval *rval)
 {
-    RootedObject obj(cx, obj_);
-
+    RootedObject obj(cx, objArg);
     CompileOptions options(cx);
     options.setFileAndLine(filename, lineno);
 
     return Evaluate(cx, obj, options, chars, length, rval);
 }
 
 /* Ancient unsigned nbytes is part of API/ABI, so use size_t length local. */
 JS_PUBLIC_API(JSBool)
-JS_EvaluateScriptForPrincipals(JSContext *cx, JSObject *obj_, JSPrincipals *principals,
+JS_EvaluateScriptForPrincipals(JSContext *cx, JSObject *objArg, JSPrincipals *principals,
                                const char *bytes, unsigned nbytes,
                                const char *filename, unsigned lineno, jsval *rval)
 {
-    RootedObject obj(cx, obj_);
-
+    RootedObject obj(cx, objArg);
     CompileOptions options(cx);
     options.setPrincipals(principals)
            .setFileAndLine(filename, lineno);
 
     return Evaluate(cx, obj, options, bytes, nbytes, rval);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_EvaluateScriptForPrincipalsVersion(JSContext *cx, JSObject *obj_, JSPrincipals *principals,
+JS_EvaluateScriptForPrincipalsVersion(JSContext *cx, JSObject *objArg, JSPrincipals *principals,
                                       const char *bytes, unsigned nbytes,
                                       const char *filename, unsigned lineno, jsval *rval,
                                       JSVersion version)
 {
-    RootedObject obj(cx, obj_);
-
+    RootedObject obj(cx, objArg);
     CompileOptions options(cx);
     options.setPrincipals(principals)
            .setVersion(version)
            .setFileAndLine(filename, lineno);
 
     return Evaluate(cx, obj, options, bytes, nbytes, rval);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_EvaluateScript(JSContext *cx, JSObject *obj_, const char *bytes, unsigned nbytes,
+JS_EvaluateScript(JSContext *cx, JSObject *objArg, const char *bytes, unsigned nbytes,
                   const char *filename, unsigned lineno, jsval *rval)
 {
-    RootedObject obj(cx, obj_);
-
+    RootedObject obj(cx, objArg);
     CompileOptions options(cx);
     options.setFileAndLine(filename, lineno);
 
     return Evaluate(cx, obj, options, bytes, nbytes, rval);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_CallFunction(JSContext *cx, JSObject *obj, JSFunction *fun, unsigned argc, jsval *argv,
+JS_CallFunction(JSContext *cx, JSObject *objArg, JSFunction *fun, unsigned argc, jsval *argv,
                 jsval *rval)
 {
+    RootedObject obj(cx, objArg);
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, fun, JSValueArray(argv, argc));
     AutoLastFrameCheck lfc(cx);
 
     return Invoke(cx, ObjectOrNullValue(obj), ObjectValue(*fun), argc, argv, rval);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_CallFunctionName(JSContext *cx, JSObject *obj_, const char *name, unsigned argc, jsval *argv,
+JS_CallFunctionName(JSContext *cx, JSObject *objArg, const char *name, unsigned argc, jsval *argv,
                     jsval *rval)
 {
+    RootedObject obj(cx, objArg);
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
-    assertSameCompartment(cx, obj_, JSValueArray(argv, argc));
+    assertSameCompartment(cx, obj, JSValueArray(argv, argc));
     AutoLastFrameCheck lfc(cx);
 
-    RootedObject obj(cx, obj_);
-
     JSAtom *atom = js_Atomize(cx, name, strlen(name));
     if (!atom)
         return false;
 
     RootedValue v(cx);
-    Rooted<jsid> id(cx, AtomToId(atom));
+    RootedId id(cx, AtomToId(atom));
     return GetMethod(cx, obj, id, 0, &v) &&
            Invoke(cx, ObjectOrNullValue(obj), v, argc, argv, rval);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_CallFunctionValue(JSContext *cx, JSObject *obj, jsval fval, unsigned argc, jsval *argv,
+JS_CallFunctionValue(JSContext *cx, JSObject *objArg, jsval fval, unsigned argc, jsval *argv,
                      jsval *rval)
 {
+    RootedObject obj(cx, objArg);
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, fval, JSValueArray(argv, argc));
     AutoLastFrameCheck lfc(cx);
 
     return Invoke(cx, ObjectOrNullValue(obj), fval, argc, argv, rval);
 }
@@ -5838,18 +5847,19 @@ Call(JSContext *cx, jsval thisv, jsval f
     AutoLastFrameCheck lfc(cx);
 
     return Invoke(cx, thisv, fval, argc, argv, rval);
 }
 
 } // namespace JS
 
 JS_PUBLIC_API(JSObject *)
-JS_New(JSContext *cx, JSObject *ctor, unsigned argc, jsval *argv)
-{
+JS_New(JSContext *cx, JSObject *ctorArg, unsigned argc, jsval *argv)
+{
+    RootedObject ctor(cx, ctorArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, ctor, JSValueArray(argv, argc));
     AutoLastFrameCheck lfc(cx);
 
     // This is not a simple variation of JS_CallFunctionValue because JSOP_NEW
     // is not a simple variation of JSOP_CALL. We have to determine what class
     // of object to create, create it, and clamp the return value to an object,
@@ -6304,19 +6314,20 @@ JS_EncodeStringToBuffer(JSString *str, c
         /* Make sure that the buffer contains only valid UTF-8 sequences. */
         JS_ASSERT(js_CStringsAreUTF8);
         PodZero(buffer + writtenLength, length - writtenLength);
     }
     return necessaryLength;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_Stringify(JSContext *cx, jsval *vp, JSObject *replacer, jsval space,
+JS_Stringify(JSContext *cx, jsval *vp, JSObject *replacerArg, jsval space,
              JSONWriteCallback callback, void *data)
 {
+    RootedObject replacer(cx, replacerArg);
     RootedValue value(cx, *vp);
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, replacer, space);
     StringBuffer sb(cx);
     if (!js_Stringify(cx, &value, replacer, space, sb))
         return false;
@@ -6692,17 +6703,17 @@ JS_PUBLIC_API(JSObject *)
 JS_NewDateObjectMsec(JSContext *cx, double msec)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     return js_NewDateObjectMsec(cx, msec);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_ObjectIsDate(JSContext *cx, JSObject *obj)
+JS_ObjectIsDate(JSContext *cx, JSRawObject obj)
 {
     AssertHeapIsIdle(cx);
     JS_ASSERT(obj);
     return obj->isDate();
 }
 
 JS_PUBLIC_API(void)
 JS_ClearDateCaches(JSContext *cx)
@@ -6713,65 +6724,69 @@ JS_ClearDateCaches(JSContext *cx)
 }
 
 /************************************************************************/
 
 /*
  * Regular Expressions.
  */
 JS_PUBLIC_API(JSObject *)
-JS_NewRegExpObject(JSContext *cx, JSObject *obj_, char *bytes, size_t length, unsigned flags)
-{
-    RootedObject obj(cx, obj_);
-
+JS_NewRegExpObject(JSContext *cx, JSObject *objArg, char *bytes, size_t length, unsigned flags)
+{
+    RootedObject obj(cx, objArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     jschar *chars = InflateString(cx, bytes, &length);
     if (!chars)
         return NULL;
 
     RegExpStatics *res = obj->asGlobal().getRegExpStatics();
     RegExpObject *reobj = RegExpObject::create(cx, res, chars, length, RegExpFlag(flags), NULL);
     cx->free_(chars);
     return reobj;
 }
 
 JS_PUBLIC_API(JSObject *)
-JS_NewUCRegExpObject(JSContext *cx, JSObject *obj, jschar *chars, size_t length, unsigned flags)
-{
+JS_NewUCRegExpObject(JSContext *cx, JSObject *objArg, jschar *chars, size_t length, unsigned flags)
+{
+    RootedObject obj(cx, objArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     RegExpStatics *res = obj->asGlobal().getRegExpStatics();
     return RegExpObject::create(cx, res, chars, length, RegExpFlag(flags), NULL);
 }
 
 JS_PUBLIC_API(void)
-JS_SetRegExpInput(JSContext *cx, JSObject *obj, JSString *input, JSBool multiline)
-{
+JS_SetRegExpInput(JSContext *cx, JSObject *objArg, JSString *input, JSBool multiline)
+{
+    RootedObject obj(cx, objArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, input);
 
     obj->asGlobal().getRegExpStatics()->reset(cx, input, !!multiline);
 }
 
 JS_PUBLIC_API(void)
-JS_ClearRegExpStatics(JSContext *cx, JSObject *obj)
-{
+JS_ClearRegExpStatics(JSContext *cx, JSObject *objArg)
+{
+    RootedObject obj(cx, objArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     JS_ASSERT(obj);
 
     obj->asGlobal().getRegExpStatics()->clear();
 }
 
 JS_PUBLIC_API(JSBool)
-JS_ExecuteRegExp(JSContext *cx, JSObject *obj, JSObject *reobj, jschar *chars, size_t length,
+JS_ExecuteRegExp(JSContext *cx, JSObject *objArg, JSObject *reobjArg, jschar *chars, size_t length,
                  size_t *indexp, JSBool test, jsval *rval)
 {
+    RootedObject obj(cx, objArg);
+    RootedObject reobj(cx, reobjArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
 
     RegExpStatics *res = obj->asGlobal().getRegExpStatics();
     return ExecuteRegExp(cx, res, reobj->asRegExp(), NULL, chars, length,
                          indexp, test ? RegExpTest : RegExpExec, rval);
 }
 
@@ -6792,46 +6807,50 @@ JS_PUBLIC_API(JSObject *)
 JS_NewUCRegExpObjectNoStatics(JSContext *cx, jschar *chars, size_t length, unsigned flags)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     return RegExpObject::createNoStatics(cx, chars, length, RegExpFlag(flags), NULL);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_ExecuteRegExpNoStatics(JSContext *cx, JSObject *obj, jschar *chars, size_t length,
+JS_ExecuteRegExpNoStatics(JSContext *cx, JSObject *objArg, jschar *chars, size_t length,
                           size_t *indexp, JSBool test, jsval *rval)
 {
+    RootedObject obj(cx, objArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
 
     return ExecuteRegExp(cx, NULL, obj->asRegExp(), NULL, chars, length, indexp,
                          test ? RegExpTest : RegExpExec, rval);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_ObjectIsRegExp(JSContext *cx, JSObject *obj)
-{
+JS_ObjectIsRegExp(JSContext *cx, JSObject *objArg)
+{
+    RootedObject obj(cx, objArg);
     AssertHeapIsIdle(cx);
     JS_ASSERT(obj);
     return obj->isRegExp();
 }
 
 JS_PUBLIC_API(unsigned)
-JS_GetRegExpFlags(JSContext *cx, JSObject *obj)
-{
+JS_GetRegExpFlags(JSContext *cx, JSObject *objArg)
+{
+    RootedObject obj(cx, objArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
 
     return obj->asRegExp().getFlags();
 }
 
 JS_PUBLIC_API(JSString *)
-JS_GetRegExpSource(JSContext *cx, JSObject *obj)
-{
+JS_GetRegExpSource(JSContext *cx, JSObject *objArg)
+{
+    RootedObject obj(cx, objArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
 
     return obj->asRegExp().getSource();
 }
 
 /************************************************************************/
 
@@ -7164,19 +7183,20 @@ JS_EncodeScript(JSContext *cx, JSScript 
 {
     XDREncoder encoder(cx);
     if (!encoder.codeScript(&script))
         return NULL;
     return encoder.forgetData(lengthp);
 }
 
 JS_PUBLIC_API(void *)
-JS_EncodeInterpretedFunction(JSContext *cx, JSObject *funobj, uint32_t *lengthp)
+JS_EncodeInterpretedFunction(JSContext *cx, JSRawObject funobjArg, uint32_t *lengthp)
 {
     XDREncoder encoder(cx);
+    RootedObject funobj(cx, funobjArg);
     if (!encoder.codeFunction(&funobj))
         return NULL;
     return encoder.forgetData(lengthp);
 }
 
 JS_PUBLIC_API(JSScript *)
 JS_DecodeScript(JSContext *cx, const void *data, uint32_t length,
                 JSPrincipals *principals, JSPrincipals *originPrincipals)
@@ -7188,17 +7208,17 @@ JS_DecodeScript(JSContext *cx, const voi
     return script;
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_DecodeInterpretedFunction(JSContext *cx, const void *data, uint32_t length,
                              JSPrincipals *principals, JSPrincipals *originPrincipals)
 {
     XDRDecoder decoder(cx, data, length, principals, originPrincipals);
-    JSObject *funobj;
+    RootedObject funobj(cx);
     if (!decoder.codeFunction(&funobj))
         return NULL;
     return funobj;
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_GetScriptedGlobal(JSContext *cx)
 {
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1598,31 +1598,35 @@ JS_STATIC_ASSERT(sizeof(jsval_layout) ==
 
 /************************************************************************/
 
 #ifdef __cplusplus
 
 typedef JS::Handle<JSObject*> JSHandleObject;
 typedef JS::Handle<JSString*> JSHandleString;
 typedef JS::Handle<jsid> JSHandleId;
+typedef JS::Handle<JS::Value> JSHandleValue;
 typedef JS::MutableHandle<JSObject*> JSMutableHandleObject;
 typedef JS::MutableHandle<JS::Value> JSMutableHandleValue;
+typedef JS::RawObject JSRawObject;
 
 #else
 
 /*
  * Handle support for C API users. Handles must be destroyed in the reverse
  * order that they were created (as in a stack).
  */
 
 typedef struct { JSObject **_; } JSHandleObject;
+typedef struct { jsval _; } JSHandleValue;
 typedef struct { JSString **_; } JSHandleString;
 typedef struct { JSObject **_; } JSMutableHandleObject;
+typedef struct { jsid *_; } JSHandleId;
 typedef struct { jsval *_; } JSMutableHandleValue;
-typedef struct { jsid *_; } JSHandleId;
+typedef JSObject *JSRawObject;
 
 JSBool JS_CreateHandleObject(JSContext *cx, JSObject *obj, JSHandleObject *phandle);
 void JS_DestroyHandleObject(JSContext *cx, JSHandleObject handle);
 
 JSBool JS_CreateMutableHandleObject(JSContext *cx, JSObject *obj, JSMutableHandleObject *phandle);
 void JS_DestroyMutableHandleObject(JSContext *cx, JSMutableHandleObject handle);
 
 JSBool JS_CreateHandleId(JSContext *cx, jsid id, JSHandleId *phandle);
@@ -1734,17 +1738,17 @@ typedef JSBool
  */
 typedef JSBool
 (* JSConvertOp)(JSContext *cx, JSHandleObject obj, JSType type, JSMutableHandleValue vp);
 
 /*
  * Delegate typeof to an object so it can cloak a primitive or another object.
  */
 typedef JSType
-(* JSTypeOfOp)(JSContext *cx, JSObject *obj);
+(* JSTypeOfOp)(JSContext *cx, JSHandleObject obj);
 
 typedef struct JSFreeOp JSFreeOp;
 
 struct JSFreeOp {
 #ifndef __cplusplus
     JSRuntime   *runtime;
 #else
   private:
@@ -2338,17 +2342,17 @@ JSID_IS_OBJECT(jsid id)
 static JS_ALWAYS_INLINE JSObject *
 JSID_TO_OBJECT(jsid id)
 {
     JS_ASSERT(JSID_IS_OBJECT(id));
     return (JSObject *)(JSID_BITS(id) & ~(size_t)JSID_TYPE_MASK);
 }
 
 static JS_ALWAYS_INLINE jsid
-OBJECT_TO_JSID(JSObject *obj)
+OBJECT_TO_JSID(JSRawObject obj)
 {
     jsid id;
     JS_ASSERT(obj != NULL);
     JS_ASSERT(((size_t)obj & JSID_TYPE_MASK) == 0);
     JSID_BITS(id) = ((size_t)obj | JSID_TYPE_OBJECT);
     return id;
 }
 
@@ -3131,17 +3135,17 @@ JS_SetCompartmentNameCallback(JSRuntime 
 
 extern JS_PUBLIC_API(JSWrapObjectCallback)
 JS_SetWrapObjectCallbacks(JSRuntime *rt,
                           JSWrapObjectCallback callback,
                           JSSameCompartmentWrapObjectCallback sccallback,
                           JSPreWrapCallback precallback);
 
 extern JS_PUBLIC_API(JSCrossCompartmentCall *)
-JS_EnterCrossCompartmentCall(JSContext *cx, JSObject *target);
+JS_EnterCrossCompartmentCall(JSContext *cx, JSRawObject target);
 
 extern JS_PUBLIC_API(void)
 JS_LeaveCrossCompartmentCall(JSCrossCompartmentCall *call);
 
 extern JS_PUBLIC_API(void)
 JS_SetCompartmentPrivate(JSCompartment *compartment, void *data);
 
 extern JS_PUBLIC_API(void *)
@@ -3203,19 +3207,19 @@ class JS_PUBLIC_API(JSAutoEnterCompartme
         STATE_UNENTERED,
         STATE_SAME_COMPARTMENT,
         STATE_OTHER_COMPARTMENT
     } state;
 
   public:
     JSAutoEnterCompartment() : state(STATE_UNENTERED) {}
 
-    bool enter(JSContext *cx, JSObject *target);
-
-    void enterAndIgnoreErrors(JSContext *cx, JSObject *target);
+    bool enter(JSContext *cx, JSRawObject target);
+
+    void enterAndIgnoreErrors(JSContext *cx, JSRawObject target);
 
     bool entered() const { return state != STATE_UNENTERED; }
 
     /*
      * In general, consumers should try to avoid calling leave() explicitly,
      * and defer to the destructor by scoping the JSAutoEnterCompartment
      * appropriately. Sometimes, though, it's unavoidable.
      */
@@ -3237,17 +3241,17 @@ typedef void (*JSIterateCompartmentCallb
 extern JS_PUBLIC_API(void)
 JS_IterateCompartments(JSRuntime *rt, void *data,
                        JSIterateCompartmentCallback compartmentCallback);
 
 extern JS_PUBLIC_API(JSObject *)
 JS_GetGlobalObject(JSContext *cx);
 
 extern JS_PUBLIC_API(void)
-JS_SetGlobalObject(JSContext *cx, JSObject *obj);
+JS_SetGlobalObject(JSContext *cx, JSRawObject obj);
 
 /*
  * Initialize standard JS class constructors, prototypes, and any top-level
  * functions and constants associated with the standard classes (e.g. isNaN
  * for Number).
  *
  * NB: This sets cx's global object to obj if it was null.
  */
@@ -3279,41 +3283,40 @@ JS_EnumerateStandardClasses(JSContext *c
  * JSIdArray if ida is null.  Return the augmented array on success, null on
  * failure with ida (if it was non-null on entry) destroyed.
  */
 extern JS_PUBLIC_API(JSIdArray *)
 JS_EnumerateResolvedStandardClasses(JSContext *cx, JSObject *obj,
                                     JSIdArray *ida);
 
 extern JS_PUBLIC_API(JSBool)
-JS_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key,
-                  JSObject **objp);
+JS_GetClassObject(JSContext *cx, JSRawObject obj, JSProtoKey key, JSObject **objp);
 
 extern JS_PUBLIC_API(JSBool)
 JS_GetClassPrototype(JSContext *cx, JSProtoKey key, JSObject **objp);
 
 extern JS_PUBLIC_API(JSProtoKey)
 JS_IdentifyClassPrototype(JSContext *cx, JSObject *obj);
 
 /*
  * Returns the original value of |Function.prototype| from the global object in
  * which |forObj| was created.
  */
 extern JS_PUBLIC_API(JSObject *)
-JS_GetFunctionPrototype(JSContext *cx, JSObject *forObj);
+JS_GetFunctionPrototype(JSContext *cx, JSRawObject forObj);
 
 /*
  * Returns the original value of |Object.prototype| from the global object in
  * which |forObj| was created.
  */
 extern JS_PUBLIC_API(JSObject *)
-JS_GetObjectPrototype(JSContext *cx, JSObject *forObj);
+JS_GetObjectPrototype(JSContext *cx, JSRawObject forObj);
 
 extern JS_PUBLIC_API(JSObject *)
-JS_GetGlobalForObject(JSContext *cx, JSObject *obj);
+JS_GetGlobalForObject(JSContext *cx, JSRawObject obj);
 
 /*
  * May return NULL, if |c| never had a global (e.g. the atoms compartment), or
  * if |c|'s global has been collected.
  */
 extern JS_PUBLIC_API(JSObject *)
 JS_GetGlobalForCompartmentOrNull(JSContext *cx, JSCompartment *c);
 
@@ -3358,17 +3361,17 @@ typedef struct JSCTypesCallbacks JSCType
 
 /*
  * Set the callbacks on the provided 'ctypesObj' object. 'callbacks' should be a
  * pointer to static data that exists for the lifetime of 'ctypesObj', but it
  * may safely be altered after calling this function and without having
  * to call this function again.
  */
 extern JS_PUBLIC_API(void)
-JS_SetCTypesCallbacks(JSObject *ctypesObj, JSCTypesCallbacks *callbacks);
+JS_SetCTypesCallbacks(JSRawObject ctypesObj, JSCTypesCallbacks *callbacks);
 #endif
 
 typedef JSBool
 (* JSEnumerateDiagnosticMemoryCallback)(void *ptr, size_t length);
 
 /*
  * Enumerate memory regions that contain diagnostic information
  * intended to be included in crash report minidumps.
@@ -4263,72 +4266,72 @@ JS_InitClass(JSContext *cx, JSObject *ob
 /*
  * Set up ctor.prototype = proto and proto.constructor = ctor with the
  * right property flags.
  */
 extern JS_PUBLIC_API(JSBool)
 JS_LinkConstructorAndPrototype(JSContext *cx, JSObject *ctor, JSObject *proto);
 
 extern JS_PUBLIC_API(JSClass *)
-JS_GetClass(JSObject *obj);
+JS_GetClass(JSRawObject obj);
 
 extern JS_PUBLIC_API(JSBool)
 JS_InstanceOf(JSContext *cx, JSObject *obj, JSClass *clasp, jsval *argv);
 
 extern JS_PUBLIC_API(JSBool)
 JS_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
 
 extern JS_PUBLIC_API(void *)
-JS_GetPrivate(JSObject *obj);
+JS_GetPrivate(JSRawObject obj);
 
 extern JS_PUBLIC_API(void)
-JS_SetPrivate(JSObject *obj, void *data);
+JS_SetPrivate(JSRawObject obj, void *data);
 
 extern JS_PUBLIC_API(void *)
 JS_GetInstancePrivate(JSContext *cx, JSObject *obj, JSClass *clasp,
                       jsval *argv);
 
 extern JS_PUBLIC_API(JSObject *)
-JS_GetPrototype(JSObject *obj);
+JS_GetPrototype(JSRawObject obj);
 
 extern JS_PUBLIC_API(JSBool)
 JS_SetPrototype(JSContext *cx, JSObject *obj, JSObject *proto);
 
 extern JS_PUBLIC_API(JSObject *)
-JS_GetParent(JSObject *obj);
+JS_GetParent(JSRawObject obj);
 
 extern JS_PUBLIC_API(JSBool)
 JS_SetParent(JSContext *cx, JSObject *obj, JSObject *parent);
 
 extern JS_PUBLIC_API(JSObject *)
 JS_GetConstructor(JSContext *cx, JSObject *proto);
 
 /*
  * Get a unique identifier for obj, good for the lifetime of obj (even if it
  * is moved by a copying GC).  Return false on failure (likely out of memory),
  * and true with *idp containing the unique id on success.
  */
 extern JS_PUBLIC_API(JSBool)
-JS_GetObjectId(JSContext *cx, JSObject *obj, jsid *idp);
+JS_GetObjectId(JSContext *cx, JSRawObject obj, jsid *idp);
 
 extern JS_PUBLIC_API(JSObject *)
 JS_NewGlobalObject(JSContext *cx, JSClass *clasp, JSPrincipals *principals);
 
 extern JS_PUBLIC_API(JSObject *)
 JS_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent);
 
 /* Queries the [[Extensible]] property of the object. */
 extern JS_PUBLIC_API(JSBool)
-JS_IsExtensible(JSObject *obj);
-
-extern JS_PUBLIC_API(JSBool)
-JS_IsNative(JSObject *obj);
+JS_IsExtensible(JSRawObject obj);
+
+extern JS_PUBLIC_API(JSBool)
+JS_IsNative(JSRawObject obj);
 
 extern JS_PUBLIC_API(JSRuntime *)
-JS_GetObjectRuntime(JSObject *obj);
+JS_GetObjectRuntime(JSRawObject obj);
 
 /*
  * Unlike JS_NewObject, JS_NewObjectWithGivenProto does not compute a default
  * proto if proto's actual parameter value is null.
  */
 extern JS_PUBLIC_API(JSObject *)
 JS_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
                            JSObject *parent);
@@ -4665,20 +4668,20 @@ JS_NextProperty(JSContext *cx, JSObject 
 extern JS_PUBLIC_API(JSBool)
 JS_ArrayIterator(JSContext *cx, unsigned argc, jsval *vp);
 
 extern JS_PUBLIC_API(JSBool)
 JS_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
                jsval *vp, unsigned *attrsp);
 
 extern JS_PUBLIC_API(jsval)
-JS_GetReservedSlot(JSObject *obj, uint32_t index);
+JS_GetReservedSlot(JSRawObject obj, uint32_t index);
 
 extern JS_PUBLIC_API(void)
-JS_SetReservedSlot(JSObject *obj, uint32_t index, jsval v);
+JS_SetReservedSlot(JSRawObject obj, uint32_t index, jsval v);
 
 /************************************************************************/
 
 /*
  * Security protocol.
  */
 struct JSPrincipals {
     /* Don't call "destroy"; use reference counting macros below. */
@@ -4789,31 +4792,31 @@ JS_GetFunctionArity(JSFunction *fun);
 
 /*
  * Infallible predicate to test whether obj is a function object (faster than
  * comparing obj's class name to "Function", but equivalent unless someone has
  * overwritten the "Function" identifier with a different constructor and then
  * created instances using that constructor that might be passed in as obj).
  */
 extern JS_PUBLIC_API(JSBool)
-JS_ObjectIsFunction(JSContext *cx, JSObject *obj);
-
-extern JS_PUBLIC_API(JSBool)
-JS_ObjectIsCallable(JSContext *cx, JSObject *obj);
-
-extern JS_PUBLIC_API(JSBool)
-JS_IsNativeFunction(JSObject *funobj, JSNative call);
+JS_ObjectIsFunction(JSContext *cx, JSRawObject obj);
+
+extern JS_PUBLIC_API(JSBool)
+JS_ObjectIsCallable(JSContext *cx, JSRawObject obj);
+
+extern JS_PUBLIC_API(JSBool)
+JS_IsNativeFunction(JSRawObject funobj, JSNative call);
 
 /*
  * Bind the given callable to use the given object as "this".
  *
  * If |callable| is not callable, will throw and return NULL.
  */
 extern JS_PUBLIC_API(JSObject*)
-JS_BindCallable(JSContext *cx, JSObject *callable, JSObject *newThis);
+JS_BindCallable(JSContext *cx, JSObject *callable, JSRawObject newThis);
 
 extern JS_PUBLIC_API(JSBool)
 JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs);
 
 extern JS_PUBLIC_API(JSFunction *)
 JS_DefineFunction(JSContext *cx, JSObject *obj, const char *name, JSNative call,
                   unsigned nargs, unsigned attrs);
 
@@ -4826,17 +4829,17 @@ extern JS_PUBLIC_API(JSFunction *)
 JS_DefineFunctionById(JSContext *cx, JSObject *obj, jsid id, JSNative call,
                       unsigned nargs, unsigned attrs);
 
 /*
  * Clone a top-level function into a new scope. This function will dynamically
  * fail if funobj was lexically nested inside some other function.
  */
 extern JS_PUBLIC_API(JSObject *)
-JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent);
+JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSRawObject parent);
 
 /*
  * Given a buffer, return JS_FALSE if the buffer might become a valid
  * javascript statement with the addition of more lines.  Otherwise return
  * JS_TRUE.  The intent is to support interactive compilation - accumulate
  * lines in a buffer until JS_BufferIsCompilableUnit is true, then pass it to
  * the compiler.
  */
@@ -5882,17 +5885,17 @@ JS_NewDateObject(JSContext *cx, int year
 
 extern JS_PUBLIC_API(JSObject *)
 JS_NewDateObjectMsec(JSContext *cx, double msec);
 
 /*
  * Infallible predicate to test whether obj is a date object.
  */
 extern JS_PUBLIC_API(JSBool)
-JS_ObjectIsDate(JSContext *cx, JSObject *obj);
+JS_ObjectIsDate(JSContext *cx, JSRawObject obj);
 
 /*
  * Clears the cache of calculated local time from each Date object.
  * Call to propagate a system timezone change.
  */
 extern JS_PUBLIC_API(void)
 JS_ClearDateCaches(JSContext *cx);
 
@@ -6122,17 +6125,17 @@ JS_DescribeScriptedCaller(JSContext *cx,
 /*
  * Encode/Decode interpreted scripts and functions to/from memory.
  */
 
 extern JS_PUBLIC_API(void *)
 JS_EncodeScript(JSContext *cx, JSScript *script, uint32_t *lengthp);
 
 extern JS_PUBLIC_API(void *)
-JS_EncodeInterpretedFunction(JSContext *cx, JSObject *funobj, uint32_t *lengthp);
+JS_EncodeInterpretedFunction(JSContext *cx, JSRawObject funobj, uint32_t *lengthp);
 
 extern JS_PUBLIC_API(JSScript *)
 JS_DecodeScript(JSContext *cx, const void *data, uint32_t length,
                 JSPrincipals *principals, JSPrincipals *originPrincipals);
 
 extern JS_PUBLIC_API(JSObject *)
 JS_DecodeInterpretedFunction(JSContext *cx, const void *data, uint32_t length,
                              JSPrincipals *principals, JSPrincipals *originPrincipals);
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -574,17 +574,17 @@ array_length_setter(JSContext *cx, Handl
     } else {
         /*
          * We are going to remove a lot of indexes in a presumably sparse
          * array. So instead of looping through indexes between newlen and
          * oldlen, we iterate through all properties and remove those that
          * correspond to indexes in the half-open range [newlen, oldlen).  See
          * bug 322135.
          */
-        JSObject *iter = JS_NewPropertyIterator(cx, obj);
+        RootedObject iter(cx, JS_NewPropertyIterator(cx, obj));
         if (!iter)
             return false;
 
         uint32_t gap = oldlen - newlen;
         for (;;) {
             jsid nid;
             if (!JS_CHECK_OPERATION_LIMIT(cx) || !JS_NextProperty(cx, iter, &nid))
                 return false;
@@ -3702,17 +3702,18 @@ NewArray(JSContext *cx, uint32_t length,
             if (allocateCapacity && !EnsureNewArrayElements(cx, obj, length))
                 return NULL;
             return obj;
         }
     }
 
     Rooted<GlobalObject*> parent(cx, parent_);
     RootedObject proto(cx, protoArg);
-    PoisonPtr(reinterpret_cast<uintptr_t *>(protoArg));
+    if (protoArg)
+        PoisonPtr(reinterpret_cast<uintptr_t *>(protoArg));
 
     if (!proto && !FindProto(cx, &ArrayClass, parent, &proto))
         return NULL;
 
     RootedTypeObject type(cx, proto->getNewType(cx));
     if (!type)
         return NULL;
 
--- a/js/src/jsclone.cpp
+++ b/js/src/jsclone.cpp
@@ -396,21 +396,22 @@ JSStructuredCloneWriter::checkStack()
         JS_ASSERT(memory.has(&objs[--j].toObject()));
 #endif
 }
 
 JS_PUBLIC_API(JSBool)
 JS_WriteTypedArray(JSStructuredCloneWriter *w, jsval v)
 {
     JS_ASSERT(v.isObject());
-    return w->writeTypedArray(&v.toObject());
+    RootedObject obj(w->context(), &v.toObject());
+    return w->writeTypedArray(obj);
 }
 
 bool
-JSStructuredCloneWriter::writeTypedArray(JSObject *arr)
+JSStructuredCloneWriter::writeTypedArray(HandleObject arr)
 {
     if (!out.writePair(ArrayTypeToTag(TypedArray::type(arr)), TypedArray::length(arr)))
         return false;
 
     switch (TypedArray::type(arr)) {
     case TypedArray::TYPE_INT8:
     case TypedArray::TYPE_UINT8:
     case TypedArray::TYPE_UINT8_CLAMPED:
@@ -426,25 +427,25 @@ JSStructuredCloneWriter::writeTypedArray
         return out.writeArray((const uint64_t *) TypedArray::viewData(arr), TypedArray::length(arr));
     default:
         JS_NOT_REACHED("unknown TypedArray type");
         return false;
     }
 }
 
 bool
-JSStructuredCloneWriter::writeArrayBuffer(JSObject *obj)
+JSStructuredCloneWriter::writeArrayBuffer(JSHandleObject obj)
 {
     ArrayBufferObject &buffer = obj->asArrayBuffer();
     return out.writePair(SCTAG_ARRAY_BUFFER_OBJECT, buffer.byteLength()) &&
            out.writeBytes(buffer.dataPointer(), buffer.byteLength());
 }
 
 bool
-JSStructuredCloneWriter::startObject(JSObject *obj)
+JSStructuredCloneWriter::startObject(JSHandleObject obj)
 {
     JS_ASSERT(obj->isArray() || obj->isObject());
 
     /* Handle cycles in the object graph. */
     CloneMemory::AddPtr p = memory.lookupForAdd(obj);
     if (p)
         return out.writePair(SCTAG_BACK_REFERENCE_OBJECT, p->value);
     if (!memory.add(p, obj, memory.count()))
@@ -487,17 +488,17 @@ JSStructuredCloneWriter::startWrite(cons
         return out.writeDouble(v.toNumber());
     } else if (v.isBoolean()) {
         return out.writePair(SCTAG_BOOLEAN, v.toBoolean());
     } else if (v.isNull()) {
         return out.writePair(SCTAG_NULL, 0);
     } else if (v.isUndefined()) {
         return out.writePair(SCTAG_UNDEFINED, 0);
     } else if (v.isObject()) {
-        JSObject *obj = &v.toObject();
+        RootedObject obj(context(), &v.toObject());
 
         // The object might be a security wrapper. See if we can clone what's
         // behind it. If we can, unwrap the object.
         obj = UnwrapObjectChecked(context(), obj);
         if (!obj)
             return false;
 
         // If we unwrapped above, we'll need to enter the underlying compartment.
@@ -648,17 +649,17 @@ JS_ReadTypedArray(JSStructuredCloneReade
         return false;
     JS_ASSERT(tag >= SCTAG_TYPED_ARRAY_MIN && tag <= SCTAG_TYPED_ARRAY_MAX);
     return r->readTypedArray(tag, nelems, vp);
 }
 
 bool
 JSStructuredCloneReader::readTypedArray(uint32_t tag, uint32_t nelems, Value *vp)
 {
-    JSObject *obj = NULL;
+    RootedObject obj(context(), NULL);
 
     switch (tag) {
       case SCTAG_TYPED_ARRAY_INT8:
         obj = JS_NewInt8Array(context(), nelems);
         break;
       case SCTAG_TYPED_ARRAY_UINT8:
         obj = JS_NewUint8Array(context(), nelems);
         break;
--- a/js/src/jsclone.h
+++ b/js/src/jsclone.h
@@ -127,19 +127,19 @@ struct JSStructuredCloneWriter {
 
     js::SCOutput &output() { return out; }
 
   private:
     JSContext *context() { return out.context(); }
 
     bool writeString(uint32_t tag, JSString *str);
     bool writeId(jsid id);
-    bool writeArrayBuffer(JSObject *obj);
-    bool writeTypedArray(JSObject *obj);
-    bool startObject(JSObject *obj);
+    bool writeArrayBuffer(JSHandleObject obj);
+    bool writeTypedArray(JSHandleObject obj);
+    bool startObject(JSHandleObject obj);
     bool startWrite(const js::Value &v);
 
     inline void checkStack();
 
     js::SCOutput &out;
 
     // Vector of objects with properties remaining to be written.
     //
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -537,17 +537,17 @@ js_ReportErrorVA(JSContext *cx, unsigned
     Foreground::free_(ucmessage);
     return warning;
 }
 
 namespace js {
 
 /* |callee| requires a usage string provided by JS_DefineFunctionsWithHelp. */
 void
-ReportUsageError(JSContext *cx, JSObject *callee, const char *msg)
+ReportUsageError(JSContext *cx, HandleObject callee, const char *msg)
 {
     const char *usageStr = "usage";
     PropertyName *usageAtom = js_Atomize(cx, usageStr, strlen(usageStr))->asPropertyName();
     DebugOnly<Shape *> shape = callee->nativeLookup(cx, NameToId(usageAtom));
     JS_ASSERT(!shape->configurable());
     JS_ASSERT(!shape->writable());
     JS_ASSERT(shape->hasDefaultGetter());
 
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -1697,17 +1697,17 @@ js_ExpandErrorArguments(JSContext *cx, J
                         char **message, JSErrorReport *reportp,
                         bool charArgs, va_list ap);
 #endif
 
 namespace js {
 
 /* |callee| requires a usage string provided by JS_DefineFunctionsWithHelp. */
 extern void
-ReportUsageError(JSContext *cx, JSObject *callee, const char *msg);
+ReportUsageError(JSContext *cx, HandleObject callee, const char *msg);
 
 } /* namespace js */
 
 extern void
 js_ReportOutOfMemory(JSContext *cx);
 
 extern JS_FRIEND_API(void)
 js_ReportAllocationOverflow(JSContext *cx);
--- a/js/src/jscntxtinlines.h
+++ b/js/src/jscntxtinlines.h
@@ -135,17 +135,17 @@ struct PreserveRegsGuard
 };
 
 static inline GlobalObject *
 GetGlobalForScopeChain(JSContext *cx)
 {
     if (cx->hasfp())
         return &cx->fp()->global();
 
-    JSObject *scope = JS_ObjectToInnerObject(cx, cx->globalObject);
+    JSObject *scope = JS_ObjectToInnerObject(cx, HandleObject::fromMarkedLocation(&cx->globalObject));
     if (!scope)
         return NULL;
     return &scope->asGlobal();
 }
 
 inline GSNCache *
 GetGSNCache(JSContext *cx)
 {
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -116,25 +116,28 @@ JSCompartment::setNeedsBarrier(bool need
 #ifdef JS_METHODJIT
     if (needsBarrier_ != needs)
         mjit::ClearAllFrames(this);
 #endif
     needsBarrier_ = needs;
 }
 
 static bool
-WrapForSameCompartment(JSContext *cx, JSObject *obj, Value *vp)
+WrapForSameCompartment(JSContext *cx, HandleObject obj, Value *vp)
 {
     JS_ASSERT(cx->compartment == obj->compartment());
-    if (cx->runtime->sameCompartmentWrapObjectCallback) {
-        obj = cx->runtime->sameCompartmentWrapObjectCallback(cx, obj);
-        if (!obj)
-            return false;
+    if (!cx->runtime->sameCompartmentWrapObjectCallback) {
+        vp->setObject(*obj);
+        return true;
     }
-    vp->setObject(*obj);
+
+    JSObject *wrapped = cx->runtime->sameCompartmentWrapObjectCallback(cx, obj);
+    if (!wrapped)
+        return false;
+    vp->setObject(*wrapped);
     return true;
 }
 
 bool
 JSCompartment::wrap(JSContext *cx, Value *vp)
 {
     JS_ASSERT(cx->compartment == this);
 
@@ -176,17 +179,18 @@ JSCompartment::wrap(JSContext *cx, Value
      * parent without being a proper global object (JSCLASS_IS_GLOBAL). Instead,
      * we parent all wrappers to the global object in their home compartment.
      * This loses us some transparency, and is generally very cheesy.
      */
     RootedObject global(cx);
     if (cx->hasfp()) {
         global = &cx->fp()->global();
     } else {
-        global = JS_ObjectToInnerObject(cx, cx->globalObject);
+        global = cx->globalObject;
+        global = JS_ObjectToInnerObject(cx, global);
         if (!global)
             return false;
     }
 
     /* Unwrap incoming objects. */
     if (vp->isObject()) {
         Rooted<JSObject*> obj(cx, &vp->toObject());
 
--- a/js/src/jsdate.cpp
+++ b/js/src/jsdate.cpp
@@ -3291,13 +3291,13 @@ js_DateGetSeconds(JSContext *cx, JSObjec
 
     double utctime = obj->getDateUTCTime().toNumber();
     if (MOZ_DOUBLE_IS_NaN(utctime))
         return 0;
     return (int) SecFromTime(utctime);
 }
 
 JS_FRIEND_API(double)
-js_DateGetMsecSinceEpoch(JSContext *cx, JSObject *obj)
+js_DateGetMsecSinceEpoch(JSContext *cx, RawObject obj)
 {
     return obj->isDate() ? obj->getDateUTCTime().toNumber() : 0;
 }
 
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -1440,18 +1440,20 @@ static JSFunctionSpec profiling_function
     JS_FN("resumeVtune",    js_ResumeVtune,       0,0),
 #endif
     JS_FS_END
 };
 
 #endif
 
 JS_PUBLIC_API(JSBool)
-JS_DefineProfilingFunctions(JSContext *cx, JSObject *obj)
+JS_DefineProfilingFunctions(JSContext *cx, JSObject *objArg)
 {
+    RootedObject obj(cx, objArg);
+
     assertSameCompartment(cx, obj);
 #ifdef MOZ_PROFILING
     return JS_DefineFunctions(cx, obj, profiling_functions);
 #else
     return true;
 #endif
 }
 
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -38,19 +38,19 @@ JS_SetGrayGCRootsTracer(JSRuntime *rt, J
 JS_FRIEND_API(JSString *)
 JS_GetAnonymousString(JSRuntime *rt)
 {
     JS_ASSERT(rt->hasContexts());
     return rt->atomState.anonymousAtom;
 }
 
 JS_FRIEND_API(JSObject *)
-JS_FindCompilationScope(JSContext *cx, JSObject *obj_)
+JS_FindCompilationScope(JSContext *cx, RawObject objArg)
 {
-    RootedObject obj(cx, obj_);
+    RootedObject obj(cx, objArg);
 
     /*
      * We unwrap wrappers here. This is a little weird, but it's what's being
      * asked of us.
      */
     if (obj->isWrapper())
         obj = UnwrapObject(obj);
 
@@ -59,32 +59,34 @@ JS_FindCompilationScope(JSContext *cx, J
      * scope.
      */
     if (JSObjectOp op = obj->getClass()->ext.innerObject)
         obj = op(cx, obj);
     return obj;
 }
 
 JS_FRIEND_API(JSFunction *)
-JS_GetObjectFunction(JSObject *obj)
+JS_GetObjectFunction(RawObject obj)
 {
     if (obj->isFunction())
         return obj->toFunction();
     return NULL;
 }
 
 JS_FRIEND_API(JSObject *)
 JS_GetGlobalForFrame(JSStackFrame *fp)
 {
     return &Valueify(fp)->global();
 }
 
 JS_FRIEND_API(JSBool)
-JS_SplicePrototype(JSContext *cx, JSObject *obj, JSObject *proto)
+JS_SplicePrototype(JSContext *cx, JSObject *objArg, JSObject *protoArg)
 {
+    RootedObject obj(cx, objArg);
+    RootedObject proto(cx, protoArg);
     /*
      * Change the prototype of an object which hasn't been used anywhere
      * and does not share its type with another object. Unlike JS_SetPrototype,
      * does not nuke type information for the object.
      */
     CHECK_REQUEST(cx);
 
     if (!obj->hasSingletonType()) {
@@ -94,18 +96,20 @@ JS_SplicePrototype(JSContext *cx, JSObje
          */
         return JS_SetPrototype(cx, obj, proto);
     }
 
     return obj->splicePrototype(cx, proto);
 }
 
 JS_FRIEND_API(JSObject *)
-JS_NewObjectWithUniqueType(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent)
+JS_NewObjectWithUniqueType(JSContext *cx, JSClass *clasp, JSObject *protoArg, JSObject *parentArg)
 {
+    RootedObject proto(cx, protoArg);
+    RootedObject parent(cx, parentArg);
     JSObject *obj = JS_NewObject(cx, clasp, proto, parent);
     if (!obj || !obj->setSingletonType(cx))
         return NULL;
     return obj;
 }
 
 JS_FRIEND_API(void)
 js::PrepareCompartmentForGC(JSCompartment *comp)
@@ -236,20 +240,19 @@ DefineHelpProperty(JSContext *cx, Handle
         return false;
     jsval v = STRING_TO_JSVAL(atom);
     return JS_DefineProperty(cx, obj, prop, v,
                              JS_PropertyStub, JS_StrictPropertyStub,
                              JSPROP_READONLY | JSPROP_PERMANENT);
 }
 
 JS_FRIEND_API(bool)
-JS_DefineFunctionsWithHelp(JSContext *cx, JSObject *obj_, const JSFunctionSpecWithHelp *fs)
+JS_DefineFunctionsWithHelp(JSContext *cx, JSObject *objArg, const JSFunctionSpecWithHelp *fs)
 {
-    RootedObject obj(cx, obj_);
-
+    RootedObject obj(cx, objArg);
     JS_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
 
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     for (; fs->name; fs++) {
         JSAtom *atom = js_Atomize(cx, fs->name, strlen(fs->name));
         if (!atom)
             return false;
@@ -276,17 +279,17 @@ JS_DefineFunctionsWithHelp(JSContext *cx
 AutoSwitchCompartment::AutoSwitchCompartment(JSContext *cx, JSCompartment *newCompartment
                                              JS_GUARD_OBJECT_NOTIFIER_PARAM_NO_INIT)
   : cx(cx), oldCompartment(cx->compartment)
 {
     JS_GUARD_OBJECT_NOTIFIER_INIT;
     cx->setCompartment(newCompartment);
 }
 
-AutoSwitchCompartment::AutoSwitchCompartment(JSContext *cx, JSObject *target
+AutoSwitchCompartment::AutoSwitchCompartment(JSContext *cx, JSHandleObject target
                                              JS_GUARD_OBJECT_NOTIFIER_PARAM_NO_INIT)
   : cx(cx), oldCompartment(cx->compartment)
 {
     JS_GUARD_OBJECT_NOTIFIER_INIT;
     cx->setCompartment(target->compartment());
 }
 
 AutoSwitchCompartment::~AutoSwitchCompartment()
@@ -303,79 +306,77 @@ js::IsSystemCompartment(const JSCompartm
 
 JS_FRIEND_API(bool)
 js::IsAtomsCompartment(const JSCompartment *c)
 {
     return c == c->rt->atomsCompartment;
 }
 
 JS_FRIEND_API(bool)
-js::IsScopeObject(JSObject *obj)
+js::IsScopeObject(RawObject obj)
 {
     return obj->isScope();
 }
 
 JS_FRIEND_API(JSObject *)
-js::GetObjectParentMaybeScope(JSObject *obj)
+js::GetObjectParentMaybeScope(RawObject obj)
 {
     return obj->enclosingScope();
 }
 
 JS_FRIEND_API(JSObject *)
-js::GetGlobalForObjectCrossCompartment(JSObject *obj)
+js::GetGlobalForObjectCrossCompartment(RawObject obj)
 {
     return &obj->global();
 }
 
 JS_FRIEND_API(void)
-js::NotifyAnimationActivity(JSObject *obj)
+js::NotifyAnimationActivity(RawObject obj)
 {
     obj->compartment()->lastAnimationTime = PRMJ_Now();
 }
 
 JS_FRIEND_API(uint32_t)
-js::GetObjectSlotSpan(JSObject *obj)
+js::GetObjectSlotSpan(RawObject obj)
 {
     return obj->slotSpan();
 }
 
 JS_FRIEND_API(bool)
-js::IsObjectInContextCompartment(const JSObject *obj, const JSContext *cx)
+js::IsObjectInContextCompartment(RawObject obj, const JSContext *cx)
 {
     return obj->compartment() == cx->compartment;
 }
 
 JS_FRIEND_API(bool)
 js::IsOriginalScriptFunction(JSFunction *fun)
 {
     return fun->script()->function() == fun;
 }
 
 JS_FRIEND_API(JSFunction *)
-js::DefineFunctionWithReserved(JSContext *cx, JSObject *obj_, const char *name, JSNative call,
+js::DefineFunctionWithReserved(JSContext *cx, JSObject *objArg, const char *name, JSNative call,
                                unsigned nargs, unsigned attrs)
 {
-    RootedObject obj(cx, obj_);
-
+    RootedObject obj(cx, objArg);
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     JSAtom *atom = js_Atomize(cx, name, strlen(name));
     if (!atom)
         return NULL;
     Rooted<jsid> id(cx, AtomToId(atom));
     return js_DefineFunction(cx, obj, id, call, nargs, attrs, JSFunction::ExtendedFinalizeKind);
 }
 
 JS_FRIEND_API(JSFunction *)
 js::NewFunctionWithReserved(JSContext *cx, JSNative native, unsigned nargs, unsigned flags,
-                            JSObject *parent_, const char *name)
+                            JSObject *parentArg, const char *name)
 {
-    RootedObject parent(cx, parent_);
-
+    RootedObject parent(cx, parentArg);
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     JSAtom *atom;
 
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, parent);
 
     if (!name) {
         atom = NULL;
@@ -385,61 +386,60 @@ js::NewFunctionWithReserved(JSContext *c
             return NULL;
     }
 
     return js_NewFunction(cx, NULL, native, nargs, flags, parent, atom,
                           JSFunction::ExtendedFinalizeKind);
 }
 
 JS_FRIEND_API(JSFunction *)
-js::NewFunctionByIdWithReserved(JSContext *cx, JSNative native, unsigned nargs, unsigned flags, JSObject *parent_,
+js::NewFunctionByIdWithReserved(JSContext *cx, JSNative native, unsigned nargs, unsigned flags, JSObject *parentArg,
                                 jsid id)
 {
-    RootedObject parent(cx, parent_);
-
+    RootedObject parent(cx, parentArg);
     JS_ASSERT(JSID_IS_STRING(id));
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, parent);
 
     return js_NewFunction(cx, NULL, native, nargs, flags, parent, JSID_TO_ATOM(id),
                           JSFunction::ExtendedFinalizeKind);
 }
 
 JS_FRIEND_API(JSObject *)
-js::InitClassWithReserved(JSContext *cx, JSObject *obj_, JSObject *parent_proto,
+js::InitClassWithReserved(JSContext *cx, JSObject *objArg, JSObject *parent_protoArg,
                           JSClass *clasp, JSNative constructor, unsigned nargs,
                           JSPropertySpec *ps, JSFunctionSpec *fs,
                           JSPropertySpec *static_ps, JSFunctionSpec *static_fs)
 {
-    RootedObject obj(cx, obj_);
-
+    RootedObject obj(cx, objArg);
+    RootedObject parent_proto(cx, parent_protoArg);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, parent_proto);
     return js_InitClass(cx, obj, parent_proto, Valueify(clasp), constructor,
                         nargs, ps, fs, static_ps, static_fs, NULL,
                         JSFunction::ExtendedFinalizeKind);
 }
 
 JS_FRIEND_API(const Value &)
-js::GetFunctionNativeReserved(JSObject *fun, size_t which)
+js::GetFunctionNativeReserved(RawObject fun, size_t which)
 {
     JS_ASSERT(fun->toFunction()->isNative());
     return fun->toFunction()->getExtendedSlot(which);
 }
 
 JS_FRIEND_API(void)
-js::SetFunctionNativeReserved(JSObject *fun, size_t which, const Value &val)
+js::SetFunctionNativeReserved(RawObject fun, size_t which, const Value &val)
 {
     JS_ASSERT(fun->toFunction()->isNative());
     fun->toFunction()->setExtendedSlot(which, val);
 }
 
 JS_FRIEND_API(void)
-js::SetReservedSlotWithBarrier(JSObject *obj, size_t slot, const js::Value &value)
+js::SetReservedSlotWithBarrier(RawObject obj, size_t slot, const js::Value &value)
 {
     obj->setSlot(slot, value);
 }
 
 JS_FRIEND_API(bool)
 js::GetGeneric(JSContext *cx, JSObject *obj, JSObject *receiver_, jsid id_,
                Value *vp)
 {
@@ -839,17 +839,17 @@ IsIncrementalBarrierNeeded(JSRuntime *rt
 
 JS_FRIEND_API(bool)
 IsIncrementalBarrierNeeded(JSContext *cx)
 {
     return IsIncrementalBarrierNeeded(cx->runtime);
 }
 
 JS_FRIEND_API(bool)
-IsIncrementalBarrierNeededOnObject(JSObject *obj)
+IsIncrementalBarrierNeededOnObject(RawObject obj)
 {
     return obj->compartment()->needsBarrier();
 }
 
 JS_FRIEND_API(bool)
 IsIncrementalBarrierNeededOnScript(JSScript *script)
 {
     return script->compartment()->needsBarrier();
@@ -888,17 +888,17 @@ extern JS_FRIEND_API(void)
 PokeGC(JSRuntime *rt)
 {
     rt->gcPoke = true;
 }
 
 JS_FRIEND_API(JSObject *)
 GetTestingFunctions(JSContext *cx)
 {
-    JSObject *obj = JS_NewObject(cx, NULL, NULL, NULL);
+    RootedObject obj(cx, JS_NewObject(cx, NULL, NULL, NULL));
     if (!obj)
         return NULL;
 
     if (!DefineTestingFunctions(cx, obj))
         return NULL;
 
     return obj;
 }
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -23,32 +23,32 @@ JS_BEGIN_EXTERN_C
 
 extern JS_FRIEND_API(void)
 JS_SetGrayGCRootsTracer(JSRuntime *rt, JSTraceDataOp traceOp, void *data);
 
 extern JS_FRIEND_API(JSString *)
 JS_GetAnonymousString(JSRuntime *rt);
 
 extern JS_FRIEND_API(JSObject *)
-JS_FindCompilationScope(JSContext *cx, JSObject *obj);
+JS_FindCompilationScope(JSContext *cx, JSRawObject obj);
 
 extern JS_FRIEND_API(JSFunction *)
-JS_GetObjectFunction(JSObject *obj);
+JS_GetObjectFunction(JSRawObject obj);
 
 extern JS_FRIEND_API(JSObject *)
 JS_GetGlobalForFrame(JSStackFrame *fp);
 
 extern JS_FRIEND_API(JSBool)
 JS_SplicePrototype(JSContext *cx, JSObject *obj, JSObject *proto);
 
 extern JS_FRIEND_API(JSObject *)
 JS_NewObjectWithUniqueType(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent);
 
 extern JS_FRIEND_API(uint32_t)
-JS_ObjectCountDynamicSlots(JSObject *obj);
+JS_ObjectCountDynamicSlots(JSHandleObject obj);
 
 extern JS_FRIEND_API(void)
 JS_ShrinkGCBuffers(JSRuntime *rt);
 
 extern JS_FRIEND_API(size_t)
 JS_GetE4XObjectsCreated(JSContext *cx);
 
 extern JS_FRIEND_API(size_t)
@@ -219,17 +219,17 @@ DumpHeapComplete(JSRuntime *rt, FILE *fp
 
 class JS_FRIEND_API(AutoSwitchCompartment) {
   private:
     JSContext *cx;
     JSCompartment *oldCompartment;
   public:
     AutoSwitchCompartment(JSContext *cx, JSCompartment *newCompartment
                           JS_GUARD_OBJECT_NOTIFIER_PARAM);
-    AutoSwitchCompartment(JSContext *cx, JSObject *target JS_GUARD_OBJECT_NOTIFIER_PARAM);
+    AutoSwitchCompartment(JSContext *cx, JSHandleObject target JS_GUARD_OBJECT_NOTIFIER_PARAM);
     ~AutoSwitchCompartment();
     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
 #ifdef OLD_GETTER_SETTER_METHODS
 JS_FRIEND_API(JSBool) obj_defineGetter(JSContext *cx, unsigned argc, js::Value *vp);
 JS_FRIEND_API(JSBool) obj_defineSetter(JSContext *cx, unsigned argc, js::Value *vp);
 #endif
@@ -345,45 +345,45 @@ extern JS_FRIEND_DATA(js::Class) Functio
 extern JS_FRIEND_DATA(js::Class) NamespaceClass;
 extern JS_FRIEND_DATA(js::Class) OuterWindowProxyClass;
 extern JS_FRIEND_DATA(js::Class) ObjectProxyClass;
 extern JS_FRIEND_DATA(js::Class) QNameClass;
 extern JS_FRIEND_DATA(js::Class) XMLClass;
 extern JS_FRIEND_DATA(js::Class) ObjectClass;
 
 inline js::Class *
-GetObjectClass(const JSObject *obj)
+GetObjectClass(RawObject obj)
 {
     return reinterpret_cast<const shadow::Object*>(obj)->shape->base->clasp;
 }
 
 inline JSClass *
-GetObjectJSClass(const JSObject *obj)
+GetObjectJSClass(RawObject obj)
 {
     return js::Jsvalify(GetObjectClass(obj));
 }
 
 JS_FRIEND_API(bool)
-IsScopeObject(JSObject *obj);
+IsScopeObject(RawObject obj);
 
 inline JSObject *
-GetObjectParent(JSObject *obj)
+GetObjectParent(RawObject obj)
 {
     JS_ASSERT(!IsScopeObject(obj));
     return reinterpret_cast<shadow::Object*>(obj)->shape->base->parent;
 }
 
 JS_FRIEND_API(JSObject *)
-GetObjectParentMaybeScope(JSObject *obj);
+GetObjectParentMaybeScope(RawObject obj);
 
 JS_FRIEND_API(JSObject *)
-GetGlobalForObjectCrossCompartment(JSObject *obj);
+GetGlobalForObjectCrossCompartment(RawObject obj);
 
 JS_FRIEND_API(void)
-NotifyAnimationActivity(JSObject *obj);
+NotifyAnimationActivity(RawObject obj);
 
 JS_FRIEND_API(bool)
 IsOriginalScriptFunction(JSFunction *fun);
 
 JS_FRIEND_API(JSFunction *)
 DefineFunctionWithReserved(JSContext *cx, JSObject *obj, const char *name, JSNative call,
                            unsigned nargs, unsigned attrs);
 
@@ -397,72 +397,72 @@ NewFunctionByIdWithReserved(JSContext *c
 
 JS_FRIEND_API(JSObject *)
 InitClassWithReserved(JSContext *cx, JSObject *obj, JSObject *parent_proto,
                       JSClass *clasp, JSNative constructor, unsigned nargs,
                       JSPropertySpec *ps, JSFunctionSpec *fs,
                       JSPropertySpec *static_ps, JSFunctionSpec *static_fs);
 
 JS_FRIEND_API(const Value &)
-GetFunctionNativeReserved(JSObject *fun, size_t which);
+GetFunctionNativeReserved(RawObject fun, size_t which);
 
 JS_FRIEND_API(void)
-SetFunctionNativeReserved(JSObject *fun, size_t which, const Value &val);
+SetFunctionNativeReserved(RawObject fun, size_t which, const Value &val);
 
 inline JSObject *
-GetObjectProto(JSObject *obj)
+GetObjectProto(RawObject obj)
 {
     return reinterpret_cast<const shadow::Object*>(obj)->type->proto;
 }
 
 inline void *
-GetObjectPrivate(JSObject *obj)
+GetObjectPrivate(RawObject obj)
 {
     const shadow::Object *nobj = reinterpret_cast<const shadow::Object*>(obj);
     void **addr = reinterpret_cast<void**>(&nobj->fixedSlots()[nobj->numFixedSlots()]);
     return *addr;
 }
 
 /*
  * Get a slot that is both reserved for object's clasp *and* is fixed (fits
  * within the maximum capacity for the object's fixed slots).
  */
 inline const Value &
-GetReservedSlot(const JSObject *obj, size_t slot)
+GetReservedSlot(RawObject obj, size_t slot)
 {
     JS_ASSERT(slot < JSCLASS_RESERVED_SLOTS(GetObjectClass(obj)));
     return reinterpret_cast<const shadow::Object *>(obj)->slotRef(slot);
 }
 
 JS_FRIEND_API(void)
-SetReservedSlotWithBarrier(JSObject *obj, size_t slot, const Value &value);
+SetReservedSlotWithBarrier(RawObject obj, size_t slot, const Value &value);
 
 inline void
-SetReservedSlot(JSObject *obj, size_t slot, const Value &value)
+SetReservedSlot(RawObject obj, size_t slot, const Value &value)
 {
     JS_ASSERT(slot < JSCLASS_RESERVED_SLOTS(GetObjectClass(obj)));
     shadow::Object *sobj = reinterpret_cast<shadow::Object *>(obj);
     if (sobj->slotRef(slot).isMarkable())
         SetReservedSlotWithBarrier(obj, slot, value);
     else
         sobj->slotRef(slot) = value;
 }
 
 JS_FRIEND_API(uint32_t)
-GetObjectSlotSpan(JSObject *obj);
+GetObjectSlotSpan(RawObject obj);
 
 inline const Value &
-GetObjectSlot(JSObject *obj, size_t slot)
+GetObjectSlot(RawObject obj, size_t slot)
 {
     JS_ASSERT(slot < GetObjectSlotSpan(obj));
     return reinterpret_cast<const shadow::Object *>(obj)->slotRef(slot);
 }
 
 inline Shape *
-GetObjectShape(JSObject *obj)
+GetObjectShape(RawObject obj)
 {
     shadow::Shape *shape = reinterpret_cast<const shadow::Object*>(obj)->shape;
     return reinterpret_cast<Shape *>(shape);
 }
 
 inline const jschar *
 GetAtomChars(JSAtom *atom)
 {
@@ -471,41 +471,41 @@ GetAtomChars(JSAtom *atom)
 
 inline JSLinearString *
 AtomToLinearString(JSAtom *atom)
 {
     return reinterpret_cast<JSLinearString *>(atom);
 }
 
 static inline js::PropertyOp
-CastAsJSPropertyOp(JSObject *object)
+CastAsJSPropertyOp(RawObject object)
 {
     return JS_DATA_TO_FUNC_PTR(js::PropertyOp, object);
 }
 
 static inline js::StrictPropertyOp
-CastAsJSStrictPropertyOp(JSObject *object)
+CastAsJSStrictPropertyOp(RawObject object)
 {
     return JS_DATA_TO_FUNC_PTR(js::StrictPropertyOp, object);
 }
 
 JS_FRIEND_API(bool)
-GetPropertyNames(JSContext *cx, JSObject *obj, unsigned flags, js::AutoIdVector *props);
+GetPropertyNames(JSContext *cx, RawObject obj, unsigned flags, js::AutoIdVector *props);
 
 JS_FRIEND_API(bool)
 GetGeneric(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp);
 
 JS_FRIEND_API(bool)
 StringIsArrayIndex(JSLinearString *str, uint32_t *indexp);
 
 JS_FRIEND_API(void)
 SetPreserveWrapperCallback(JSRuntime *rt, PreserveWrapperCallback callback);
 
 JS_FRIEND_API(bool)
-IsObjectInContextCompartment(const JSObject *obj, const JSContext *cx);
+IsObjectInContextCompartment(RawObject obj, const JSContext *cx);
 
 /*
  * NB: these flag bits are encoded into the bytecode stream in the immediate
  * operand of JSOP_ITER, so don't change them without advancing vm/Xdr.h's
  * XDR_BYTECODE_VERSION.
  */
 #define JSITER_ENUMERATE  0x1   /* for-in compatible hidden default iterator */
 #define JSITER_FOREACH    0x2   /* return [key, value] pair rather than key */
@@ -760,17 +760,17 @@ DisableIncrementalGC(JSRuntime *rt);
 
 extern JS_FRIEND_API(bool)
 IsIncrementalBarrierNeeded(JSRuntime *rt);
 
 extern JS_FRIEND_API(bool)
 IsIncrementalBarrierNeeded(JSContext *cx);
 
 extern JS_FRIEND_API(bool)
-IsIncrementalBarrierNeededOnObject(JSObject *obj);
+IsIncrementalBarrierNeededOnObject(RawObject obj);
 
 extern JS_FRIEND_API(bool)
 IsIncrementalBarrierNeededOnScript(JSScript *obj);
 
 extern JS_FRIEND_API(void)
 IncrementalReferenceBarrier(void *ptr);
 
 extern JS_FRIEND_API(void)
@@ -840,18 +840,20 @@ extern JS_FRIEND_API(const jschar*)
 GetErrorTypeName(JSContext* cx, int16_t exnType);
 
 /* Implemented in jswrapper.cpp. */
 typedef enum NukeReferencesToWindow {
     NukeWindowReferences,
     DontNukeWindowReferences
 } NukeReferencesToWindow;
 
-// These filters are designed to be ephemeral stack classes, and thus don't
-// do any rooting or holding of their members.
+/*
+ * These filters are designed to be ephemeral stack classes, and thus don't
+ * do any rooting or holding of their members.
+ */
 struct CompartmentFilter {
     virtual bool match(JSCompartment *c) const = 0;
 };
 
 struct AllCompartments : public CompartmentFilter {
     virtual bool match(JSCompartment *c) const { return true; }
 };
 
@@ -896,17 +898,17 @@ NukeCrossCompartmentWrappers(JSContext* 
 /*
  * Detect whether the internal date value is NaN.  (Because failure is
  * out-of-band for js_DateGet*)
  */
 extern JS_FRIEND_API(JSBool)
 js_DateIsValid(JSContext *cx, JSObject* obj);
 
 extern JS_FRIEND_API(double)
-js_DateGetMsecSinceEpoch(JSContext *cx, JSObject *obj);
+js_DateGetMsecSinceEpoch(JSContext *cx, JSRawObject obj);
 
 /* Implemented in jscntxt.cpp. */
 
 /*
  * Report an exception, which is currently realized as a printf-style format
  * string and its arguments.
  */
 typedef enum JSErrNum {
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -337,30 +337,30 @@ fun_resolve(JSContext *cx, HandleObject 
     }
 
     return true;
 }
 
 template<XDRMode mode>
 bool
 js::XDRInterpretedFunction(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enclosingScript,
-                           JSObject **objp)
+                           MutableHandleObject objp)
 {
     /* NB: Keep this in sync with CloneInterpretedFunction. */
-    JSAtom *atom;
+    Rooted<JSAtom*> atom(xdr->cx());
     uint32_t firstword;           /* flag telling whether fun->atom is non-null,
                                    plus for fun->u.i.skipmin, fun->u.i.wrapper,
                                    and 14 bits reserved for future use */
     uint32_t flagsword;           /* word for argument count and fun->flags */
 
     JSContext *cx = xdr->cx();
     RootedFunction fun(cx);
     JSScript *script;
     if (mode == XDR_ENCODE) {
-        fun = (*objp)->toFunction();
+        fun = objp->toFunction();
         if (!fun->isInterpreted()) {
             JSAutoByteString funNameBytes;
             if (const char *name = GetFunctionNameBytes(cx, fun, &funNameBytes)) {
                 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_SCRIPTED_FUNCTION,
                                      name);
             }
             return false;
         }
@@ -378,17 +378,17 @@ js::XDRInterpretedFunction(XDRState<mode
         if (!JSObject::clearType(cx, fun))
             return false;
         atom = NULL;
         script = NULL;
     }
 
     if (!xdr->codeUint32(&firstword))
         return false;
-    if ((firstword & 1U) && !XDRAtom(xdr, &atom))
+    if ((firstword & 1U) && !XDRAtom(xdr, atom.address()))
         return false;
     if (!xdr->codeUint32(&flagsword))
         return false;
 
     if (!XDRScript(xdr, enclosingScope, enclosingScript, fun, &script))
         return false;
 
     if (mode == XDR_DECODE) {
@@ -396,27 +396,27 @@ js::XDRInterpretedFunction(XDRState<mode
         fun->flags = uint16_t(flagsword);
         fun->atom.init(atom);
         fun->initScript(script);
         script->setFunction(fun);
         if (!fun->setTypeForScriptedFunction(cx))
             return false;
         JS_ASSERT(fun->nargs == fun->script()->bindings.numArgs());
         js_CallNewScriptHook(cx, fun->script(), fun);
-        *objp = fun;
+        objp.set(fun);
     }
 
     return true;
 }
 
 template bool
-js::XDRInterpretedFunction(XDRState<XDR_ENCODE> *, HandleObject, HandleScript, JSObject **);
+js::XDRInterpretedFunction(XDRState<XDR_ENCODE> *, HandleObject, HandleScript, MutableHandleObject);
 
 template bool
-js::XDRInterpretedFunction(XDRState<XDR_DECODE> *, HandleObject, HandleScript, JSObject **);
+js::XDRInterpretedFunction(XDRState<XDR_DECODE> *, HandleObject, HandleScript, MutableHandleObject);
 
 JSObject *
 js::CloneInterpretedFunction(JSContext *cx, HandleObject enclosingScope, HandleFunction srcFun)
 {
     /* NB: Keep this in sync with XDRInterpretedFunction. */
 
     RootedObject parent(cx, NULL);
     RootedFunction clone(cx, js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, parent, NULL));
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -246,17 +246,17 @@ JSFunction::toExtended() const
 
 namespace js {
 
 JSString *FunctionToString(JSContext *cx, HandleFunction fun, bool bodyOnly, bool lambdaParen);
 
 template<XDRMode mode>
 bool
 XDRInterpretedFunction(XDRState<mode> *xdr, HandleObject enclosingScope,
-                       HandleScript enclosingScript, JSObject **objp);
+                       HandleScript enclosingScript, MutableHandleObject objp);
 
 extern JSObject *
 CloneInterpretedFunction(JSContext *cx, HandleObject enclosingScope, HandleFunction fun);
 
 /*
  * Report an error that call.thisv is not compatible with the specified class,
  * assuming that the method (clasp->name).prototype.<name of callee function>
  * is what was called.
--- a/js/src/jsinferinlines.h
+++ b/js/src/jsinferinlines.h
@@ -1532,18 +1532,17 @@ JSScript::ensureHasTypes(JSContext *cx)
 {
     return types || makeTypes(cx);
 }
 
 inline bool
 JSScript::ensureRanAnalysis(JSContext *cx)
 {
     js::analyze::AutoEnterAnalysis aea(cx->compartment);
-    JSScript *self = this;
-    JS::SkipRoot root(cx, &self);
+    js::RootedScript self(cx, this);
 
     if (!self->ensureHasTypes(cx))
         return false;
     if (!self->hasAnalysis() && !self->makeAnalysis(cx))
         return false;
     JS_ASSERT(self->analysis()->ranBytecode());
     return true;
 }
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -457,24 +457,22 @@ js::InvokeGetterOrSetter(JSContext *cx, 
      * bug 355497.
      */
     JS_CHECK_RECURSION(cx, return false);
 
     return Invoke(cx, ObjectValue(*obj), fval, argc, argv, rval);
 }
 
 bool
-js::ExecuteKernel(JSContext *cx, JSScript *script_, JSObject &scopeChain, const Value &thisv,
+js::ExecuteKernel(JSContext *cx, HandleScript script, JSObject &scopeChain, const Value &thisv,
                   ExecuteType type, StackFrame *evalInFrame, Value *result)
 {
     JS_ASSERT_IF(evalInFrame, type == EXECUTE_DEBUG);
     JS_ASSERT_IF(type == EXECUTE_GLOBAL, !scopeChain.isScope());
 
-    JS::Rooted<JSScript*> script(cx, script_);
-
     if (script->isEmpty()) {
         if (result)
             result->setUndefined();
         return true;
     }
 
     ExecuteFrameGuard efg;
     if (!cx->stack.pushExecuteFrame(cx, script, thisv, scopeChain, type, evalInFrame, &efg))
@@ -490,17 +488,17 @@ js::ExecuteKernel(JSContext *cx, JSScrip
 
     /* Propgate the return value out. */
     if (result)
         *result = efg.fp()->returnValue();
     return ok;
 }
 
 bool
-js::Execute(JSContext *cx, JSScript *script, JSObject &scopeChainArg, Value *rval)
+js::Execute(JSContext *cx, HandleScript script, JSObject &scopeChainArg, Value *rval)
 {
     /* The scope chain could be anything, so innerize just in case. */
     RootedObject scopeChain(cx, &scopeChainArg);
     scopeChain = GetInnerObject(cx, scopeChain);
     if (!scopeChain)
         return false;
 
     /* If we were handed a non-native object, complain bitterly. */
--- a/js/src/jsinterp.h
+++ b/js/src/jsinterp.h
@@ -161,22 +161,22 @@ InvokeConstructor(JSContext *cx, const V
 
 /*
  * Executes a script with the given scopeChain/this. The 'type' indicates
  * whether this is eval code or global code. To support debugging, the
  * evalFrame parameter can point to an arbitrary frame in the context's call
  * stack to simulate executing an eval in that frame.
  */
 extern bool
-ExecuteKernel(JSContext *cx, JSScript *script, JSObject &scopeChain, const Value &thisv,
+ExecuteKernel(JSContext *cx, HandleScript script, JSObject &scopeChain, const Value &thisv,
               ExecuteType type, StackFrame *evalInFrame, Value *result);
 
 /* Execute a script with the given scopeChain as global code. */
 extern bool
-Execute(JSContext *cx, JSScript *script, JSObject &scopeChain, Value *rval);
+Execute(JSContext *cx, HandleScript script, JSObject &scopeChain, Value *rval);
 
 /* Flags to toggle js::Interpret() execution. */
 enum InterpMode
 {
     JSINTERP_NORMAL    = 0, /* interpreter is running normally */
     JSINTERP_REJOIN    = 1, /* as normal, but the frame has already started */
     JSINTERP_SKIP_TRAP = 2  /* as REJOIN, but skip trap at first opcode */
 };
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -200,17 +200,17 @@ struct SortComparatorIds
         *lessOrEqualp = (result <= 0);
         return true;
     }
 };
 
 #endif /* JS_MORE_DETERMINISTIC */
 
 static bool
-Snapshot(JSContext *cx, JSObject *obj_, unsigned flags, AutoIdVector *props)
+Snapshot(JSContext *cx, RawObject obj_, unsigned flags, AutoIdVector *props)
 {
     IdSet ht(cx);
     if (!ht.init(32))
         return false;
 
     RootedObject obj(cx, obj_), pobj(cx);
     pobj = obj;
 
@@ -965,17 +965,17 @@ js::ValueToIterator(JSContext *cx, unsig
         /*
          * Enumerating over null and undefined gives an empty enumerator.
          * This is contrary to ECMA-262 9.9 ToObject, invoked from step 3 of
          * the first production in 12.6.4 and step 4 of the second production,
          * but it's "web JS" compatible. ES5 fixed for-in to match this de-facto
          * standard.
          */
         if (flags & JSITER_ENUMERATE) {
-            if (!js_ValueToObjectOrNull(cx, vp, obj.address()))
+            if (!js_ValueToObjectOrNull(cx, vp, &obj))
                 return false;
             /* fall through */
         } else {
             obj = js_ValueToNonNullObject(cx, vp);
             if (!obj)
                 return false;
         }
     }
--- a/js/src/jsmath.cpp
+++ b/js/src/jsmath.cpp
@@ -660,17 +660,16 @@ static JSFunctionSpec math_static_method
     JS_FN("tan",            math_tan,             1, 0),
     JS_FS_END
 };
 
 JSObject *
 js_InitMathClass(JSContext *cx, JSObject *obj_)
 {
     RootedObject obj(cx, obj_);
-
     RootedObject Math(cx, NewObjectWithClassProto(cx, &MathClass, NULL, obj));
     if (!Math || !Math->setSingletonType(cx))
         return NULL;
 
     if (!JS_DefineProperty(cx, obj, js_Math_str, OBJECT_TO_JSVAL(Math),
                            JS_PropertyStub, JS_StrictPropertyStub, 0)) {
         return NULL;
     }
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -82,23 +82,23 @@ Class js::ObjectClass = {
     JS_PropertyStub,         /* getProperty */
     JS_StrictPropertyStub,   /* setProperty */
     JS_EnumerateStub,
     JS_ResolveStub,
     JS_ConvertStub
 };
 
 JS_FRIEND_API(JSObject *)
-JS_ObjectToInnerObject(JSContext *cx, JSObject *obj_)
-{
-    if (!obj_) {
+JS_ObjectToInnerObject(JSContext *cx, JSObject *objArg)
+{
+    RootedObject obj(cx, objArg);
+    if (!obj) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INACTIVE);
         return NULL;
     }
-    Rooted<JSObject*> obj(cx, obj_);
     return GetInnerObject(cx, obj);
 }
 
 JS_FRIEND_API(JSObject *)
 JS_ObjectToOuterObject(JSContext *cx, JSObject *obj_)
 {
     Rooted<JSObject*> obj(cx, obj_);
     return GetOuterObject(cx, obj);
@@ -2286,17 +2286,17 @@ JSBool
 js_Object(JSContext *cx, unsigned argc, Value *vp)
 {
     RootedObject obj(cx);
     if (argc == 0) {
         /* Trigger logic below to construct a blank object. */
         obj = NULL;
     } else {
         /* If argv[0] is null or undefined, obj comes back null. */
-        if (!js_ValueToObjectOrNull(cx, vp[2], obj.address()))
+        if (!js_ValueToObjectOrNull(cx, vp[2], &obj))
             return JS_FALSE;
     }
     if (!obj) {
         /* Make an object whether this was called with 'new' or not. */
         JS_ASSERT(!argc || vp[2].isNull() || vp[2].isUndefined());
         gc::AllocKind kind = NewObjectGCKind(cx, &ObjectClass);
         obj = NewBuiltinClassInstance(cx, &ObjectClass, kind);
         if (!obj)
@@ -3795,17 +3795,17 @@ SetProto(JSContext *cx, HandleObject obj
 
     obj->setType(type);
     return true;
 }
 
 }
 
 bool
-js_GetClassObject(JSContext *cx, HandleObject obj, JSProtoKey key,
+js_GetClassObject(JSContext *cx, RawObject obj, JSProtoKey key,
                   MutableHandleObject objp)
 {
 
     RootedObject global(cx, &obj->global());
     if (!global->isGlobal()) {
         objp.set(NULL);
         return true;
     }
@@ -5463,30 +5463,30 @@ js_PrimitiveToObject(JSContext *cx, Valu
     if (!obj)
         return false;
 
     vp->setObject(*obj);
     return true;
 }
 
 JSBool
-js_ValueToObjectOrNull(JSContext *cx, const Value &v, JSObject **objp)
+js_ValueToObjectOrNull(JSContext *cx, const Value &v, MutableHandleObject objp)
 {
     JSObject *obj;
 
     if (v.isObjectOrNull()) {
         obj = v.toObjectOrNull();
     } else if (v.isUndefined()) {
         obj = NULL;
     } else {
         obj = PrimitiveToObject(cx, v);
         if (!obj)
             return false;
     }
-    *objp = obj;
+    objp.set(obj);
     return true;
 }
 
 namespace js {
 
 /* Callers must handle the already-object case . */
 JSObject *
 ToObjectSlow(JSContext *cx, Value *vp)
@@ -5506,17 +5506,17 @@ ToObjectSlow(JSContext *cx, Value *vp)
     return obj;
 }
 
 }
 
 JSObject *
 js_ValueToNonNullObject(JSContext *cx, const Value &v)
 {
-    JSObject *obj;
+    RootedObject obj(cx);
 
     if (!js_ValueToObjectOrNull(cx, v, &obj))
         return NULL;
     if (!obj)
         js_ReportIsNullOrUndefined(cx, JSDVG_SEARCH_STACK, v, NULL);
     return obj;
 }
 
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -1103,17 +1103,17 @@ extern const char js_lookupSetter_str[];
 
 extern JSBool
 js_PopulateObject(JSContext *cx, js::HandleObject newborn, js::HandleObject props);
 
 /*
  * Fast access to immutable standard objects (constructors and prototypes).
  */
 extern bool
-js_GetClassObject(JSContext *cx, js::HandleObject obj, JSProtoKey key,
+js_GetClassObject(JSContext *cx, js::RawObject obj, JSProtoKey key,
                   js::MutableHandleObject objp);
 
 /*
  * Determine if the given object is a prototype for a standard class. If so,
  * return the associated JSProtoKey. If not, return JSProto_Null.
  */
 extern JSProtoKey
 js_IdentifyClassPrototype(JSObject *obj);
@@ -1321,17 +1321,17 @@ js_IsDelegate(JSContext *cx, JSObject *o
 /*
  * Wrap boolean, number or string as Boolean, Number or String object.
  * *vp must not be an object, null or undefined.
  */
 extern JSBool
 js_PrimitiveToObject(JSContext *cx, js::Value *vp);
 
 extern JSBool
-js_ValueToObjectOrNull(JSContext *cx, const js::Value &v, JSObject **objp);
+js_ValueToObjectOrNull(JSContext *cx, const js::Value &v, JS::MutableHandleObject objp);
 
 /* Throws if v could not be converted to an object. */
 extern JSObject *
 js_ValueToNonNullObject(JSContext *cx, const js::Value &v);
 
 namespace js {
 
 /*
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -804,18 +804,18 @@ inline bool JSObject::isStrictArguments(
 inline bool JSObject::isString() const { return hasClass(&js::StringClass); }
 inline bool JSObject::isTypedArray() const { return IsTypedArrayClass(getClass()); }
 inline bool JSObject::isWeakMap() const { return hasClass(&js::WeakMapClass); }
 inline bool JSObject::isWith() const { return hasClass(&js::WithClass); }
 
 inline bool
 JSObject::isDebugScope() const
 {
-    extern bool js_IsDebugScopeSlow(const JSObject *obj);
-    return getClass() == &js::ObjectProxyClass && js_IsDebugScopeSlow(this);
+    extern bool js_IsDebugScopeSlow(JS::RawObject obj);
+    return getClass() == &js::ObjectProxyClass && js_IsDebugScopeSlow(const_cast<JSObject*>(this));
 }
 
 #if JS_HAS_XML_SUPPORT
 inline bool JSObject::isNamespace() const { return hasClass(&js::NamespaceClass); }
 inline bool JSObject::isXML() const { return hasClass(&js::XMLClass); }
 
 inline bool
 JSObject::isXMLId() const
@@ -1209,29 +1209,29 @@ JSObject::getSpecialAttributes(JSContext
 {
     js::Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
     return getGenericAttributes(cx, id, attrsp);
 }
 
 inline bool
 JSObject::isProxy() const
 {
-    return js::IsProxy(this);
+    return js::IsProxy(const_cast<JSObject*>(this));
 }
 
 inline bool
 JSObject::isCrossCompartmentWrapper() const
 {
-    return js::IsCrossCompartmentWrapper(this);
+    return js::IsCrossCompartmentWrapper(const_cast<JSObject*>(this));
 }
 
 inline bool
 JSObject::isWrapper() const
 {
-    return js::IsWrapper(this);
+    return js::IsWrapper(const_cast<JSObject*>(this));
 }
 
 inline js::GlobalObject &
 JSObject::global() const
 {
     JSObject *obj = const_cast<JSObject *>(this);
     while (JSObject *parent = obj->getParent())
         obj = parent;
--- a/js/src/json.cpp
+++ b/js/src/json.cpp
@@ -897,19 +897,19 @@ static JSFunctionSpec json_static_method
     JS_FN(js_toSource_str,  json_toSource,      0, 0),
 #endif
     JS_FN("parse",          js_json_parse,      2, 0),
     JS_FN("stringify",      js_json_stringify,  3, 0),
     JS_FS_END
 };
 
 JSObject *
-js_InitJSONClass(JSContext *cx, JSObject *obj_)
+js_InitJSONClass(JSContext *cx, JSObject *obj)
 {
-    Rooted<GlobalObject*> global(cx, &obj_->asGlobal());
+    Rooted<GlobalObject*> global(cx, &obj->asGlobal());
 
     /*
      * JSON requires that Boolean.prototype.valueOf be created and stashed in a
      * reserved slot on the global object; see js::BooleanGetPrimitiveValueSlow
      * called from PreprocessValue above.
      */
     if (!global->getOrCreateBooleanPrototype(cx))
         return NULL;
--- a/js/src/json.h
+++ b/js/src/json.h
@@ -2,28 +2,29 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef json_h___
 #define json_h___
 
 #include "jsprvtd.h"
 #include "jspubtd.h"
+#include "jsapi.h"
 
 #include "js/Vector.h"
 
 #define JSON_MAX_DEPTH  2048
 #define JSON_PARSER_BUFSIZE 1024
 
 extern JSObject *
 js_InitJSONClass(JSContext *cx, JSObject *obj);
 
 extern JSBool
 js_Stringify(JSContext *cx, js::MutableHandleValue vp,
-	     JSObject *replacer, js::Value space, 
+             JSObject *replacer, js::Value space,
              js::StringBuffer &sb);
 
 // Avoid build errors on certain platforms that define these names as constants
 #undef STRICT
 #undef LEGACY
 
 /*
  * The type of JSON decoding to perform.  Strict decoding is to-the-spec;
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -6382,17 +6382,18 @@ GetPCCountScriptContents(JSContext *cx, 
 
     StringBuffer buf(cx);
 
     if (!script->function() && !script->compileAndGo)
         return buf.finishString();
 
     {
         JSAutoEnterCompartment ac;
-        if (!ac.enter(cx, &script->global()))
+        RootedObject target(cx, &script->global());
+        if (!ac.enter(cx, target))
             return NULL;
 
         if (!GetPCCountJSON(cx, sac, buf))
             return NULL;
     }
 
     return buf.finishString();
 }
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -378,18 +378,18 @@ IndirectProxyHandler::IndirectProxyHandl
 {
 }
 
 bool
 IndirectProxyHandler::getPropertyDescriptor(JSContext *cx, JSObject *proxy,
                                             jsid id, bool set,
                                             PropertyDescriptor *desc)
 {
-    return JS_GetPropertyDescriptorById(cx, GetProxyTargetObject(proxy), id,
-                                        JSRESOLVE_QUALIFIED, desc);
+    RootedObject target(cx, GetProxyTargetObject(proxy));
+    return JS_GetPropertyDescriptorById(cx, target, id, JSRESOLVE_QUALIFIED, desc);
 }
 
 static bool
 GetOwnPropertyDescriptor(JSContext *cx, HandleObject obj, jsid id, unsigned flags,
                          JSPropertyDescriptor *desc)
 {
     // If obj is a proxy, we can do better than just guessing. This is
     // important for certain types of wrappers that wrap other wrappers.
@@ -406,18 +406,17 @@ GetOwnPropertyDescriptor(JSContext *cx, 
 }
 
 bool
 IndirectProxyHandler::getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy,
                                                jsid id, bool set,
                                                PropertyDescriptor *desc)
 {
     RootedObject target(cx, GetProxyTargetObject(proxy));
-    return GetOwnPropertyDescriptor(cx, target, id,
-                                    JSRESOLVE_QUALIFIED, desc);
+    return GetOwnPropertyDescriptor(cx, target, id, JSRESOLVE_QUALIFIED, desc);
 }
 
 bool
 IndirectProxyHandler::defineProperty(JSContext *cx, JSObject *proxy, jsid id_,
                                      PropertyDescriptor *desc)
 {
     RootedObject obj(cx, GetProxyTargetObject(proxy));
     Rooted<jsid> id(cx, id_);
@@ -425,38 +424,40 @@ IndirectProxyHandler::defineProperty(JSC
     return CheckDefineProperty(cx, obj, id, v, desc->getter, desc->setter, desc->attrs) &&
            JS_DefinePropertyById(cx, obj, id, v, desc->getter, desc->setter, desc->attrs);
 }
 
 bool
 IndirectProxyHandler::getOwnPropertyNames(JSContext *cx, JSObject *proxy,
                                           AutoIdVector &props)
 {
-    return GetPropertyNames(cx, GetProxyTargetObject(proxy),
-                            JSITER_OWNONLY | JSITER_HIDDEN, &props);
+    RootedObject target(cx, GetProxyTargetObject(proxy));
+    return GetPropertyNames(cx, target, JSITER_OWNONLY | JSITER_HIDDEN, &props);
 }
 
 bool
 IndirectProxyHandler::delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
 {
     Value v;
-    if (!JS_DeletePropertyById2(cx, GetProxyTargetObject(proxy), id, &v))
+    RootedObject target(cx, GetProxyTargetObject(proxy));
+    if (!JS_DeletePropertyById2(cx, target, id, &v))
         return false;
     JSBool b;
     if (!JS_ValueToBoolean(cx, v, &b))
         return false;
     *bp = !!b;
     return true;
 }
 
 bool
 IndirectProxyHandler::enumerate(JSContext *cx, JSObject *proxy,
                                 AutoIdVector &props)
 {
-    return GetPropertyNames(cx, GetProxyTargetObject(proxy), 0, &props);
+    RootedObject target(cx, GetProxyTargetObject(proxy));
+    return GetPropertyNames(cx, target, 0, &props);
 }
 
 bool
 IndirectProxyHandler::call(JSContext *cx, JSObject *proxy, unsigned argc,
                    Value *vp)
 {
     JS_ASSERT(OperationInProgress(cx, proxy));
     AutoValueRooter rval(cx);
@@ -490,17 +491,18 @@ IndirectProxyHandler::nativeCall(JSConte
     return CallNativeImpl(cx, impl, args);
 }
 
 bool
 IndirectProxyHandler::hasInstance(JSContext *cx, JSObject *proxy, const Value *vp,
                                   bool *bp)
 {
     JSBool b;
-    if (!JS_HasInstance(cx, GetProxyTargetObject(proxy), *vp, &b))
+    RootedObject target(cx, GetProxyTargetObject(proxy));
+    if (!JS_HasInstance(cx, target, *vp, &b))
         return false;
     *bp = !!b;
     return true;
 }
 
 JSType
 IndirectProxyHandler::typeOf(JSContext *cx, JSObject *proxy)
 {
@@ -565,29 +567,29 @@ DirectProxyHandler::DirectProxyHandler(v
   : IndirectProxyHandler(family)
 {
 }
 
 bool
 DirectProxyHandler::has(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
 {
     JSBool found;
-    if (!JS_HasPropertyById(cx, GetProxyTargetObject(proxy), id, &found))
+    RootedObject target(cx, GetProxyTargetObject(proxy));
+    if (!JS_HasPropertyById(cx, target, id, &found))
         return false;
     *bp = !!found;
     return true;
 }
 
 bool
 DirectProxyHandler::hasOwn(JSContext *cx, JSObject *proxy, jsid id, bool *bp)
 {
-    JSObject *target = GetProxyTargetObject(proxy);
+    RootedObject target(cx, GetProxyTargetObject(proxy));
     AutoPropertyDescriptorRooter desc(cx);
-    if (!JS_GetPropertyDescriptorById(cx, target, id, JSRESOLVE_QUALIFIED,
-                                      &desc))
+    if (!JS_GetPropertyDescriptorById(cx, target, id, JSRESOLVE_QUALIFIED, &desc))
         return false;
     *bp = (desc.obj == target);
     return true;
 }
 
 bool
 DirectProxyHandler::get(JSContext *cx, JSObject *proxy, JSObject *receiver_,
                         jsid id_, Value *vp)
@@ -614,18 +616,17 @@ DirectProxyHandler::set(JSContext *cx, J
 
     *vp = value;
     return true;
 }
 
 bool
 DirectProxyHandler::keys(JSContext *cx, JSObject *proxy, AutoIdVector &props)
 {
-    return GetPropertyNames(cx, GetProxyTargetObject(proxy), JSITER_OWNONLY,
-                            &props);
+    return GetPropertyNames(cx, GetProxyTargetObject(proxy), JSITER_OWNONLY, &props);
 }
 
 bool
 DirectProxyHandler::iterate(JSContext *cx, JSObject *proxy, unsigned flags,
                             Value *vp)
 {
     Rooted<JSObject*> target(cx, GetProxyTargetObject(proxy));
     RootedValue value(cx);
@@ -1942,17 +1943,16 @@ Class js::ProxyClass = {
     JS_ResolveStub,
     JS_ConvertStub
 };
 
 JS_FRIEND_API(JSObject *)
 js_InitProxyClass(JSContext *cx, JSObject *obj_)
 {
     RootedObject obj(cx, obj_);
-
     RootedObject module(cx, NewObjectWithClassProto(cx, &ProxyClass, NULL, obj));
     if (!module || !module->setSingletonType(cx))
         return NULL;
 
     if (!JS_DefineProperty(cx, obj, "Proxy", OBJECT_TO_JSVAL(module),
                            JS_PropertyStub, JS_StrictPropertyStub, 0)) {
         return NULL;
     }
--- a/js/src/jsproxy.h
+++ b/js/src/jsproxy.h
@@ -242,91 +242,91 @@ inline bool IsObjectProxyClass(const Cla
     return clasp == &js::ObjectProxyClass || clasp == &js::OuterWindowProxyClass;
 }
 
 inline bool IsFunctionProxyClass(const Class *clasp)
 {
     return clasp == &js::FunctionProxyClass;
 }
 
-inline bool IsObjectProxy(const JSObject *obj)
+inline bool IsObjectProxy(RawObject obj)
 {
     return IsObjectProxyClass(GetObjectClass(obj));
 }
 
-inline bool IsFunctionProxy(const JSObject *obj)
+inline bool IsFunctionProxy(RawObject obj)
 {
     return IsFunctionProxyClass(GetObjectClass(obj));
 }
 
-inline bool IsProxy(const JSObject *obj)
+inline bool IsProxy(RawObject obj)
 {
     Class *clasp = GetObjectClass(obj);
     return IsObjectProxyClass(clasp) || IsFunctionProxyClass(clasp);
 }
 
 /* Shared between object and function proxies. */
 const uint32_t JSSLOT_PROXY_HANDLER = 0;
 const uint32_t JSSLOT_PROXY_PRIVATE = 1;
 const uint32_t JSSLOT_PROXY_EXTRA   = 2;
 /* Function proxies only. */
 const uint32_t JSSLOT_PROXY_CALL = 4;
 const uint32_t JSSLOT_PROXY_CONSTRUCT = 5;
 
 inline BaseProxyHandler *
-GetProxyHandler(const JSObject *obj)
+GetProxyHandler(RawObject obj)
 {
     JS_ASSERT(IsProxy(obj));
     return (BaseProxyHandler *) GetReservedSlot(obj, JSSLOT_PROXY_HANDLER).toPrivate();
 }
 
 inline const Value &
-GetProxyPrivate(const JSObject *obj)
+GetProxyPrivate(RawObject obj)
 {
     JS_ASSERT(IsProxy(obj));
     return GetReservedSlot(obj, JSSLOT_PROXY_PRIVATE);
 }
 
 inline JSObject *
-GetProxyTargetObject(const JSObject *obj)
+GetProxyTargetObject(RawObject obj)
 {
     JS_ASSERT(IsProxy(obj));
     return GetProxyPrivate(obj).toObjectOrNull();
 }
 
 inline const Value &
-GetProxyCall(const JSObject *obj)
+GetProxyCall(RawObject obj)
 {
     JS_ASSERT(IsFunctionProxy(obj));
     return GetReservedSlot(obj, JSSLOT_PROXY_CALL);
 }
 
 inline const Value &
-GetProxyExtra(const JSObject *obj, size_t n)
+GetProxyExtra(RawObject obj, size_t n)
 {
     JS_ASSERT(IsProxy(obj));
     return GetReservedSlot(obj, JSSLOT_PROXY_EXTRA + n);
 }
 
 inline void
-SetProxyHandler(JSObject *obj, BaseProxyHandler *handler)
+SetProxyHandler(RawObject obj, BaseProxyHandler *handler)
 {
     JS_ASSERT(IsProxy(obj));
     SetReservedSlot(obj, JSSLOT_PROXY_HANDLER, PrivateValue(handler));
 }
 
 inline void
-SetProxyPrivate(JSObject *obj, const Value &value)
+SetProxyPrivate(RawObject obj, const Value &value)
 {
     JS_ASSERT(IsProxy(obj));
     SetReservedSlot(obj, JSSLOT_PROXY_PRIVATE, value);
 }
 
 inline void
-SetProxyExtra(JSObject *obj, size_t n, const Value &extra)
+SetProxyExtra(RawObject obj, size_t n, const Value &extra)
 {
     JS_ASSERT(IsProxy(obj));
     JS_ASSERT(n <= 1);
     SetReservedSlot(obj, JSSLOT_PROXY_EXTRA + n, extra);
 }
 
 JS_FRIEND_API(JSObject *)
 NewProxyObject(JSContext *cx, BaseProxyHandler *handler, const Value &priv,
--- a/js/src/jspubtd.h
+++ b/js/src/jspubtd.h
@@ -244,16 +244,17 @@ template <typename T>
 struct RootKind;
 
 /*
  * Specifically mark the ThingRootKind of externally visible types, so that
  * JSAPI users may use JSRooted... types without having the class definition
  * available.
  */
 template <> struct RootKind<JSObject *> { static ThingRootKind rootKind() { return THING_ROOT_OBJECT; }; };
+template <> struct RootKind<JSFunction *> { static ThingRootKind rootKind() { return THING_ROOT_OBJECT; }; };
 template <> struct RootKind<JSString *> { static ThingRootKind rootKind() { return THING_ROOT_STRING; }; };
 template <> struct RootKind<JSScript *> { static ThingRootKind rootKind() { return THING_ROOT_SCRIPT; }; };
 template <> struct RootKind<jsid> { static ThingRootKind rootKind() { return THING_ROOT_ID; }; };
 template <> struct RootKind<Value> { static ThingRootKind rootKind() { return THING_ROOT_VALUE; }; };
 
 struct ContextFriendFields {
     JSRuntime *const    runtime;
 
--- a/js/src/jsreflect.cpp
+++ b/js/src/jsreflect.cpp
@@ -3285,21 +3285,20 @@ static JSFunctionSpec static_methods[] =
     JS_FN("parse", reflect_parse, 1, 0),
     JS_FS_END
 };
 
 
 JS_BEGIN_EXTERN_C
 
 JS_PUBLIC_API(JSObject *)
-JS_InitReflect(JSContext *cx, JSObject *obj_)
+JS_InitReflect(JSContext *cx, JSObject *objArg)
 {
-    RootedObject obj(cx, obj_), Reflect(cx);
-
-    Reflect = NewObjectWithClassProto(cx, &ObjectClass, NULL, obj);
+    RootedObject obj(cx, objArg);
+    RootedObject Reflect(cx, NewObjectWithClassProto(cx, &ObjectClass, NULL, obj));
     if (!Reflect || !Reflect->setSingletonType(cx))
         return NULL;
 
     if (!JS_DefineProperty(cx, obj, "Reflect", OBJECT_TO_JSVAL(Reflect),
                            JS_PropertyStub, JS_StrictPropertyStub, 0)) {
         return NULL;
     }
 
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -710,17 +710,17 @@ js::XDRScript(XDRState<mode> *xdr, Handl
                 if (funEnclosingScopeIndex == UINT32_MAX) {
                     funEnclosingScope = fun;
                 } else {
                     JS_ASSERT(funEnclosingScopeIndex < i);
                     funEnclosingScope = script->objects()->vector[funEnclosingScopeIndex];
                 }
             }
 
-            JSObject *tmp = *objp;
+            RootedObject tmp(cx, *objp);
             if (!XDRInterpretedFunction(xdr, funEnclosingScope, script, &tmp))
                 return false;
             *objp = tmp;
         } else {
             /* Code the nested block's enclosing scope. */
             JS_ASSERT(isBlock == 1);
             uint32_t blockEnclosingScopeIndex = 0;
             if (mode == XDR_ENCODE) {
@@ -736,18 +736,18 @@ js::XDRScript(XDRState<mode> *xdr, Handl
                 if (blockEnclosingScopeIndex != UINT32_MAX) {
                     JS_ASSERT(blockEnclosingScopeIndex < i);
                     blockEnclosingScope = script->objects()->vector[blockEnclosingScopeIndex];
                 } else {
                     blockEnclosingScope = fun;
                 }
             }
 
-            StaticBlockObject *tmp = static_cast<StaticBlockObject *>(objp->get());
-            if (!XDRStaticBlockObject(xdr, blockEnclosingScope, script, &tmp))
+            Rooted<StaticBlockObject*> tmp(cx, static_cast<StaticBlockObject *>(objp->get()));
+            if (!XDRStaticBlockObject(xdr, blockEnclosingScope, script, tmp.address()))
                 return false;
             *objp = tmp;
         }
     }
     for (i = 0; i != nregexps; ++i) {
         if (!XDRScriptRegExpObject(xdr, &script->regexps()->vector[i]))
             return false;
     }
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -648,17 +648,17 @@ str_toLocaleLowerCase(JSContext *cx, uns
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     /*
      * Forcefully ignore the first (or any) argument and return toLowerCase(),
      * ECMA has reserved that argument, presumably for defining the locale.
      */
     if (cx->localeCallbacks && cx->localeCallbacks->localeToLowerCase) {
-        JSString *str = ThisToStringForStringProto(cx, args);
+        RootedString str(cx, ThisToStringForStringProto(cx, args));
         if (!str)
             return false;
 
         Value result;
         if (!cx->localeCallbacks->localeToLowerCase(cx, str, &result))
             return false;
 
         args.rval().set(result);
@@ -715,17 +715,17 @@ str_toLocaleUpperCase(JSContext *cx, uns
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     /*
      * Forcefully ignore the first (or any) argument and return toUpperCase(),
      * ECMA has reserved that argument, presumably for defining the locale.
      */
     if (cx->localeCallbacks && cx->localeCallbacks->localeToUpperCase) {
-        JSString *str = ThisToStringForStringProto(cx, args);
+        RootedString str(cx, ThisToStringForStringProto(cx, args));
         if (!str)
             return false;
 
         Value result;
         if (!cx->localeCallbacks->localeToUpperCase(cx, str, &result))
             return false;
 
         args.rval().set(result);
@@ -741,17 +741,17 @@ str_localeCompare(JSContext *cx, unsigne
     CallArgs args = CallArgsFromVp(argc, vp);
     RootedString str(cx, ThisToStringForStringProto(cx, args));
     if (!str)
         return false;
 
     if (args.length() == 0) {
         args.rval().setInt32(0);
     } else {
-        JSString *thatStr = ToString(cx, args[0]);
+        RootedString thatStr(cx, ToString(cx, args[0]));
         if (!thatStr)
             return false;
 
         if (cx->localeCallbacks && cx->localeCallbacks->localeCompare) {
             args[0].setString(thatStr);
 
             Value result;
             if (!cx->localeCallbacks->localeCompare(cx, str, thatStr, &result))
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -3355,245 +3355,293 @@ CheckedUnwrap(JSContext *cx, JSObject *o
         return UnwrapObject(obj);
     MOZ_ASSERT(!cx->isExceptionPending());
     obj = UnwrapObjectChecked(cx, obj);
     MOZ_ASSERT(obj);
     return obj;
 }
 
 JS_FRIEND_API(JSBool)
-JS_IsArrayBufferObject(JSObject *obj, JSContext *cx)
+JS_IsArrayBufferObject(JSObject *objArg, JSContext *cx)
 {
+    RootedObject obj_(cx, objArg);
     MOZ_ASSERT(!cx->isExceptionPending());
-    if (!(obj = UnwrapObjectChecked(cx, obj))) {
+    JSObject *obj = UnwrapObjectChecked(cx, obj_);
+    if (!obj) {
         cx->clearPendingException();
         return false;
     }
     return obj->isArrayBuffer();
 }
 
 JS_FRIEND_API(JSBool)
-JS_IsTypedArrayObject(JSObject *obj, JSContext *cx)
+JS_IsTypedArrayObject(JSObject *objArg, JSContext *cx)
 {
+    RootedObject obj_(cx, objArg);
     MOZ_ASSERT(!cx->isExceptionPending());
-    if (!(obj = UnwrapObjectChecked(cx, obj))) {
+    JSObject *obj = UnwrapObjectChecked(cx, obj_);
+    if (!obj) {
         cx->clearPendingException();
         return false;
     }
     return obj->isTypedArray();
 }
 
 JS_FRIEND_API(JSBool)
-JS_IsArrayBufferViewObject(JSObject *obj, JSContext *cx)
+JS_IsArrayBufferViewObject(JSObject *objArg, JSContext *cx)
 {
+    RootedObject obj_(cx, objArg);
     MOZ_ASSERT(!cx->isExceptionPending());
-    if (!(obj = UnwrapObjectChecked(cx, obj))) {
+    JSObject *obj = UnwrapObjectChecked(cx, obj_);
+    if (!obj) {
         cx->clearPendingException();
         return false;
     }
     return obj->isTypedArray() || obj->isDataView();
 }
 
 JS_FRIEND_API(uint32_t)
-JS_GetArrayBufferByteLength(JSObject *obj, JSContext *cx)
+JS_GetArrayBufferByteLength(JSObject *objArg, JSContext *cx)
 {
-    if (!(obj = CheckedUnwrap(cx, obj)))
+    RootedObject obj_(cx, objArg);
+    JSObject *obj = CheckedUnwrap(cx, obj_);
+    if (!obj)
         return 0;
     return obj->asArrayBuffer().byteLength();
 }
 
 JS_FRIEND_API(uint8_t *)
-JS_GetArrayBufferData(JSObject *obj, JSContext *cx)
+JS_GetArrayBufferData(JSObject *objArg, JSContext *cx)
 {
-    if (!(obj = CheckedUnwrap(cx, obj)))
+    RootedObject obj_(cx, objArg);
+    JSObject *obj = CheckedUnwrap(cx, obj_);
+    if (!obj)
         return NULL;
     return obj->asArrayBuffer().dataPointer();
 }
 
 JS_FRIEND_API(JSObject *)
 JS_NewArrayBuffer(JSContext *cx, uint32_t nbytes)
 {
     JS_ASSERT(nbytes <= INT32_MAX);
     return ArrayBufferObject::create(cx, nbytes);
 }
 
 JS_FRIEND_API(uint32_t)
-JS_GetTypedArrayLength(JSObject *obj, JSContext *cx)
+JS_GetTypedArrayLength(JSObject *objArg, JSContext *cx)
 {
-    if (!(obj = CheckedUnwrap(cx, obj)))
+    RootedObject obj_(cx, objArg);
+    JSObject *obj = CheckedUnwrap(cx, obj_);
+    if (!obj)
         return 0;
     JS_ASSERT(obj->isTypedArray());
     return obj->getSlot(TypedArray::FIELD_LENGTH).toInt32();
 }
 
 JS_FRIEND_API(uint32_t)
-JS_GetTypedArrayByteOffset(JSObject *obj, JSContext *cx)
+JS_GetTypedArrayByteOffset(JSObject *objArg, JSContext *cx)
 {
-    if (!(obj = CheckedUnwrap(cx, obj)))
+    RootedObject obj_(cx, objArg);
+    JSObject *obj = CheckedUnwrap(cx, obj_);
+    if (!obj)
         return 0;
     JS_ASSERT(obj->isTypedArray());
     return obj->getSlot(TypedArray::FIELD_BYTEOFFSET).toInt32();
 }
 
 JS_FRIEND_API(uint32_t)
-JS_GetTypedArrayByteLength(JSObject *obj, JSContext *cx)
+JS_GetTypedArrayByteLength(JSObject *objArg, JSContext *cx)
 {
-    if (!(obj = CheckedUnwrap(cx, obj)))
+    RootedObject obj_(cx, objArg);
+    JSObject *obj = CheckedUnwrap(cx, obj_);
+    if (!obj)
         return 0;
     JS_ASSERT(obj->isTypedArray());
     return obj->getSlot(TypedArray::FIELD_BYTELENGTH).toInt32();
 }
 
 JS_FRIEND_API(JSArrayBufferViewType)
-JS_GetTypedArrayType(JSObject *obj, JSContext *cx)
+JS_GetTypedArrayType(JSObject *objArg, JSContext *cx)
 {
-    if (!(obj = CheckedUnwrap(cx, obj)))
+    RootedObject obj_(cx, objArg);
+    JSObject *obj = CheckedUnwrap(cx, obj_);
+    if (!obj)
         return ArrayBufferView::TYPE_MAX;
     JS_ASSERT(obj->isTypedArray());
     return static_cast<JSArrayBufferViewType>(obj->getSlot(TypedArray::FIELD_TYPE).toInt32());
 }
 
 JS_FRIEND_API(int8_t *)
-JS_GetInt8ArrayData(JSObject *obj, JSContext *cx)
+JS_GetInt8ArrayData(JSObject *objArg, JSContext *cx)
 {
-    if (!(obj = CheckedUnwrap(cx, obj)))
+    RootedObject obj_(cx, objArg);
+    JSObject *obj = CheckedUnwrap(cx, obj_);
+    if (!obj)
         return NULL;
     JS_ASSERT(obj->isTypedArray());
     JS_ASSERT(obj->getSlot(TypedArray::FIELD_TYPE).toInt32() == ArrayBufferView::TYPE_INT8);
     return static_cast<int8_t *>(TypedArray::viewData(obj));
 }
 
 JS_FRIEND_API(uint8_t *)
-JS_GetUint8ArrayData(JSObject *obj, JSContext *cx)
+JS_GetUint8ArrayData(JSObject *objArg, JSContext *cx)
 {
-    if (!(obj = CheckedUnwrap(cx, obj)))
+    RootedObject obj_(cx, objArg);
+    JSObject *obj = CheckedUnwrap(cx, obj_);
+    if (!obj)
         return NULL;
     JS_ASSERT(obj->isTypedArray());
     JS_ASSERT(obj->getSlot(TypedArray::FIELD_TYPE).toInt32() == ArrayBufferView::TYPE_UINT8);
     return static_cast<uint8_t *>(TypedArray::viewData(obj));
 }
 
 JS_FRIEND_API(uint8_t *)
-JS_GetUint8ClampedArrayData(JSObject *obj, JSContext *cx)
+JS_GetUint8ClampedArrayData(JSObject *objArg, JSContext *cx)
 {
-    if (!(obj = CheckedUnwrap(cx, obj)))
+    RootedObject obj_(cx, objArg);
+    JSObject *obj = CheckedUnwrap(cx, obj_);
+    if (!obj)
         return NULL;
     JS_ASSERT(obj->isTypedArray());
     JS_ASSERT(obj->getSlot(TypedArray::FIELD_TYPE).toInt32() == ArrayBufferView::TYPE_UINT8_CLAMPED);
     return static_cast<uint8_t *>(TypedArray::viewData(obj));
 }
 
 JS_FRIEND_API(int16_t *)
-JS_GetInt16ArrayData(JSObject *obj, JSContext *cx)
+JS_GetInt16ArrayData(JSObject *objArg, JSContext *cx)
 {
-    if (!(obj = CheckedUnwrap(cx, obj)))
+    RootedObject obj_(cx, objArg);
+    JSObject *obj = CheckedUnwrap(cx, obj_);
+    if (!obj)
         return NULL;
     JS_ASSERT(obj->isTypedArray());
     JS_ASSERT(obj->getSlot(TypedArray::FIELD_TYPE).toInt32() == ArrayBufferView::TYPE_INT16);
     return static_cast<int16_t *>(TypedArray::viewData(obj));
 }
 
 JS_FRIEND_API(uint16_t *)
-JS_GetUint16ArrayData(JSObject *obj, JSContext *cx)
+JS_GetUint16ArrayData(JSObject *objArg, JSContext *cx)
 {
-    if (!(obj = CheckedUnwrap(cx, obj)))
+    RootedObject obj_(cx, objArg);
+    JSObject *obj = CheckedUnwrap(cx, obj_);
+    if (!obj)
         return NULL;
     JS_ASSERT(obj->isTypedArray());
     JS_ASSERT(obj->getSlot(TypedArray::FIELD_TYPE).toInt32() == ArrayBufferView::TYPE_UINT16);
     return static_cast<uint16_t *>(TypedArray::viewData(obj));
 }
 
 JS_FRIEND_API(int32_t *)
-JS_GetInt32ArrayData(JSObject *obj, JSContext *cx)
+JS_GetInt32ArrayData(JSObject *objArg, JSContext *cx)
 {
-    if (!(obj = CheckedUnwrap(cx, obj)))
+    RootedObject obj_(cx, objArg);
+    JSObject *obj = CheckedUnwrap(cx, obj_);
+    if (!obj)
         return NULL;
     JS_ASSERT(obj->isTypedArray());
     JS_ASSERT(obj->getSlot(TypedArray::FIELD_TYPE).toInt32() == ArrayBufferView::TYPE_INT32);
     return static_cast<int32_t *>(TypedArray::viewData(obj));
 }
 
 JS_FRIEND_API(uint32_t *)
-JS_GetUint32ArrayData(JSObject *obj, JSContext *cx)
+JS_GetUint32ArrayData(JSObject *objArg, JSContext *cx)
 {
-    if (!(obj = CheckedUnwrap(cx, obj)))
+    RootedObject obj_(cx, objArg);
+    JSObject *obj = CheckedUnwrap(cx, obj_);
+    if (!obj)
         return NULL;
     JS_ASSERT(obj->isTypedArray());
     JS_ASSERT(obj->getSlot(TypedArray::FIELD_TYPE).toInt32() == ArrayBufferView::TYPE_UINT32);
     return static_cast<uint32_t *>(TypedArray::viewData(obj));
 }
 
 JS_FRIEND_API(float *)
-JS_GetFloat32ArrayData(JSObject *obj, JSContext *cx)
+JS_GetFloat32ArrayData(JSObject *objArg, JSContext *cx)
 {
-    if (!(obj = CheckedUnwrap(cx, obj)))
+    RootedObject obj_(cx, objArg);
+    JSObject *obj = CheckedUnwrap(cx, obj_);
+    if (!obj)
         return NULL;
     JS_ASSERT(obj->isTypedArray());
     JS_ASSERT(obj->getSlot(TypedArray::FIELD_TYPE).toInt32() == ArrayBufferView::TYPE_FLOAT32);
     return static_cast<float *>(TypedArray::viewData(obj));
 }
 
 JS_FRIEND_API(double *)
-JS_GetFloat64ArrayData(JSObject *obj, JSContext *cx)
+JS_GetFloat64ArrayData(JSObject *objArg, JSContext *cx)
 {
-    if (!(obj = CheckedUnwrap(cx, obj)))
+    RootedObject obj_(cx, objArg);
+    JSObject *obj = CheckedUnwrap(cx, obj_);
+    if (!obj)
         return NULL;
     JS_ASSERT(obj->isTypedArray());
     JS_ASSERT(obj->getSlot(TypedArray::FIELD_TYPE).toInt32() == ArrayBufferView::TYPE_FLOAT64);
     return static_cast<double *>(TypedArray::viewData(obj));
 }
 
 JS_FRIEND_API(JSBool)
-JS_IsDataViewObject(JSContext *cx, JSObject *obj, JSBool *isDataView)
+JS_IsDataViewObject(JSContext *cx, JSObject *objArg, JSBool *isDataView)
 {
-    if (!(obj = CheckedUnwrap(cx, obj)))
+    RootedObject obj_(cx, objArg);
+    JSObject *obj = CheckedUnwrap(cx, obj_);
+    if (!obj)
         return false;
     *isDataView = obj->isDataView();
     return true;
 }
 
 JS_FRIEND_API(uint32_t)
-JS_GetDataViewByteOffset(JSObject *obj, JSContext *cx)
+JS_GetDataViewByteOffset(JSObject *objArg, JSContext *cx)
 {
-    if (!(obj = CheckedUnwrap(cx, obj)))
+    RootedObject obj_(cx, objArg);
+    JSObject *obj = CheckedUnwrap(cx, obj_);
+    if (!obj)
         return 0;
     return obj->asDataView().byteOffset();
 }
 
 JS_FRIEND_API(void *)
-JS_GetDataViewData(JSObject *obj, JSContext *cx)
+JS_GetDataViewData(JSObject *objArg, JSContext *cx)
 {
-    if (!(obj = CheckedUnwrap(cx, obj)))
+    RootedObject obj_(cx, objArg);
+    JSObject *obj = CheckedUnwrap(cx, obj_);
+    if (!obj)
         return NULL;
     JS_ASSERT(obj->isDataView());
     return obj->asDataView().dataPointer();
 }
 
 JS_FRIEND_API(uint32_t)
-JS_GetDataViewByteLength(JSObject *obj, JSContext *cx)
+JS_GetDataViewByteLength(JSObject *objArg, JSContext *cx)
 {
-    if (!(obj = CheckedUnwrap(cx, obj)))
+    RootedObject obj_(cx, objArg);
+    JSObject *obj = CheckedUnwrap(cx, obj_);
+    if (!obj)
         return 0;
     JS_ASSERT(obj->isDataView());
     return obj->asDataView().byteLength();
 }
 
 JS_FRIEND_API(void *)
-JS_GetArrayBufferViewData(JSObject *obj, JSContext *cx)
+JS_GetArrayBufferViewData(JSObject *objArg, JSContext *cx)
 {
-    if (!(obj = CheckedUnwrap(cx, obj)))
+    RootedObject obj_(cx, objArg);
+    JSObject *obj = CheckedUnwrap(cx, obj_);
+    if (!obj)
         return NULL;
     JS_ASSERT(obj->isTypedArray() || obj->isDataView());
     return obj->isDataView() ? obj->asDataView().dataPointer() : TypedArray::viewData(obj);
 }
 
 JS_FRIEND_API(uint32_t)
-JS_GetArrayBufferViewByteLength(JSObject *obj, JSContext *cx)
+JS_GetArrayBufferViewByteLength(JSObject *objArg, JSContext *cx)
 {
-    if (!(obj = CheckedUnwrap(cx, obj)))
+    RootedObject obj_(cx, objArg);
+    JSObject *obj = CheckedUnwrap(cx, obj_);
+    if (!obj)
         return 0;
     JS_ASSERT(obj->isTypedArray() || obj->isDataView());
     return obj->isDataView()
            ? obj->asDataView().byteLength()
            : TypedArray::byteLengthValue(obj).toInt32();
 }
 
 JS_FRIEND_API(JSObject *)
--- a/js/src/jsweakmap.cpp
+++ b/js/src/jsweakmap.cpp
@@ -226,17 +226,17 @@ WeakMap_set_impl(JSContext *cx, CallArgs
 {
     JS_ASSERT(IsWeakMap(args.thisv()));
 
     if (args.length() < 1) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_MORE_ARGS_NEEDED,
                              "WeakMap.set", "0", "s");
         return false;
     }
-    JSObject *key = GetKeyArg(cx, args);
+    RootedObject key(cx, GetKeyArg(cx, args));
     if (!key)
         return false;
 
     Value value = (args.length() > 1) ? args[1] : UndefinedValue();
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
     ObjectValueMap *map = GetObjectMap(thisObj);
     if (!map) {
@@ -281,19 +281,19 @@ JS_NondeterministicGetWeakMapKeys(JSCont
         return true;
     }
     RootedObject arr(cx, NewDenseEmptyArray(cx));
     if (!arr)
         return false;
     ObjectValueMap *map = GetObjectMap(obj);
     if (map) {
         for (ObjectValueMap::Range r = map->nondeterministicAll(); !r.empty(); r.popFront()) {
-            JSObject *key = r.front().key;
+            RootedObject key(cx, r.front().key);
             // Re-wrapping the key (see comment of GetKeyArg)
-            if (!JS_WrapObject(cx, &key))
+            if (!JS_WrapObject(cx, key.address()))
                 return false;
 
             if (!js_NewbornArrayPush(cx, arr, ObjectValue(*key)))
                 return false;
         }
     }
     *ret = arr;
     return true;
--- a/js/src/jswrapper.cpp
+++ b/js/src/jswrapper.cpp
@@ -52,24 +52,24 @@ Wrapper::New(JSContext *cx, JSObject *ob
         return NULL;
     }
 #endif
     return NewProxyObject(cx, handler->toBaseProxyHandler(), ObjectValue(*obj),
                           proto, parent, obj->isCallable() ? obj : NULL, NULL);
 }
 
 Wrapper *
-Wrapper::wrapperHandler(const JSObject *wrapper)
+Wrapper::wrapperHandler(RawObject wrapper)
 {
     JS_ASSERT(wrapper->isWrapper());
     return GetProxyHandler(wrapper)->toWrapper();
 }
 
 JSObject *
-Wrapper::wrappedObject(const JSObject *wrapper)
+Wrapper::wrappedObject(RawObject wrapper)
 {
     JS_ASSERT(wrapper->isWrapper());
     return GetProxyTargetObject(wrapper);
 }
 
 Wrapper::Wrapper(unsigned flags) : mFlags(flags)
 {
 }
@@ -125,17 +125,17 @@ js::UnwrapOneChecked(JSContext *cx, JSOb
     }
     obj = Wrapper::wrappedObject(obj);
     JS_ASSERT(obj);
 
     return obj;
 }
 
 bool
-js::IsCrossCompartmentWrapper(const JSObject *wrapper)
+js::IsCrossCompartmentWrapper(RawObject wrapper)
 {
     return wrapper->isWrapper() &&
            !!(Wrapper::wrapperHandler(wrapper)->flags() & Wrapper::CROSS_COMPARTMENT);
 }
 
 IndirectWrapper::IndirectWrapper(unsigned flags) : Wrapper(flags),
     IndirectProxyHandler(&sWrapperFamily)
 {
@@ -372,19 +372,23 @@ DirectWrapper::fun_toString(JSContext *c
 
 DirectWrapper DirectWrapper::singleton((unsigned)0);
 
 /* Compartments. */
 
 namespace js {
 
 extern JSObject *
-TransparentObjectWrapper(JSContext *cx, JSObject *obj, JSObject *wrappedProto, JSObject *parent,
+TransparentObjectWrapper(JSContext *cx, JSObject *objArg, JSObject *wrappedProtoArg, JSObject *parentArg,
                          unsigned flags)
 {
+    RootedObject obj(cx, objArg);
+    RootedObject wrappedProto(cx, wrappedProtoArg);
+    RootedObject parent(cx, parentArg);
+
     // Allow wrapping outer window proxies.
     JS_ASSERT(!obj->isWrapper() || obj->getClass()->ext.innerObject);
     return Wrapper::New(cx, obj, wrappedProto, parent, &CrossCompartmentWrapper::singleton);
 }
 
 }
 
 ForceFrame::ForceFrame(JSContext *cx, JSObject *target)
--- a/js/src/jswrapper.h
+++ b/js/src/jswrapper.h
@@ -59,19 +59,19 @@ class JS_FRIEND_API(Wrapper)
         PermitObjectAccess,
         PermitPropertyAccess,
         DenyAccess
     } Permission;
 
     static JSObject *New(JSContext *cx, JSObject *obj, JSObject *proto,
                          JSObject *parent, Wrapper *handler);
 
-    static Wrapper *wrapperHandler(const JSObject *wrapper);
+    static Wrapper *wrapperHandler(RawObject wrapper);
 
-    static JSObject *wrappedObject(const JSObject *wrapper);
+    static JSObject *wrappedObject(RawObject wrapper);
 
     explicit Wrapper(unsigned flags);
 
     unsigned flags() const {
         return mFlags;
     }
 
     /*
@@ -338,17 +338,17 @@ extern JSObject *
 TransparentObjectWrapper(JSContext *cx, JSObject *obj, JSObject *wrappedProto, JSObject *parent,
                          unsigned flags);
 
 // Proxy family for wrappers. Public so that IsWrapper() can be fully inlined by
 // jsfriendapi users.
 extern JS_FRIEND_DATA(int) sWrapperFamily;
 
 inline bool
-IsWrapper(const JSObject *obj)
+IsWrappe