Bug 767141 - moar rooting. r=bhackett
authorSteve Fink <sfink@mozilla.com>
Thu, 21 Jun 2012 14:19:21 -0700
changeset 98016 0dd9559f15ff98a990e79cb204f76a1c88a72d8a
parent 98015 54bb503183ebfcc0c98faa89c097a128eabd155c
child 98017 8f15e352d4b4fa0ec9315938623365abfd75ea3b
push id11322
push usersfink@mozilla.com
push dateSat, 30 Jun 2012 04:47:50 +0000
treeherdermozilla-inbound@8f15e352d4b4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbhackett
bugs767141
milestone16.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 767141 - moar rooting. r=bhackett Believed to be complete rooting for jsapi.cpp, ctypes/CTypes.cpp, and frontend/BytecodeCompiler.cpp, and lots of rooting for additional things I encountered along the way
js/src/ctypes/CTypes.cpp
js/src/ctypes/CTypes.h
js/src/frontend/BytecodeCompiler.cpp
js/src/frontend/BytecodeCompiler.h
js/src/gc/Marking.cpp
js/src/jsapi.cpp
js/src/jsarray.cpp
js/src/jsfun.cpp
js/src/jsinfer.cpp
js/src/jsinfer.h
js/src/jsinferinlines.h
js/src/jsinterp.cpp
js/src/jsobj.cpp
js/src/jsobjinlines.h
js/src/jsscript.cpp
js/src/jsstr.cpp
js/src/jstypedarray.cpp
js/src/jstypedarrayinlines.h
js/src/methodjit/Compiler.cpp
js/src/methodjit/Compiler.h
js/src/methodjit/StubCalls.cpp
js/src/vm/GlobalObject.cpp
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -42,17 +42,17 @@ namespace ctypes {
 /*******************************************************************************
 ** JSAPI function prototypes
 *******************************************************************************/
 
 static JSBool ConstructAbstract(JSContext* cx, unsigned argc, jsval* vp);
 
 namespace CType {
   static JSBool ConstructData(JSContext* cx, unsigned argc, jsval* vp);
-  static JSBool ConstructBasic(JSContext* cx, JSObject* obj, unsigned argc, jsval* vp);
+  static JSBool ConstructBasic(JSContext* cx, JSHandleObject obj, unsigned argc, jsval* vp);
 
   static void Trace(JSTracer* trc, JSObject* obj);
   static void Finalize(JSFreeOp *fop, JSObject* obj);
   static void FinalizeProtoClass(JSFreeOp *fop, JSObject* obj);
 
   static JSBool PrototypeGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
     jsval* vp);
   static JSBool NameGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
@@ -79,17 +79,17 @@ namespace CType {
 
 namespace ABI {
   bool IsABI(JSObject* obj);
   static JSBool ToSource(JSContext* cx, unsigned argc, jsval* vp);
 }
 
 namespace PointerType {
   static JSBool Create(JSContext* cx, unsigned argc, jsval* vp);
-  static JSBool ConstructData(JSContext* cx, JSObject* obj, unsigned argc, jsval* vp);
+  static JSBool ConstructData(JSContext* cx, JSHandleObject obj, unsigned argc, jsval* vp);
 
   static JSBool TargetTypeGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
     jsval* vp);
   static JSBool ContentsGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
     jsval* vp);
   static JSBool ContentsSetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, JSBool strict,
     jsval* vp);
   static JSBool IsNull(JSContext* cx, unsigned argc, jsval* vp);
@@ -97,45 +97,45 @@ namespace PointerType {
   static JSBool Decrement(JSContext* cx, unsigned argc, jsval* vp);
   // The following is not an instance function, since we don't want to expose arbitrary
   // pointer arithmetic at this moment.
   static JSBool OffsetBy(JSContext* cx, int offset, jsval* vp);
 }
 
 namespace ArrayType {
   static JSBool Create(JSContext* cx, unsigned argc, jsval* vp);
-  static JSBool ConstructData(JSContext* cx, JSObject* obj, unsigned argc, jsval* vp);
+  static JSBool ConstructData(JSContext* cx, JSHandleObject obj, unsigned argc, jsval* vp);
 
   static JSBool ElementTypeGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
     jsval* vp);
   static JSBool LengthGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
     jsval* vp);
   static JSBool Getter(JSContext* cx, JSHandleObject obj, JSHandleId idval, jsval* vp);
   static JSBool Setter(JSContext* cx, JSHandleObject obj, JSHandleId idval, JSBool strict, jsval* vp);
   static JSBool AddressOfElement(JSContext* cx, unsigned argc, jsval* vp);
 }
 
 namespace StructType {
   static JSBool Create(JSContext* cx, unsigned argc, jsval* vp);
-  static JSBool ConstructData(JSContext* cx, JSObject* obj, unsigned argc, jsval* vp);
+  static JSBool ConstructData(JSContext* cx, JSHandleObject obj, unsigned argc, jsval* vp);
 
   static JSBool FieldsArrayGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
     jsval* vp);
   static JSBool FieldGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
     jsval* vp);
   static JSBool FieldSetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, JSBool strict,
                             jsval* vp);
   static JSBool AddressOfField(JSContext* cx, unsigned argc, jsval* vp);
   static JSBool Define(JSContext* cx, unsigned argc, jsval* vp);
 }
 
 namespace FunctionType {
   static JSBool Create(JSContext* cx, unsigned argc, jsval* vp);
-  static JSBool ConstructData(JSContext* cx, JSObject* typeObj,
-    JSObject* dataObj, JSObject* fnObj, JSObject* thisObj, jsval errVal);
+  static JSBool ConstructData(JSContext* cx, JSHandleObject typeObj,
+    JSHandleObject dataObj, JSHandleObject fnObj, JSHandleObject thisObj, jsval errVal);
 
   static JSBool Call(JSContext* cx, unsigned argc, jsval* vp);
 
   static JSBool ArgTypesGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
     jsval* vp);
   static JSBool ReturnTypeGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
     jsval* vp);
   static JSBool ABIGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, jsval* vp);
@@ -157,17 +157,17 @@ namespace CData {
 
   static JSBool ValueGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
                             jsval* vp);
   static JSBool ValueSetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
                             JSBool strict, jsval* vp);
   static JSBool Address(JSContext* cx, unsigned argc, jsval* vp);
   static JSBool ReadString(JSContext* cx, unsigned argc, jsval* vp);
   static JSBool ToSource(JSContext* cx, unsigned argc, jsval* vp);
-  static JSString *GetSourceString(JSContext *cx, JSObject *typeObj,
+  static JSString *GetSourceString(JSContext *cx, JSHandleObject typeObj,
                                    void *data);
   static JSBool ErrnoGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
                             jsval* vp);
 
 #if defined(XP_WIN)
   static JSBool LastErrorGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
                                 jsval* vp);
 #endif // defined(XP_WIN)
@@ -695,30 +695,30 @@ TypeError(JSContext* cx, const char* exp
     src = "<<error converting value to string>>";
   }
   JS_ReportErrorNumber(cx, GetErrorMessage, NULL,
                        CTYPESMSG_TYPE_ERROR, expected, src);
   return false;
 }
 
 static JSObject*
-InitCTypeClass(JSContext* cx, JSObject* parent)
-{
-  JSFunction* fun = JS_DefineFunction(cx, parent, "CType", ConstructAbstract, 0,
-                      CTYPESCTOR_FLAGS);
+InitCTypeClass(JSContext* cx, HandleObject parent)
+{
+  JSFunction *fun = JS_DefineFunction(cx, parent, "CType", ConstructAbstract, 0,
+                                      CTYPESCTOR_FLAGS);
   if (!fun)
     return NULL;
 
-  JSObject* ctor = JS_GetFunctionObject(fun);
-  JSObject* fnproto = JS_GetPrototype(ctor);
+  RootedObject ctor(cx, JS_GetFunctionObject(fun));
+  JSObject *fnproto = JS_GetPrototype(ctor);
   JS_ASSERT(ctor);
   JS_ASSERT(fnproto);
 
   // Set up ctypes.CType.prototype.
-  JSObject* prototype = JS_NewObject(cx, &sCTypeProtoClass, fnproto, parent);
+  RootedObject prototype(cx, JS_NewObject(cx, &sCTypeProtoClass, fnproto, parent));
   if (!prototype)
     return NULL;
 
   if (!JS_DefineProperty(cx, ctor, "prototype", OBJECT_TO_JSVAL(prototype),
          NULL, NULL, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT))
     return NULL;
 
   if (!JS_DefineProperty(cx, prototype, "constructor", OBJECT_TO_JSVAL(ctor),
@@ -734,47 +734,47 @@ InitCTypeClass(JSContext* cx, JSObject* 
     return NULL;
 
   return prototype;
 }
 
 static JSObject*
 InitABIClass(JSContext* cx, JSObject* parent)
 {
-  JSObject* obj = JS_NewObject(cx, NULL, NULL, NULL);
+  RootedObject obj(cx, JS_NewObject(cx, NULL, NULL, NULL));
   
   if (!obj)
     return NULL;
     
   if (!JS_DefineFunctions(cx, obj, sCABIFunctions))
     return NULL;
   
   return obj;
 }
 
 
 static JSObject*
-InitCDataClass(JSContext* cx, JSObject* parent, JSObject* CTypeProto)
+InitCDataClass(JSContext* cx, HandleObject parent, HandleObject CTypeProto)
 {
   JSFunction* fun = JS_DefineFunction(cx, parent, "CData", ConstructAbstract, 0,
                       CTYPESCTOR_FLAGS);
   if (!fun)
     return NULL;
 
-  JSObject* ctor = JS_GetFunctionObject(fun);
+  RootedObject ctor(cx, JS_GetFunctionObject(fun));
   JS_ASSERT(ctor);
 
   // Set up ctypes.CData.__proto__ === ctypes.CType.prototype.
   // (Note that 'ctypes.CData instanceof Function' is still true, thanks to the
   // prototype chain.)
   if (!JS_SetPrototype(cx, ctor, CTypeProto))
     return NULL;
 
   // Set up ctypes.CData.prototype.
-  JSObject* prototype = JS_NewObject(cx, &sCDataProtoClass, NULL, parent);
+  RootedObject prototype(cx, JS_NewObject(cx, &sCDataProtoClass, NULL, parent));
   if (!prototype)
     return NULL;
 
   if (!JS_DefineProperty(cx, ctor, "prototype", OBJECT_TO_JSVAL(prototype),
          NULL, NULL, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT))
     return NULL;
 
   if (!JS_DefineProperty(cx, prototype, "constructor", OBJECT_TO_JSVAL(ctor),
@@ -790,50 +790,50 @@ InitCDataClass(JSContext* cx, JSObject* 
       !JS_FreezeObject(cx, ctor))
     return NULL;
 
   return prototype;
 }
 
 static JSBool
 DefineABIConstant(JSContext* cx,
-                  JSObject* parent,
+                  HandleObject parent,
                   const char* name,
                   ABICode code,
                   JSObject* prototype)
 {
   JSObject* obj = 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.
 static JSBool
 InitTypeConstructor(JSContext* cx,
-                    JSObject* parent,
-                    JSObject* CTypeProto,
-                    JSObject* CDataProto,
+                    HandleObject parent,
+                    HandleObject CTypeProto,
+                    HandleObject CDataProto,
                     JSFunctionSpec spec,
                     JSFunctionSpec* fns,
                     JSPropertySpec* props,
                     JSFunctionSpec* instanceFns,
                     JSPropertySpec* instanceProps,
                     JSObject*& typeProto,
                     JSObject*& dataProto)
 {
   JSFunction* fun = js::DefineFunctionWithReserved(cx, parent, spec.name, spec.call, 
                       spec.nargs, spec.flags);
   if (!fun)
     return false;
 
-  JSObject* obj = JS_GetFunctionObject(fun);
+  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);
   if (!typeProto)
     return false;
 
@@ -882,29 +882,29 @@ InitTypeConstructor(JSContext* cx,
       !JS_FreezeObject(cx, typeProto))
     return false;
 
   return true;
 }
 
 JSObject*
 InitInt64Class(JSContext* cx,
-               JSObject* parent,
+               HandleObject parent,
                JSClass* clasp,
                JSNative construct,
                JSFunctionSpec* fs,
                JSFunctionSpec* static_fs)
 {
   // Init type class and constructor
-  JSObject* prototype = JS_InitClass(cx, parent, NULL, clasp, construct,
-    0, NULL, fs, NULL, static_fs);
+  RootedObject prototype(cx, JS_InitClass(cx, parent, NULL, clasp, construct,
+                                          0, NULL, fs, NULL, static_fs));
   if (!prototype)
     return NULL;
 
-  JSObject* ctor = JS_GetConstructor(cx, prototype);
+  RootedObject ctor(cx, JS_GetConstructor(cx, prototype));
   if (!ctor)
     return NULL;
   if (!JS_FreezeObject(cx, ctor))
     return NULL;
 
   // Redefine the 'join' function as an extended native and stash
   // ctypes.{Int64,UInt64}.prototype in a reserved slot of the new function.
   JS_ASSERT(clasp == &sInt64ProtoClass || clasp == &sUInt64ProtoClass);
@@ -919,63 +919,62 @@ InitInt64Class(JSContext* cx,
 
   if (!JS_FreezeObject(cx, prototype))
     return NULL;
 
   return prototype;
 }
 
 static void
-AttachProtos(JSObject* proto, JSObject** protos)
+AttachProtos(JSObject* proto, const AutoObjectVector& protos)
 {
   // For a given 'proto' of [[Class]] "CTypeProto", attach each of the 'protos'
   // to the appropriate CTypeProtoSlot. (SLOT_CTYPES is the last slot
   // of [[Class]] "CTypeProto" that we fill in this automated manner.)
   for (uint32_t i = 0; i <= SLOT_CTYPES; ++i)
     JS_SetReservedSlot(proto, i, OBJECT_TO_JSVAL(protos[i]));
 }
 
 JSBool
-InitTypeClasses(JSContext* cx, JSObject* parent)
+InitTypeClasses(JSContext* cx, HandleObject parent)
 {
   // Initialize the ctypes.CType class. This acts as an abstract base class for
   // the various types, and provides the common API functions. It has:
   //   * [[Class]] "Function"
   //   * __proto__ === Function.prototype
   //   * A constructor that throws a TypeError. (You can't construct an
   //     abstract type!)
   //   * 'prototype' property:
   //     * [[Class]] "CTypeProto"
   //     * __proto__ === Function.prototype
   //     * A constructor that throws a TypeError. (You can't construct an
   //       abstract type instance!)
   //     * 'constructor' property === ctypes.CType
   //     * Provides properties and functions common to all CTypes.
-  JSObject* CTypeProto = InitCTypeClass(cx, parent);
+  RootedObject CTypeProto(cx, InitCTypeClass(cx, parent));
   if (!CTypeProto)
     return false;
 
   // Initialize the ctypes.CData class. This acts as an abstract base class for
   // instances of the various types, and provides the common API functions.
   // It has:
   //   * [[Class]] "Function"
   //   * __proto__ === Function.prototype
   //   * A constructor that throws a TypeError. (You can't construct an
   //     abstract type instance!)
   //   * 'prototype' property:
   //     * [[Class]] "CDataProto"
   //     * 'constructor' property === ctypes.CData
   //     * Provides properties and functions common to all CDatas.
-  JSObject* CDataProto = InitCDataClass(cx, parent, CTypeProto);
+  RootedObject CDataProto(cx, InitCDataClass(cx, parent, CTypeProto));
   if (!CDataProto)
     return false;
 
   // Link CTypeProto to CDataProto.
-  JS_SetReservedSlot(CTypeProto, SLOT_OURDATAPROTO,
-                     OBJECT_TO_JSVAL(CDataProto));
+  JS_SetReservedSlot(CTypeProto, SLOT_OURDATAPROTO, OBJECT_TO_JSVAL(CDataProto));
 
   // Create and attach the special class constructors: ctypes.PointerType,
   // ctypes.ArrayType, ctypes.StructType, and ctypes.FunctionType.
   // Each of these constructors 'c' has, respectively:
   //   * [[Class]] "Function"
   //   * __proto__ === Function.prototype
   //   * A constructor that creates a user-defined type.
   //   * 'prototype' property:
@@ -993,43 +992,40 @@ InitTypeClasses(JSContext* cx, JSObject*
   //   * [[Class]] "CType"
   //   * __proto__ === ctypes.{Pointer,Array,Struct,Function}Type.prototype
   //   * A constructor which creates and returns a CData object, containing
   //     binary data of the given type.
   //   * 'prototype' property:
   //     * [[Class]] "CDataProto"
   //     * __proto__ === 'p', the prototype object from above
   //     * 'constructor' property === 't'
-  JSObject* protos[CTYPEPROTO_SLOTS];
+  AutoObjectVector protos(cx);
+  protos.resize(CTYPEPROTO_SLOTS);
   if (!InitTypeConstructor(cx, parent, CTypeProto, CDataProto,
          sPointerFunction, NULL, sPointerProps,
          sPointerInstanceFunctions, sPointerInstanceProps,
          protos[SLOT_POINTERPROTO], protos[SLOT_POINTERDATAPROTO]))
     return false;
-  js::AutoObjectRooter proot(cx, protos[SLOT_POINTERDATAPROTO]);
 
   if (!InitTypeConstructor(cx, parent, CTypeProto, CDataProto,
          sArrayFunction, NULL, sArrayProps,
          sArrayInstanceFunctions, sArrayInstanceProps,
          protos[SLOT_ARRAYPROTO], protos[SLOT_ARRAYDATAPROTO]))
     return false;
-  js::AutoObjectRooter aroot(cx, protos[SLOT_ARRAYDATAPROTO]);
 
   if (!InitTypeConstructor(cx, parent, CTypeProto, CDataProto,
          sStructFunction, sStructFunctions, sStructProps,
          sStructInstanceFunctions, NULL,
          protos[SLOT_STRUCTPROTO], protos[SLOT_STRUCTDATAPROTO]))
     return false;
-  js::AutoObjectRooter sroot(cx, protos[SLOT_STRUCTDATAPROTO]);
-
-  if (!InitTypeConstructor(cx, parent, CTypeProto, protos[SLOT_POINTERDATAPROTO],
+
+  if (!InitTypeConstructor(cx, parent, CTypeProto, protos.handleAt(SLOT_POINTERDATAPROTO),
          sFunctionFunction, NULL, sFunctionProps, sFunctionInstanceFunctions, NULL,
          protos[SLOT_FUNCTIONPROTO], protos[SLOT_FUNCTIONDATAPROTO]))
     return false;
-  js::AutoObjectRooter froot(cx, protos[SLOT_FUNCTIONDATAPROTO]);
 
   protos[SLOT_CDATAPROTO] = CDataProto;
 
   // Create and attach the ctypes.{Int64,UInt64} constructors.
   // Each of these has, respectively:
   //   * [[Class]] "Function"
   //   * __proto__ === Function.prototype
   //   * A constructor that creates a ctypes.{Int64,UInt64} object, respectively.
@@ -1053,17 +1049,17 @@ InitTypeClasses(JSContext* cx, JSObject*
   // and the special type constructors, so we can access them when constructing
   // instances of those types. 
   AttachProtos(CTypeProto, protos);
   AttachProtos(protos[SLOT_POINTERPROTO], protos);
   AttachProtos(protos[SLOT_ARRAYPROTO], protos);
   AttachProtos(protos[SLOT_STRUCTPROTO], protos);
   AttachProtos(protos[SLOT_FUNCTIONPROTO], protos);
 
-  JSObject* ABIProto = InitABIClass(cx, parent);
+  RootedObject ABIProto(cx, InitABIClass(cx, parent));
   if (!ABIProto)
     return false;
 
   // Attach objects representing ABI constants.
   if (!DefineABIConstant(cx, parent, "default_abi", ABI_DEFAULT, ABIProto) ||
       !DefineABIConstant(cx, parent, "stdcall_abi", ABI_STDCALL, ABIProto) ||
       !DefineABIConstant(cx, parent, "winapi_abi", ABI_WINAPI, ABIProto))
     return false;
@@ -1074,35 +1070,35 @@ InitTypeClasses(JSContext* cx, JSObject*
   //   * __proto__ === ctypes.CType.prototype
   //   * A constructor which creates and returns a CData object, containing
   //     binary data of the given type.
   //   * 'prototype' property:
   //     * [[Class]] "CDataProto"
   //     * __proto__ === ctypes.CData.prototype
   //     * 'constructor' property === 't'
 #define DEFINE_TYPE(name, type, ffiType)                                       \
-  JSObject* typeObj_##name =                                                   \
+  RootedObject typeObj_##name(cx,                                              \
     CType::DefineBuiltin(cx, parent, #name, CTypeProto, CDataProto, #name,     \
       TYPE_##name, INT_TO_JSVAL(sizeof(type)),                                 \
-      INT_TO_JSVAL(ffiType.alignment), &ffiType);                              \
+      INT_TO_JSVAL(ffiType.alignment), &ffiType));                             \
   if (!typeObj_##name)                                                         \
     return false;
 #include "typedefs.h"
 
   // 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 =
+  JSObject *typeObj =
     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))
@@ -1148,20 +1144,21 @@ bool GetObjectProperty(JSContext *cx, JS
 
   *result = 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* global_)
 {
   // attach ctypes property to global object
-  JSObject* ctypes = JS_NewObject(cx, &sCTypesGlobalClass, NULL, NULL);
+  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)) {
     return false;
   }
 
@@ -1169,23 +1166,21 @@ JS_InitCTypesClass(JSContext* cx, JSObje
     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.
-  JSObject* ctor;
-  if (!GetObjectProperty(cx, ctypes, "CDataFinalizer", &ctor)) {
+  RootedObject ctor(cx);
+  if (!GetObjectProperty(cx, ctypes, "CDataFinalizer", ctor.address()))
     return false;
-  }
-
-  JSObject* prototype = JS_NewObject(cx, &sCDataFinalizerProtoClass,
-                                     NULL, ctypes);
+
+  RootedObject prototype(cx, JS_NewObject(cx, &sCDataFinalizerProtoClass, NULL, ctypes));
   if (!prototype)
     return false;
 
   if (!JS_DefineProperties(cx, prototype, sCDataFinalizerProps) ||
       !JS_DefineFunctions(cx, prototype, sCDataFinalizerFunctions))
     return false;
 
   if (!JS_DefineProperty(cx, ctor, "prototype", OBJECT_TO_JSVAL(prototype),
@@ -2238,17 +2233,17 @@ ImplicitConvert(JSContext* cx,
       }
       default:
         return TypeError(cx, "array", val);
       }
 
     } else if (!JSVAL_IS_PRIMITIVE(val) &&
                JS_IsArrayObject(cx, JSVAL_TO_OBJECT(val))) {
       // Convert each element of the array by calling ImplicitConvert.
-      JSObject* sourceArray = JSVAL_TO_OBJECT(val);
+      RootedObject sourceArray(cx, JSVAL_TO_OBJECT(val));
       uint32_t sourceLength;
       if (!JS_GetArrayLength(cx, sourceArray, &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.
@@ -2295,21 +2290,20 @@ ImplicitConvert(JSContext* cx,
       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.
-      JSObject* obj = JSVAL_TO_OBJECT(val);
-      JSObject* iter = JS_NewPropertyIterator(cx, obj);
+      RootedObject obj(cx, JSVAL_TO_OBJECT(val));
+      RootedObject iter(cx, JS_NewPropertyIterator(cx, obj));
       if (!iter)
         return false;
-      js::AutoObjectRooter iterroot(cx, iter);
 
       // 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);
         return false;
       }
@@ -2364,17 +2358,17 @@ ImplicitConvert(JSContext* cx,
 
   return true;
 }
 
 // Convert jsval 'val' to a C binary representation of CType 'targetType',
 // storing the result in 'buffer'. This function is more forceful than
 // ImplicitConvert.
 JSBool
-ExplicitConvert(JSContext* cx, jsval val, JSObject* targetType, void* buffer)
+ExplicitConvert(JSContext* cx, jsval val, HandleObject targetType, void* buffer)
 {
   // If ImplicitConvert succeeds, use that result.
   if (ImplicitConvert(cx, val, targetType, buffer, false, NULL))
     return true;
 
   // If ImplicitConvert failed, and there is no pending exception, then assume
   // hard failure (out of memory, or some other similarly serious condition).
   // We store any pending exception in case we need to re-throw it.
@@ -2437,19 +2431,20 @@ ExplicitConvert(JSContext* cx, jsval val
   return true;
 }
 
 // Given a CType 'typeObj', generate a string describing the C type declaration
 // corresponding to 'typeObj'. For instance, the CType constructed from
 // 'ctypes.int32_t.ptr.array(4).ptr.ptr' will result in the type string
 // 'int32_t*(**)[4]'.
 static JSString*
-BuildTypeName(JSContext* cx, JSObject* typeObj)
+BuildTypeName(JSContext* cx, JSObject* typeObj_)
 {
   AutoString result;
+  RootedObject typeObj(cx, typeObj_);
 
   // Walk the hierarchy of types, outermost to innermost, building up the type
   // string. This consists of the base type, which goes on the left.
   // Derived type modifiers (* and []) build from the inside outward, with
   // pointers on the left and arrays on the right. An excellent description
   // of the rules for building C type declarations can be found at:
   // http://unixwiz.net/techtips/reading-cdecl.html
   TypeCode prevGrouping = CType::GetTypeCode(typeObj), currentGrouping;
@@ -2504,17 +2499,18 @@ BuildTypeName(JSContext* cx, JSObject* t
       if (prevGrouping == TYPE_pointer) {
         PrependString(result, "(");
         AppendString(result, ")");
       }
 
       // Argument list goes on the right.
       AppendString(result, "(");
       for (size_t i = 0; i < fninfo->mArgTypes.length(); ++i) {
-        JSString* argName = CType::GetName(cx, fninfo->mArgTypes[i]);
+        RootedObject argType(cx, fninfo->mArgTypes[i]);
+        JSString* argName = CType::GetName(cx, argType);
         AppendString(result, argName);
         if (i != fninfo->mArgTypes.length() - 1 ||
             fninfo->mIsVariadic)
           AppendString(result, ", ");
       }
       if (fninfo->mIsVariadic)
         AppendString(result, "...");
       AppendString(result, ")");
@@ -2549,34 +2545,36 @@ BuildTypeName(JSContext* cx, JSObject* t
 // would construct the same CType. If 'makeShort' is true, assume that any
 // StructType 't' is bound to an in-scope variable of name 't.name', and use
 // that variable in place of generating a string to construct the type 't'.
 // (This means the type comparison function CType::TypesEqual will return true
 // when comparing the input and output of BuildTypeSource, since struct
 // equality is determined by strict JSObject pointer equality.)
 static void
 BuildTypeSource(JSContext* cx,
-                JSObject* typeObj, 
+                JSObject* typeObj_, 
                 bool makeShort, 
                 AutoString& result)
 {
+  RootedObject typeObj(cx, typeObj_);
+
   // Walk the types, building up the toSource() string.
   switch (CType::GetTypeCode(typeObj)) {
   case TYPE_void_t:
 #define DEFINE_TYPE(name, type, ffiType)  \
   case TYPE_##name:
 #include "typedefs.h"
   {
     AppendString(result, "ctypes.");
     JSString* nameStr = CType::GetName(cx, typeObj);
     AppendString(result, nameStr);
     break;
   }
   case TYPE_pointer: {
-    JSObject* baseType = PointerType::GetBaseType(typeObj);
+    RootedObject baseType(cx, PointerType::GetBaseType(typeObj));
 
     // Specialcase ctypes.voidptr_t.
     if (CType::GetTypeCode(baseType) == TYPE_void_t) {
       AppendString(result, "ctypes.voidptr_t");
       break;
     }
 
     // Recursively build the source string, and append '.ptr'.
@@ -2695,17 +2693,17 @@ BuildTypeSource(JSContext* cx,
 // the type comparison function CType::TypesEqual will return true when
 // comparing the types, since struct equality is determined by strict JSObject
 // pointer equality.) Further, if 'isImplicit' is true, ensure that the
 // resulting string can ImplicitConvert successfully if passed to another data
 // constructor. (This is important when called recursively, since fields of
 // structs and arrays are converted with ImplicitConvert.)
 static JSBool
 BuildDataSource(JSContext* cx,
-                JSObject* typeObj, 
+                HandleObject typeObj, 
                 void* data, 
                 bool isImplicit, 
                 AutoString& result)
 {
   TypeCode type = CType::GetTypeCode(typeObj);
   switch (type) {
   case TYPE_bool:
     if (*static_cast<bool*>(data))
@@ -2781,17 +2779,17 @@ BuildDataSource(JSContext* cx,
     if (isImplicit)
       AppendString(result, ")");
 
     break;
   }
   case TYPE_array: {
     // Serialize each element of the array recursively. Each element must
     // be able to ImplicitConvert successfully.
-    JSObject* baseType = ArrayType::GetBaseType(typeObj);
+    RootedObject baseType(cx, ArrayType::GetBaseType(typeObj));
     AppendString(result, "[");
 
     size_t length = ArrayType::GetLength(typeObj);
     size_t elementSize = CType::GetSize(baseType);
     for (size_t i = 0; i < length; ++i) {
       char* element = static_cast<char*>(data) + elementSize * i;
       if (!BuildDataSource(cx, baseType, element, true, result))
         return false;
@@ -2826,17 +2824,18 @@ BuildDataSource(JSContext* cx,
 
       if (isImplicit) {
         AppendString(result, "\"");
         AppendString(result, entry->key);
         AppendString(result, "\": ");
       }
 
       char* fieldData = static_cast<char*>(data) + entry->value.mOffset;
-      if (!BuildDataSource(cx, entry->value.mType, fieldData, true, result))
+      RootedObject entryType(cx, entry->value.mType);
+      if (!BuildDataSource(cx, entryType, fieldData, true, result))
         return false;
 
       if (i + 1 != length)
         AppendString(result, ", ");
     }
 
     if (isImplicit)
       AppendString(result, "}");
@@ -2870,17 +2869,17 @@ ConstructAbstract(JSContext* cx,
 *******************************************************************************/
 
 JSBool
 CType::ConstructData(JSContext* cx,
                      unsigned argc,
                      jsval* vp)
 {
   // get the callee object...
-  JSObject* obj = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
+  RootedObject obj(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));
   if (!CType::IsCType(obj)) {
     JS_ReportError(cx, "not a CType");
     return JS_FALSE;
   }
 
   // How we construct the CData object depends on what type we represent.
   // An instance 'd' of a CData object of type 't' has:
   //   * [[Class]] "CData"
@@ -2900,50 +2899,52 @@ CType::ConstructData(JSContext* cx,
     return StructType::ConstructData(cx, obj, argc, vp);
   default:
     return ConstructBasic(cx, obj, argc, vp);
   }
 }
 
 JSBool
 CType::ConstructBasic(JSContext* cx,
-                      JSObject* obj,
+                      HandleObject obj,
                       unsigned argc,
                       jsval* vp)
 {
   if (argc > 1) {
     JS_ReportError(cx, "CType constructor takes zero or one argument");
     return JS_FALSE;
   }
 
   // construct a CData object
-  JSObject* result = CData::Create(cx, obj, NULL, NULL, true);
+  RootedObject result(cx, CData::Create(cx, obj, NULL, 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,
+              JSObject* dataProto_,
               TypeCode type,
-              JSString* name,
+              JSString* name_,
               jsval size,
               jsval align,
               ffi_type* ffiType)
 {
-  JSObject* parent = JS_GetParent(typeProto);
+  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,
   //     StructType}.prototype
   //   * A constructor which creates and returns a CData object, containing
@@ -2952,36 +2953,34 @@ CType::Create(JSContext* cx,
   //     * [[Class]] "CDataProto"
   //     * __proto__ === 'dataProto'; an object containing properties and
   //       functions common to all CData objects of types derived from
   //       'typeProto'. (For instance, this could be ctypes.CData.prototype
   //       for simple types, or something representing structs for StructTypes.)
   //     * 'constructor' property === 't'
   //     * Additional properties specified by 'ps', as appropriate for the
   //       specific type instance 't'.
-  JSObject* typeObj = JS_NewObject(cx, &sCTypeClass, typeProto, parent);
+  RootedObject typeObj(cx, JS_NewObject(cx, &sCTypeClass, typeProto, parent));
   if (!typeObj)
     return NULL;
-  js::AutoObjectRooter root(cx, typeObj);
 
   // Set up the reserved slots.
   JS_SetReservedSlot(typeObj, SLOT_TYPECODE, INT_TO_JSVAL(type));
   if (ffiType)
     JS_SetReservedSlot(typeObj, SLOT_FFITYPE, PRIVATE_TO_JSVAL(ffiType));
   if (name)
     JS_SetReservedSlot(typeObj, SLOT_NAME, STRING_TO_JSVAL(name));
   JS_SetReservedSlot(typeObj, SLOT_SIZE, size);
   JS_SetReservedSlot(typeObj, SLOT_ALIGN, align);
 
   if (dataProto) {
     // Set up the 'prototype' and 'prototype.constructor' properties.
-    JSObject* prototype = JS_NewObject(cx, &sCDataProtoClass, dataProto, parent);
+    RootedObject prototype(cx, JS_NewObject(cx, &sCDataProtoClass, dataProto, parent));
     if (!prototype)
       return NULL;
-    js::AutoObjectRooter protoroot(cx, prototype);
 
     if (!JS_DefineProperty(cx, prototype, "constructor", OBJECT_TO_JSVAL(typeObj),
            NULL, NULL, JSPROP_READONLY | JSPROP_PERMANENT))
       return NULL;
 
     // Set the 'prototype' object.
     //if (!JS_FreezeObject(cx, prototype)) // XXX fixme - see bug 541212!
     //  return NULL;
@@ -2996,34 +2995,36 @@ CType::Create(JSContext* cx,
   JS_ASSERT_IF(IsSizeDefined(typeObj),
                GetSize(typeObj) % GetAlignment(typeObj) == 0);
 
   return typeObj;
 }
 
 JSObject*
 CType::DefineBuiltin(JSContext* cx,
-                     JSObject* parent,
+                     JSObject* parent_,
                      const char* propName,
-                     JSObject* typeProto,
-                     JSObject* dataProto,
+                     JSObject* typeProto_,
+                     JSObject* dataProto_,
                      const char* name,
                      TypeCode type,
                      jsval size,
                      jsval align,
                      ffi_type* ffiType)
 {
-  JSString* nameStr = JS_NewStringCopyZ(cx, name);
+  RootedObject parent(cx, parent_);
+  RootedObject typeProto(cx, typeProto_);
+  RootedObject dataProto(cx, dataProto_);
+
+  RootedString nameStr(cx, JS_NewStringCopyZ(cx, name));
   if (!nameStr)
     return NULL;
-  js::AutoStringRooter nameRoot(cx, nameStr);
 
   // Create a new CType object with the common properties and slots.
-  JSObject* typeObj = Create(cx, typeProto, dataProto, type, nameStr, size,
-                        align, ffiType);
+  RootedObject typeObj(cx, Create(cx, typeProto, dataProto, type, nameStr, size, align, ffiType));
   if (!typeObj)
     return NULL;
 
   // Define the CType as a 'propName' property on 'parent'.
   if (!JS_DefineProperty(cx, parent, propName, OBJECT_TO_JSVAL(typeObj),
          NULL, NULL, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT))
     return NULL;
 
@@ -3316,31 +3317,30 @@ CType::GetFFIType(JSContext* cx, JSObjec
 
   if (!result)
     return NULL;
   JS_SetReservedSlot(obj, SLOT_FFITYPE, PRIVATE_TO_JSVAL(result.get()));
   return result.forget();
 }
 
 JSString*
-CType::GetName(JSContext* cx, JSObject* obj)
+CType::GetName(JSContext* cx, JSHandleObject obj)
 {
   JS_ASSERT(CType::IsCType(obj));
 
   jsval string = JS_GetReservedSlot(obj, SLOT_NAME);
-  if (JSVAL_IS_VOID(string)) {
-    // Build the type name lazily.
-    JSString* name = BuildTypeName(cx, obj);
-    if (!name)
-      return NULL;
-    JS_SetReservedSlot(obj, SLOT_NAME, STRING_TO_JSVAL(name));
-    return name;
-  }
-
-  return JSVAL_TO_STRING(string);
+  if (!JSVAL_IS_VOID(string))
+    return JSVAL_TO_STRING(string);
+
+  // Build the type name lazily.
+  JSString* name = BuildTypeName(cx, obj);
+  if (!name)
+    return NULL;
+  JS_SetReservedSlot(obj, SLOT_NAME, STRING_TO_JSVAL(name));
+  return name;
 }
 
 JSObject*
 CType::GetProtoFromCtor(JSObject* obj, CTypeProtoSlot slot)
 {
   // Get ctypes.{Pointer,Array,Struct}Type.prototype from a reserved slot
   // on the type constructor.
   jsval protoslot = js::GetFunctionNativeReserved(obj, SLOT_FN_CTORPROTO);
@@ -3459,17 +3459,17 @@ CType::CreateArray(JSContext* cx, unsign
 
   JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(result));
   return JS_TRUE;
 }
 
 JSBool
 CType::ToString(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 (!CType::IsCType(obj) && !CType::IsCTypeProto(obj)) {
     JS_ReportError(cx, "not a CType");
     return JS_FALSE;
   }
 
   // Create the appropriate string depending on whether we're sCTypeClass or
@@ -3633,18 +3633,20 @@ PointerType::Create(JSContext* cx, unsig
   if (!result)
     return JS_FALSE;
 
   JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(result));
   return JS_TRUE;
 }
 
 JSObject*
-PointerType::CreateInternal(JSContext* cx, JSObject* baseType)
-{
+PointerType::CreateInternal(JSContext* cx, JSObject* baseType_)
+{
+  RootedObject baseType(cx, 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 ?
@@ -3666,31 +3668,31 @@ PointerType::CreateInternal(JSContext* c
   // Finally, cache our newly-created PointerType on our pointed-to CType.
   JS_SetReservedSlot(baseType, SLOT_PTR, OBJECT_TO_JSVAL(typeObj));
 
   return typeObj;
 }
 
 JSBool
 PointerType::ConstructData(JSContext* cx,
-                           JSObject* obj,
+                           JSHandleObject obj,
                            unsigned argc,
                            jsval* vp)
 {
   if (!CType::IsCType(obj) || CType::GetTypeCode(obj) != TYPE_pointer) {
     JS_ReportError(cx, "not a PointerType");
     return JS_FALSE;
   }
 
   if (argc > 3) {
     JS_ReportError(cx, "constructor takes 0, 1, 2, or 3 arguments");
     return JS_FALSE;
   }
 
-  JSObject* result = CData::Create(cx, obj, NULL, NULL, true);
+  RootedObject result(cx, CData::Create(cx, obj, NULL, 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)
@@ -3703,17 +3705,17 @@ PointerType::ConstructData(JSContext* cx
   //
   // Case 1 - Null pointer
   //
   if (argc == 0)
     return JS_TRUE;
 
   // Analyze the arguments a bit to decide what to do next.
   jsval* argv = JS_ARGV(cx, vp);
-  JSObject* baseObj = PointerType::GetBaseType(obj);
+  RootedObject baseObj(cx, PointerType::GetBaseType(obj));
   bool looksLikeClosure = CType::GetTypeCode(baseObj) == TYPE_function &&
                           argv[0].isObject() &&
                           JS_ObjectIsCallable(cx, &argv[0].toObject());
 
   //
   // Case 2 - Initialized pointer
   //
   if (!looksLikeClosure) {
@@ -3726,35 +3728,35 @@ PointerType::ConstructData(JSContext* cx
 
   //
   // Case 3 - Closure
   //
 
   // The second argument is an optional 'this' parameter with which to invoke
   // the given js function. Callers may leave this blank, or pass null if they
   // wish to pass the third argument.
-  JSObject* thisObj = NULL;
+  RootedObject thisObj(cx, NULL);
   if (argc >= 2) {
     if (JSVAL_IS_NULL(argv[1])) {
       thisObj = NULL;
     } else if (!JSVAL_IS_PRIMITIVE(argv[1])) {
       thisObj = JSVAL_TO_OBJECT(argv[1]);
-    } else if (!JS_ValueToObject(cx, argv[1], &thisObj)) {
+    } else if (!JS_ValueToObject(cx, argv[1], thisObj.address())) {
       return JS_FALSE;
     }
   }
 
   // The third argument is an optional error sentinel that js-ctypes will return
   // if an exception is raised while executing the closure. The type must match
   // the return type of the callback.
   jsval errVal = JSVAL_VOID;
   if (argc == 3)
     errVal = argv[2];
 
-  JSObject* fnObj = JSVAL_TO_OBJECT(argv[0]);
+  RootedObject fnObj(cx, JSVAL_TO_OBJECT(argv[0]));
   return FunctionType::ConstructData(cx, baseObj, result, fnObj, thisObj, errVal);
 }
 
 JSObject*
 PointerType::GetBaseType(JSObject* obj)
 {
   JS_ASSERT(CType::GetTypeCode(obj) == TYPE_pointer);
 
@@ -3956,20 +3958,22 @@ ArrayType::Create(JSContext* cx, unsigne
     return JS_FALSE;
 
   JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(result));
   return JS_TRUE;
 }
 
 JSObject*
 ArrayType::CreateInternal(JSContext* cx,
-                          JSObject* baseType,
+                          JSObject* 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);
 
   // 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.
@@ -4007,20 +4011,22 @@ ArrayType::CreateInternal(JSContext* cx,
   // Set the length.
   JS_SetReservedSlot(typeObj, SLOT_LENGTH, lengthVal);
 
   return typeObj;
 }
 
 JSBool
 ArrayType::ConstructData(JSContext* cx,
-                         JSObject* obj,
+                         JSHandleObject obj_,
                          unsigned argc,
                          jsval* 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
   // if we get a length argument instead.
   bool convertObject = argc == 1;
@@ -4034,17 +4040,17 @@ ArrayType::ConstructData(JSContext* cx,
     }
 
   } else {
     if (argc != 1) {
       JS_ReportError(cx, "constructor takes one argument");
       return JS_FALSE;
     }
 
-    JSObject* baseType = GetBaseType(obj);
+    RootedObject baseType(cx, GetBaseType(obj));
 
     jsval* argv = JS_ARGV(cx, vp);
     size_t length;
     if (jsvalToSize(cx, argv[0], false, &length)) {
       // Have a length, rather than an object to initialize from.
       convertObject = false;
 
     } else if (!JSVAL_IS_PRIMITIVE(argv[0])) {
@@ -4320,28 +4326,28 @@ ArrayType::AddressOfElement(JSContext* c
   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_array) {
     JS_ReportError(cx, "not an ArrayType");
     return JS_FALSE;
   }
 
   if (argc != 1) {
     JS_ReportError(cx, "addressOfElement takes one argument");
     return JS_FALSE;
   }
 
-  JSObject* baseType = GetBaseType(typeObj);
+  RootedObject baseType(cx, GetBaseType(typeObj));
   JSObject* pointerType = 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);
   if (!result)
@@ -4374,17 +4380,17 @@ ArrayType::AddressOfElement(JSContext* c
 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;
   }
 
-  JSObject* obj = JSVAL_TO_OBJECT(val);
+  RootedObject obj(cx, JSVAL_TO_OBJECT(val));
   JSObject* iter = JS_NewPropertyIterator(cx, obj);
   if (!iter)
     return NULL;
   js::AutoObjectRooter iterroot(cx, iter);
 
   jsid nameid;
   if (!JS_NextProperty(cx, iter, &nameid))
     return NULL;
@@ -4430,20 +4436,22 @@ ExtractStructField(JSContext* cx, jsval 
   return JSID_TO_FLAT_STRING(nameid);
 }
 
 // For a struct field with 'name' and 'type', add an element of the form
 // { name : type }.
 static JSBool
 AddFieldToArray(JSContext* cx,
                 jsval* element,
-                JSFlatString* name,
-                JSObject* typeObj)
-{
-  JSObject* fieldObj = JS_NewObject(cx, NULL, NULL, NULL);
+                JSFlatString* name_,
+                JSObject* typeObj_)
+{
+  RootedObject typeObj(cx, typeObj_);
+  Rooted<JSFlatString*> name(cx, name_);
+  RootedObject fieldObj(cx, JS_NewObject(cx, NULL, NULL, NULL));
   if (!fieldObj)
     return false;
 
   *element = OBJECT_TO_JSVAL(fieldObj);
 
   if (!JS_DefineUCProperty(cx, fieldObj,
          name->chars(), name->length(),
          OBJECT_TO_JSVAL(typeObj), NULL, NULL,
@@ -4494,18 +4502,21 @@ StructType::Create(JSContext* cx, unsign
       return JS_FALSE;
   }
 
   JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(result));
   return JS_TRUE;
 }
 
 JSBool
-StructType::DefineInternal(JSContext* cx, JSObject* typeObj, JSObject* fieldsObj)
-{
+StructType::DefineInternal(JSContext* cx, JSObject* typeObj_, JSObject* fieldsObj_)
+{
+  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);
 
   // Set up the 'prototype' and 'prototype.constructor' properties.
@@ -4539,18 +4550,18 @@ StructType::DefineInternal(JSContext* cx
     structSize = 0;
     structAlign = 0;
 
     for (uint32_t i = 0; i < len; ++i) {
       js::AutoValueRooter item(cx);
       if (!JS_GetElement(cx, fieldsObj, i, item.jsval_addr()))
         return JS_FALSE;
 
-      JSObject* fieldType = NULL;
-      JSFlatString* name = ExtractStructField(cx, item.jsval_value(), &fieldType);
+      RootedObject fieldType(cx, NULL);
+      JSFlatString* name = ExtractStructField(cx, item.jsval_value(), fieldType.address());
       if (!name)
         return JS_FALSE;
       fieldRootsArray[i] = OBJECT_TO_JSVAL(fieldType);
 
       // Make sure each field name is unique, and add it to the hash.
       FieldInfoHash::AddPtr entryPtr = fields->lookupForAdd(name);
       if (entryPtr) {
         JS_ReportError(cx, "struct fields must have unique names");
@@ -4721,17 +4732,17 @@ StructType::Define(JSContext* cx, unsign
     return JS_FALSE;
   }
 
   return DefineInternal(cx, obj, JSVAL_TO_OBJECT(arg));
 }
 
 JSBool
 StructType::ConstructData(JSContext* cx,
-                          JSObject* obj,
+                          HandleObject obj,
                           unsigned argc,
                           jsval* vp)
 {
   if (!CType::IsCType(obj) || CType::GetTypeCode(obj) != TYPE_struct) {
     JS_ReportError(cx, "not a StructType");
     return JS_FALSE;
   }
 
@@ -4850,17 +4861,17 @@ StructType::BuildFieldsArray(JSContext* 
   for (FieldInfoHash::Range r = fields->all(); !r.empty(); r.popFront()) {
     const FieldInfoHash::Entry& entry = r.front();
     // Add the field descriptor to the array.
     if (!AddFieldToArray(cx, &fieldsVec[entry.value.mIndex],
                          entry.key, entry.value.mType))
       return NULL;
   }
 
-  JSObject* fieldsProp = JS_NewArrayObject(cx, len, fieldsVec.begin());
+  RootedObject fieldsProp(cx, JS_NewArrayObject(cx, len, fieldsVec.begin()));
   if (!fieldsProp)
     return NULL;
 
   // Seal the fields array.
   if (!JS_FreezeObject(cx, fieldsProp))
     return NULL;
 
   return fieldsProp;
@@ -5375,20 +5386,20 @@ FunctionType::CreateInternal(JSContext* 
   return typeObj;
 }
 
 // Construct a function pointer to a JS function (see CClosure::Create()).
 // Regular function pointers are constructed directly in
 // PointerType::ConstructData().
 JSBool
 FunctionType::ConstructData(JSContext* cx,
-                            JSObject* typeObj,
-                            JSObject* dataObj,
-                            JSObject* fnObj,
-                            JSObject* thisObj,
+                            JSHandleObject typeObj,
+                            JSHandleObject dataObj,
+                            JSHandleObject fnObj,
+                            JSHandleObject thisObj,
                             jsval errVal)
 {
   JS_ASSERT(CType::GetTypeCode(typeObj) == TYPE_function);
 
   PRFuncPtr* data = static_cast<PRFuncPtr*>(CData::GetData(dataObj));
 
   FunctionInfo* fninfo = FunctionType::GetFunctionInfo(typeObj);
   if (fninfo->mIsVariadic) {
@@ -5651,17 +5662,17 @@ FunctionType::ArgTypesGetter(JSContext* 
   // Prepare a new array.
   Array<jsval, 16> vec;
   if (!vec.resize(len))
     return JS_FALSE;
 
   for (size_t i = 0; i < len; ++i)
     vec[i] = OBJECT_TO_JSVAL(fninfo->mArgTypes[i]);
 
-  JSObject* argTypes = JS_NewArrayObject(cx, len, vec.begin());
+  RootedObject argTypes(cx, JS_NewArrayObject(cx, len, vec.begin()));
   if (!argTypes)
     return JS_FALSE;
 
   // Seal and cache it.
   if (!JS_FreezeObject(cx, argTypes))
     return JS_FALSE;
   JS_SetReservedSlot(obj, SLOT_ARGS_T, OBJECT_TO_JSVAL(argTypes));
 
@@ -5702,22 +5713,25 @@ FunctionType::IsVariadicGetter(JSContext
 }
 
 /*******************************************************************************
 ** CClosure implementation
 *******************************************************************************/
 
 JSObject*
 CClosure::Create(JSContext* cx,
-                 JSObject* typeObj,
-                 JSObject* fnObj,
-                 JSObject* thisObj,
+                 JSObject* typeObj_,
+                 JSObject* fnObj_,
+                 JSObject* 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);
   if (!result)
     return NULL;
   js::AutoObjectRooter root(cx, result);
 
   // Get the FunctionInfo from the FunctionType.
@@ -5853,19 +5867,19 @@ CClosure::ClosureStub(ffi_cif* cif, void
   JS_ASSERT(cif);
   JS_ASSERT(result);
   JS_ASSERT(args);
   JS_ASSERT(userData);
 
   // Retrieve the essentials from our closure object.
   ClosureInfo* cinfo = static_cast<ClosureInfo*>(userData);
   JSContext* cx = cinfo->cx;
-  JSObject* typeObj = cinfo->typeObj;
-  JSObject* thisObj = cinfo->thisObj;
-  JSObject* jsfnObj = cinfo->jsfnObj;
+  RootedObject typeObj(cx, cinfo->typeObj);
+  RootedObject thisObj(cx, cinfo->thisObj);
+  RootedObject jsfnObj(cx, cinfo->jsfnObj);
 
   JS_AbortIfWrongThread(JS_GetRuntime(cx));
 
   JSAutoRequest ar(cx);
 
   JSAutoEnterCompartment ac;
   if (!ac.enter(cx, jsfnObj))
     return;
@@ -6166,17 +6180,17 @@ CData::ValueSetter(JSContext* cx, JSHand
 JSBool
 CData::Address(JSContext* cx, unsigned argc, jsval* vp)
 {
   if (argc != 0) {
     JS_ReportError(cx, "address takes zero arguments");
     return JS_FALSE;
   }
 
-  JSObject* obj = JS_THIS_OBJECT(cx, vp);
+  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);
@@ -6360,17 +6374,17 @@ CData::ReadString(JSContext* cx, unsigne
   if (!result)
     return JS_FALSE;
 
   JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(result));
   return JS_TRUE;
 }
 
 JSString *
-CData::GetSourceString(JSContext *cx, JSObject *typeObj, void *data)
+CData::GetSourceString(JSContext *cx, JSHandleObject typeObj, void *data)
 {
   // Walk the types, building up the toSource() string.
   // First, we build up the type expression:
   // 't.ptr' for pointers;
   // 't.array([n])' for arrays;
   // 'n' for structs, where n = t.name, the struct's name. (We assume this is
   // bound to a variable in the current scope.)
   AutoString source;
@@ -6397,17 +6411,17 @@ CData::ToSource(JSContext* cx, unsigned 
     return JS_FALSE;
   if (!CData::IsCData(obj) && !CData::IsCDataProto(obj)) {
     JS_ReportError(cx, "not a CData");
     return JS_FALSE;
   }
 
   JSString* result;
   if (CData::IsCData(obj)) {
-    JSObject* typeObj = CData::GetCType(obj);
+    RootedObject typeObj(cx, CData::GetCType(obj));
     void* data = CData::GetData(obj);
 
     result = CData::GetSourceString(cx, typeObj, data);
   } else {
     result = JS_NewStringCopyZ(cx, "[CData proto object]");
   }
 
   if (!result)
@@ -6442,32 +6456,32 @@ CData::LastErrorGetter(JSContext* cx, JS
   *vp = JS_GetReservedSlot(obj, SLOT_LASTERROR);
   return JS_TRUE;
 }
 #endif // defined(XP_WIN)
 
 JSBool
 CDataFinalizer::Methods::ToSource(JSContext *cx, unsigned argc, jsval *vp)
 {
-  JSObject* objThis = JS_THIS_OBJECT(cx, vp);
+  RootedObject objThis(cx, JS_THIS_OBJECT(cx, vp));
   if (!objThis)
     return JS_FALSE;
   if (!CDataFinalizer::IsCDataFinalizer(objThis)) {
     JS_ReportError(cx, "not a CDataFinalizer");
     return JS_FALSE;
   }
 
   CDataFinalizer::Private *p = (CDataFinalizer::Private *)
     JS_GetPrivate(objThis);
 
   JSString *strMessage;
   if (!p) {
     strMessage = JS_NewStringCopyZ(cx, "ctypes.CDataFinalizer()");
   } else {
-    JSObject *objType = CDataFinalizer::GetCType(cx, objThis);
+    RootedObject objType(cx, CDataFinalizer::GetCType(cx, objThis));
     if (!objType) {
       JS_ReportError(cx, "CDataFinalizer has no type");
       return JS_FALSE;
     }
 
     AutoString source;
     AppendString(source, "ctypes.CDataFinalizer(");
     JSString *srcValue = CData::GetSourceString(cx, objType, p->cargs);
@@ -6477,19 +6491,18 @@ CDataFinalizer::Methods::ToSource(JSCont
     AppendString(source, srcValue);
     AppendString(source, ", ");
     jsval valCodePtrType = JS_GetReservedSlot(objThis,
                                               SLOT_DATAFINALIZER_CODETYPE);
     if (JSVAL_IS_PRIMITIVE(valCodePtrType)) {
       return JS_FALSE;
     }
 
-    JSString *srcDispose =
-      CData::GetSourceString(cx, JSVAL_TO_OBJECT(valCodePtrType),
-                             &(p->code));
+    RootedObject typeObj(cx, JSVAL_TO_OBJECT(valCodePtrType));
+    JSString *srcDispose = CData::GetSourceString(cx, typeObj, &(p->code));
     if (!srcDispose) {
       return JS_FALSE;
     }
 
     AppendString(source, srcDispose);
     AppendString(source, ")");
     strMessage = NewUCString(cx, source);
   }
@@ -6673,17 +6686,18 @@ CDataFinalizer::Construct(JSContext* cx,
     FunctionType::GetFunctionInfo(objCodeType);
   MOZ_ASSERT(funInfoFinalizer);
 
   if ((funInfoFinalizer->mArgTypes.length() != 1)
       || (funInfoFinalizer->mIsVariadic)) {
     return TypeError(cx, "a function accepting exactly one argument",
                      OBJECT_TO_JSVAL(objCodeType));
   }
-  JSObject *objArgType = funInfoFinalizer->mArgTypes[0];
+  RootedObject objArgType(cx, funInfoFinalizer->mArgTypes[0]);
+  RootedObject returnType(cx, funInfoFinalizer->mReturnType);
 
   // Invariant: At this stage, we know that funInfoFinalizer->mIsVariadic
   // is |false|. Therefore, funInfoFinalizer->mCIF has already been initialized.
 
   bool freePointer = false;
 
   // 3. Perform dynamic cast of |argv[0]| into |objType|, store it in |cargs|
 
@@ -6703,17 +6717,16 @@ CDataFinalizer::Construct(JSContext* cx,
   if (freePointer) {
     // Note: We could handle that case, if necessary.
     JS_ReportError(cx, "Internal Error during CDataFinalizer. Object cannot be represented");
     return JS_FALSE;
   }
 
   // 4. Prepare buffer for holding return value
 
-  JSObject *returnType = funInfoFinalizer->mReturnType;
   ScopedFreePtr<void> rvalue;
   if (CType::GetTypeCode(returnType) != TYPE_void_t) {
     rvalue = malloc(Align(CType::GetSize(returnType),
                           sizeof(ffi_arg)));
   } //Otherwise, simply do not allocate
 
   // 5. Create |objResult|
 
--- a/js/src/ctypes/CTypes.h
+++ b/js/src/ctypes/CTypes.h
@@ -314,25 +314,25 @@ struct ClosureInfo
       rt->free_(errResult);
   };
 };
 
 bool IsCTypesGlobal(JSObject* obj);
 
 JSCTypesCallbacks* GetCallbacks(JSObject* obj);
 
-JSBool InitTypeClasses(JSContext* cx, JSObject* parent);
+JSBool InitTypeClasses(JSContext* cx, JSHandleObject parent);
 
 JSBool ConvertToJS(JSContext* cx, JSObject* typeObj, JSObject* 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, JSObject* targetType,
+JSBool ExplicitConvert(JSContext* cx, jsval val, JSHandleObject targetType,
   void* buffer);
 
 /*******************************************************************************
 ** JSClass reserved slot definitions
 *******************************************************************************/
 
 enum CTypesGlobalSlot {
   SLOT_CALLBACKS = 0, // pointer to JSCTypesCallbacks struct
@@ -438,17 +438,17 @@ namespace CType {
   bool IsCTypeProto(JSObject* obj);
   TypeCode GetTypeCode(JSObject* typeObj);
   bool TypesEqual(JSObject* t1, JSObject* t2);
   size_t GetSize(JSObject* obj);
   bool GetSafeSize(JSObject* obj, size_t* result);
   bool IsSizeDefined(JSObject* obj);
   size_t GetAlignment(JSObject* obj);
   ffi_type* GetFFIType(JSContext* cx, JSObject* obj);
-  JSString* GetName(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);
 
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -17,22 +17,22 @@
 #include "jsinferinlines.h"
 
 #include "frontend/TreeContext-inl.h"
 
 using namespace js;
 using namespace js::frontend;
 
 bool
-MarkInnerAndOuterFunctions(JSContext *cx, JSScript* script_)
+MarkInnerAndOuterFunctions(JSContext *cx, JSScript* script)
 {
-    Rooted<JSScript*> script(cx, script_);
+    AssertRootingUnnecessary safe(cx);
 
     Vector<JSScript *, 16> worklist(cx);
-    if (!worklist.append(script.reference()))
+    if (!worklist.append(script))
         return false;
 
     while (worklist.length()) {
         JSScript *outer = worklist.back();
         worklist.popBack();
 
         if (outer->hasObjects()) {
             ObjectArray *arr = outer->objects();
@@ -61,24 +61,26 @@ MarkInnerAndOuterFunctions(JSContext *cx
             }
         }
     }
 
     return true;
 }
 
 JSScript *
-frontend::CompileScript(JSContext *cx, JSObject *scopeChain, StackFrame *callerFrame,
+frontend::CompileScript(JSContext *cx, HandleObject scopeChain, StackFrame *callerFrame,
                         JSPrincipals *principals, JSPrincipals *originPrincipals,
                         bool compileAndGo, bool noScriptRval, bool needScriptGlobal,
                         const jschar *chars, size_t length,
                         const char *filename, unsigned lineno, JSVersion version,
-                        JSString *source /* = NULL */,
+                        JSString *source_ /* = NULL */,
                         unsigned staticLevel /* = 0 */)
 {
+    RootedString source(cx, source_);
+
     class ProbesManager
     {
         const char* filename;
         unsigned lineno;
 
       public:
         ProbesManager(const char *f, unsigned l) : filename(f), lineno(l) {
             Probes::compileScriptBegin(filename, lineno);
@@ -109,17 +111,17 @@ frontend::CompileScript(JSContext *cx, J
     GlobalObject *globalObject = needScriptGlobal ? GetCurrentGlobal(cx) : NULL;
     Rooted<JSScript*> script(cx);
     script = JSScript::Create(cx, savedCallerFun, principals, originPrincipals, compileAndGo,
                               noScriptRval, globalObject, version, staticLevel);
     if (!script)
         return NULL;
 
     // We can specialize a bit for the given scope chain if that scope chain is the global object.
-    JSObject *globalScope = scopeChain && scopeChain == &scopeChain->global() ? scopeChain : NULL;
+    JSObject *globalScope = scopeChain && scopeChain == &scopeChain->global() ? (JSObject*) scopeChain : NULL;
     JS_ASSERT_IF(globalScope, globalScope->isNative());
     JS_ASSERT_IF(globalScope, JSCLASS_HAS_GLOBAL_FLAG_AND_SLOTS(globalScope->getClass()));
 
     BytecodeEmitter bce(/* parent = */ NULL, &parser, &sc, script, callerFrame, !!globalScope,
                         lineno);
     if (!bce.init())
         return NULL;
 
@@ -237,17 +239,17 @@ frontend::CompileScript(JSContext *cx, J
         return NULL;
 
     return script;
 }
 
 // Compile a JS function body, which might appear as the value of an event
 // handler attribute in an HTML <INPUT> tag, or in a Function() constructor.
 bool
-frontend::CompileFunctionBody(JSContext *cx, JSFunction *fun,
+frontend::CompileFunctionBody(JSContext *cx, HandleFunction fun,
                               JSPrincipals *principals, JSPrincipals *originPrincipals,
                               Bindings *bindings, const jschar *chars, size_t length,
                               const char *filename, unsigned lineno, JSVersion version)
 {
     Parser parser(cx, principals, originPrincipals, chars, length, filename, lineno, version,
                   /* foldConstants = */ true, /* compileAndGo = */ false);
     if (!parser.init())
         return false;
--- a/js/src/frontend/BytecodeCompiler.h
+++ b/js/src/frontend/BytecodeCompiler.h
@@ -9,25 +9,25 @@
 #define BytecodeCompiler_h__
 
 #include "frontend/Parser.h"
 
 namespace js {
 namespace frontend {
 
 JSScript *
-CompileScript(JSContext *cx, JSObject *scopeChain, StackFrame *callerFrame,
+CompileScript(JSContext *cx, HandleObject scopeChain, StackFrame *callerFrame,
               JSPrincipals *principals, JSPrincipals *originPrincipals,
               bool compileAndGo, bool noScriptRval, bool needScriptGlobal,
               const jschar *chars, size_t length,
               const char *filename, unsigned lineno, JSVersion version,
-              JSString *source = NULL, unsigned staticLevel = 0);
+              JSString *source_ = NULL, unsigned staticLevel = 0);
 
 bool
-CompileFunctionBody(JSContext *cx, JSFunction *fun,
+CompileFunctionBody(JSContext *cx, HandleFunction fun,
                     JSPrincipals *principals, JSPrincipals *originPrincipals,
                     Bindings *bindings, const jschar *chars, size_t length,
                     const char *filename, unsigned lineno, JSVersion version);
 
 } /* namespace frontend */
 } /* namespace js */
 
 #endif /* BytecodeCompiler_h__ */
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -165,18 +165,20 @@ MarkRange(JSTracer *trc, size_t len, Hea
 }
 
 template <typename T>
 static void
 MarkRootRange(JSTracer *trc, size_t len, T **vec, const char *name)
 {
     JS_ROOT_MARKING_ASSERT(trc);
     for (size_t i = 0; i < len; ++i) {
-        JS_SET_TRACING_INDEX(trc, name, i);
-        MarkInternal(trc, &vec[i]);
+        if (vec[i]) {
+            JS_SET_TRACING_INDEX(trc, name, i);
+            MarkInternal(trc, &vec[i]);
+        }
     }
 }
 
 template <typename T>
 static bool
 IsMarked(T **thingp)
 {
     JS_ASSERT(thingp);
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -3322,34 +3322,38 @@ 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)
-{
+JS_NewObject(JSContext *cx, JSClass *jsclasp, JSObject *proto_, JSObject *parent_)
+{
+    RootedObject proto(cx, proto_);
+    RootedObject parent(cx, parent_);
+
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, proto, parent);
 
     Class *clasp = Valueify(jsclasp);
     if (!clasp)
         clasp = &ObjectClass;    /* default class is Object */
 
     JS_ASSERT(clasp != &FunctionClass);
     JS_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL));
 
     if (proto && !proto->setNewTypeUnknown(cx))
         return NULL;
 
     JSObject *obj = NewObjectWithClassProto(cx, clasp, proto, parent);
+    AssertRootingUnnecessary safe(cx);
     if (obj) {
         if (clasp->ext.equality)
             MarkTypeObjectFlags(cx, obj, OBJECT_FLAG_SPECIAL_EQUALITY);
         MarkTypeObjectUnknownProperties(cx, obj->type());
     }
 
     JS_ASSERT_IF(obj, obj->getParent());
     return obj;
@@ -3366,16 +3370,17 @@ JS_NewObjectWithGivenProto(JSContext *cx
     Class *clasp = Valueify(jsclasp);
     if (!clasp)
         clasp = &ObjectClass;    /* default class is Object */
 
     JS_ASSERT(clasp != &FunctionClass);
     JS_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL));
 
     JSObject *obj = NewObjectWithGivenProto(cx, clasp, proto, parent);
+    AssertRootingUnnecessary safe(cx);
     if (obj)
         MarkTypeObjectUnknownProperties(cx, obj->type());
     return obj;
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_NewObjectForConstructor(JSContext *cx, JSClass *clasp, const jsval *vp)
 {
@@ -3410,18 +3415,19 @@ JS_FreezeObject(JSContext *cx, JSObject 
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
 
     return obj->freeze(cx);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_DeepFreezeObject(JSContext *cx, JSObject *obj)
-{
+JS_DeepFreezeObject(JSContext *cx, JSObject *obj_)
+{
+    RootedObject obj(cx, obj_);
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
 
     /* Assume that non-extensible objects are already deep-frozen, to avoid divergence. */
     if (!obj->isExtensible())
         return true;
 
@@ -3436,32 +3442,32 @@ JS_DeepFreezeObject(JSContext *cx, JSObj
         if (!JS_DeepFreezeObject(cx, &v.toObject()))
             return false;
     }
 
     return true;
 }
 
 static JSBool
-LookupPropertyById(JSContext *cx, JSObject *obj, HandleId id, unsigned flags,
+LookupPropertyById(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
                    JSObject **objp, JSProperty **propp)
 {
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, id);
 
     JSAutoResolveFlags rf(cx, flags);
     return obj->lookupGeneric(cx, id, objp, propp);
 }
 
 #define AUTO_NAMELEN(s,n)   (((n) == (size_t)-1) ? js_strlen(s) : (n))
 
 static JSBool
-LookupResult(JSContext *cx, JSObject *obj, JSObject *obj2, jsid id,
-             JSProperty *prop, Value *vp)
+LookupResult(JSContext *cx, HandleObject obj, HandleObject obj2, jsid id,
+             JSProperty* prop, Value *vp)
 {
     if (!prop) {
         /* XXX bad API: no way to tell "not defined" from "void value" */
         vp->setUndefined();
         return JS_TRUE;
     }
 
     if (obj2->isNative()) {
@@ -3487,23 +3493,24 @@ LookupResult(JSContext *cx, JSObject *ob
     }
 
     /* 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)
+JS_LookupPropertyById(JSContext *cx, JSObject *obj_, jsid id_, jsval *vp)
 {
     RootedId id(cx, id_);
-
-    JSObject *obj2;
-    JSProperty *prop;
-    return LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &prop) &&
+    RootedObject obj(cx, obj_);
+    RootedObject obj2(cx);
+    JSProperty* prop;
+
+    return LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED, obj2.address(), &prop) &&
            LookupResult(cx, obj, obj2, id, prop, vp);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_LookupElement(JSContext *cx, JSObject *obj, uint32_t index, jsval *vp)
 {
     CHECK_REQUEST(cx);
     jsid id;
@@ -3515,58 +3522,64 @@ JS_LookupElement(JSContext *cx, JSObject
 JS_PUBLIC_API(JSBool)
 JS_LookupProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
 {
     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)
-{
+JS_LookupUCProperty(JSContext *cx, JSObject *obj_, const jschar *name, size_t namelen, jsval *vp)
+{
+    RootedObject obj(cx, obj_);
     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)
+                               JSObject **objp_, jsval *vp)
 {
     RootedObject obj(cx, obj_);
+    RootedObject objp(cx, *objp_);
     RootedId id(cx, id_);
-
-    JSBool ok;
-    JSProperty *prop;
+    JSProperty* prop;
 
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, id);
-    ok = obj->isNative()
-         ? LookupPropertyWithFlags(cx, obj, id, flags, objp, &prop)
-         : obj->lookupGeneric(cx, id, objp, &prop);
-    return ok && LookupResult(cx, obj, *objp, id, prop, vp);
+    if (!(obj->isNative()
+          ? LookupPropertyWithFlags(cx, obj, id, flags, objp.address(), &prop)
+          : obj->lookupGeneric(cx, id, objp.address(), &prop)))
+        return false;
+
+    if (!LookupResult(cx, obj, objp, id, prop, vp))
+        return false;
+
+    *objp_ = objp;
+    return true;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, const char *name, unsigned flags, jsval *vp)
 {
     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)
-{
+JS_HasPropertyById(JSContext *cx, JSObject *obj_, jsid id_, JSBool *foundp)
+{
+    RootedObject obj(cx, obj_);
     RootedId id(cx, id_);
-
-    JSObject *obj2;
-    JSProperty *prop;
+    RootedObject obj2(cx);
+    JSProperty* prop;
     JSBool ok = LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING,
-                                   &obj2, &prop);
+                                   obj2.address(), &prop);
     *foundp = (prop != NULL);
     return ok;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_HasElement(JSContext *cx, JSObject *obj, uint32_t index, JSBool *foundp)
 {
     AssertNoGC(cx);
@@ -3580,26 +3593,28 @@ JS_HasElement(JSContext *cx, JSObject *o
 JS_PUBLIC_API(JSBool)
 JS_HasProperty(JSContext *cx, JSObject *obj, const char *name, JSBool *foundp)
 {
     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)
-{
+JS_HasUCProperty(JSContext *cx, JSObject *obj_, const jschar *name, size_t namelen, JSBool *foundp)
+{
+    RootedObject obj(cx, obj_);
     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 *obj_, jsid id_, JSBool *foundp)
 {
     RootedId id(cx, id_);
+    RootedObject obj(cx, obj_);
 
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, id);
 
     if (!obj->isNative()) {
         JSObject *obj2;
         JSProperty *prop;
@@ -3630,19 +3645,20 @@ JS_AlreadyHasOwnElement(JSContext *cx, J
 JS_PUBLIC_API(JSBool)
 JS_AlreadyHasOwnProperty(JSContext *cx, JSObject *obj, const char *name, JSBool *foundp)
 {
     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 *obj_, const jschar *name, size_t namelen,
                            JSBool *foundp)
 {
+    RootedObject obj(cx, obj_);
     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)
@@ -3864,23 +3880,23 @@ JS_DefineProperties(JSContext *cx, JSObj
                             ps->flags, Shape::HAS_SHORTID, ps->tinyid);
         if (!ok)
             break;
     }
     return ok;
 }
 
 static JSBool
-GetPropertyDescriptorById(JSContext *cx, JSObject *obj, HandleId id, unsigned flags,
+GetPropertyDescriptorById(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
                           JSBool own, PropertyDescriptor *desc)
 {
-    JSObject *obj2;
+    RootedObject obj2(cx);
     JSProperty *prop;
 
-    if (!LookupPropertyById(cx, obj, id, flags, &obj2, &prop))
+    if (!LookupPropertyById(cx, obj, id, flags, obj2.address(), &prop))
         return JS_FALSE;
 
     if (!prop || (own && obj != obj2)) {
         desc->obj = NULL;
         desc->attrs = 0;
         desc->getter = NULL;
         desc->setter = NULL;
         desc->value.setUndefined();
@@ -3909,28 +3925,30 @@ 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 *obj_, jsid id_, unsigned flags,
                              JSPropertyDescriptor *desc)
 {
     RootedId id(cx, id_);
+    RootedObject obj(cx, obj_);
     return GetPropertyDescriptorById(cx, obj, id, flags, JS_FALSE, desc);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_GetPropertyAttrsGetterAndSetterById(JSContext *cx, JSObject *obj, jsid id_,
+JS_GetPropertyAttrsGetterAndSetterById(JSContext *cx, JSObject *obj_, jsid id_,
                                        unsigned *attrsp, JSBool *foundp,
                                        JSPropertyOp *getterp, JSStrictPropertyOp *setterp)
 {
+    RootedObject obj(cx, obj_);
     RootedId id(cx, id_);
     PropertyDescriptor desc;
     if (!GetPropertyDescriptorById(cx, obj, id, JSRESOLVE_QUALIFIED, JS_FALSE, &desc))
         return false;
 
     *attrsp = desc.attrs;
     *foundp = (desc.obj != NULL);
     if (getterp)
@@ -3945,40 +3963,42 @@ JS_GetPropertyAttributes(JSContext *cx, 
                          unsigned *attrsp, JSBool *foundp)
 {
     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 *obj_, const jschar *name, size_t namelen,
                            unsigned *attrsp, JSBool *foundp)
 {
+    RootedObject obj(cx, obj_);
     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,
                                    unsigned *attrsp, JSBool *foundp,
                                    JSPropertyOp *getterp, JSStrictPropertyOp *setterp)
 {
     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 *obj_,
                                      const jschar *name, size_t namelen,
                                      unsigned *attrsp, JSBool *foundp,
                                      JSPropertyOp *getterp, JSStrictPropertyOp *setterp)
 {
+    RootedObject obj(cx, obj_);
     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)
 {
@@ -3986,49 +4006,51 @@ JS_GetOwnPropertyDescriptor(JSContext *c
     CHECK_REQUEST(cx);
 
     Rooted<JSObject*> obj(cx, obj_);
     Rooted<jsid> id(cx, id_);
     return GetOwnPropertyDescriptor(cx, obj, id, vp);
 }
 
 static JSBool
-SetPropertyAttributesById(JSContext *cx, JSObject *obj, HandleId id, unsigned attrs, JSBool *foundp)
-{
-    JSObject *obj2;
+SetPropertyAttributesById(JSContext *cx, HandleObject obj, HandleId id, unsigned attrs, JSBool *foundp)
+{
+    RootedObject obj2(cx);
     JSProperty *prop;
 
-    if (!LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &prop))
+    if (!LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED, obj2.address(), &prop))
         return false;
     if (!prop || obj != obj2) {
         *foundp = false;
         return true;
     }
     Shape *shape = (Shape *) prop;
     JSBool ok = obj->isNative()
                 ? 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 *obj_, const char *name,
                          unsigned attrs, JSBool *foundp)
 {
+    RootedObject obj(cx, obj_);
     JSAtom *atom = js_Atomize(cx, name, strlen(name));
     Rooted<jsid> 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 *obj_, const jschar *name, size_t namelen,
                            unsigned attrs, JSBool *foundp)
 {
+    RootedObject obj(cx, obj_);
     JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
     Rooted<jsid> 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)
 {
@@ -4146,39 +4168,37 @@ JS_SetPropertyById(JSContext *cx, JSObje
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, id);
     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING);
     return obj->setGeneric(cx, id, vp, false);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_SetElement(JSContext *cx, JSObject *obj_, uint32_t index, jsval *vp)
-{
-    RootedObject obj(cx, obj_);
-
+JS_SetElement(JSContext *cx, JSObject *obj, uint32_t index, jsval *vp)
+{
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, *vp);
     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING);
     return obj->setElement(cx, index, vp, false);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_SetProperty(JSContext *cx, JSObject *obj_, const char *name, jsval *vp)
 {
     RootedObject obj(cx, obj_);
-
     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)
-{
+JS_SetUCProperty(JSContext *cx, JSObject *obj_, const jschar *name, size_t namelen, jsval *vp)
+{
+    RootedObject obj(cx, obj_);
     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)
 {
     AssertNoGC(cx);
@@ -4200,32 +4220,36 @@ JS_DeleteElement2(JSContext *cx, JSObjec
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
     return obj->deleteElement(cx, index, rval, false);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_DeleteProperty2(JSContext *cx, JSObject *obj, const char *name, jsval *rval)
-{
+JS_DeleteProperty2(JSContext *cx, JSObject *obj_, const char *name, jsval *rval)
+{
+    RootedObject obj(cx, obj_);
+
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
 
     JSAtom *atom = js_Atomize(cx, name, strlen(name));
     if (!atom)
         return false;
 
     return obj->deleteByValue(cx, StringValue(atom), rval, false);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_DeleteUCProperty2(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen, jsval *rval)
-{
+JS_DeleteUCProperty2(JSContext *cx, JSObject *obj_, const jschar *name, size_t namelen, jsval *rval)
+{
+    RootedObject obj(cx, obj_);
+
     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;
 
@@ -4350,27 +4374,29 @@ 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)
-{
+JS_NewPropertyIterator(JSContext *cx, JSObject *obj_)
+{
+    RootedObject obj(cx, obj_);
     JSObject *iterobj;
     void *pdata;
     int index;
     JSIdArray *ida;
 
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     iterobj = NewObjectWithClassProto(cx, &prop_iter_class, NULL, obj);
+    AssertRootingUnnecessary safe(cx);
     if (!iterobj)
         return NULL;
 
     if (obj->isNative()) {
         /* Native case: start with the last property in obj. */
         pdata = (void *)obj->lastProperty();
         index = -1;
     } else {
@@ -4391,16 +4417,17 @@ JS_NewPropertyIterator(JSContext *cx, JS
     iterobj->setPrivate(pdata);
     iterobj->setSlot(JSSLOT_ITER_INDEX, Int32Value(index));
     return iterobj;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp)
 {
+    AssertRootingUnnecessary safe(cx);
     int32_t i;
     const Shape *shape;
     JSIdArray *ida;
 
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, iterobj);
     i = iterobj->getSlot(JSSLOT_ITER_INDEX).toInt32();
@@ -4794,21 +4821,20 @@ JS_DefineUCFunction(JSContext *cx, JSObj
     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,
-                    unsigned nargs, unsigned attrs)
+                      unsigned nargs, unsigned attrs)
 {
     RootedObject obj(cx, obj_);
     RootedId id(cx, id_);
-
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     return js_DefineFunction(cx, obj, id, call, nargs, attrs);
 }
 
 extern JS_PUBLIC_API(JSBool)
@@ -4835,21 +4861,22 @@ struct AutoLastFrameCheck {
     }
 
   private:
     JSContext       *cx;
     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
 static JSScript *
-CompileUCScriptForPrincipalsCommon(JSContext *cx, JSObject *obj,
+CompileUCScriptForPrincipalsCommon(JSContext *cx, JSObject *obj_,
                                    JSPrincipals *principals, JSPrincipals *originPrincipals,
                                    const jschar *chars, size_t length,
                                    const char *filename, unsigned lineno, JSVersion version)
 {
+    RootedObject obj(cx, obj_);
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, principals);
     AutoLastFrameCheck lfc(cx);
 
     bool compileAndGo = cx->hasRunOption(JSOPTION_COMPILE_N_GO);
     bool noScriptRval = cx->hasRunOption(JSOPTION_NO_SCRIPT_RVAL);
@@ -4908,21 +4935,23 @@ JS_CompileScriptForPrincipalsVersion(JSC
                                      const char *filename, unsigned lineno,
                                      JSVersion version)
 {
     AutoVersionAPI ava(cx, version);
     return JS_CompileScriptForPrincipals(cx, obj, principals, bytes, length, filename, lineno);
 }
 
 JS_PUBLIC_API(JSScript *)
-JS_CompileScriptForPrincipals(JSContext *cx, JSObject *obj,
+JS_CompileScriptForPrincipals(JSContext *cx, JSObject *obj_,
                               JSPrincipals *principals,
                               const char *bytes, size_t length,
                               const char *filename, unsigned lineno)
 {
+    RootedObject obj(cx, obj_);
+
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
 
     jschar *chars = InflateString(cx, bytes, &length);
     if (!chars)
         return NULL;
     JSScript *script =
@@ -4935,18 +4964,20 @@ JS_PUBLIC_API(JSScript *)
 JS_CompileScript(JSContext *cx, JSObject *obj, const char *bytes, size_t length,
                  const char *filename, unsigned lineno)
 {
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     return JS_CompileScriptForPrincipals(cx, obj, NULL, bytes, length, filename, lineno);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_BufferIsCompilableUnit(JSContext *cx, JSBool bytes_are_utf8, JSObject *obj, const char *bytes, size_t length)
-{
+JS_BufferIsCompilableUnit(JSContext *cx, JSBool bytes_are_utf8, JSObject *obj_, const char *bytes, size_t length)
+{
+    RootedObject obj(cx, obj_);
+
     jschar *chars;
     JSBool result;
     JSExceptionState *exnState;
     JSErrorReporter older;
 
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
@@ -4991,19 +5022,21 @@ JS_BufferIsCompilableUnit(JSContext *cx,
 # define fast_getc getc_unlocked
 #elif defined(HAVE__GETC_NOLOCK)
 # define fast_getc _getc_nolock
 #else
 # define fast_getc getc
 #endif
 
 static JSScript *
-CompileUTF8FileHelper(JSContext *cx, JSObject *obj, JSPrincipals *principals,
+CompileUTF8FileHelper(JSContext *cx, JSObject *obj_, JSPrincipals *principals,
                       const char* filename, FILE *fp)
 {
+    RootedObject obj(cx, obj_);
+
     struct stat st;
     int ok = fstat(fileno(fp), &st);
     if (ok != 0)
         return NULL;
 
     char *buf = NULL;
     size_t len = st.st_size;
     size_t i = 0;
@@ -5061,18 +5094,20 @@ CompileUTF8FileHelper(JSContext *cx, JSO
         script = NULL;
     }
     cx->free_(buf);
     cx->free_(decodebuf);
     return script;
 }
 
 JS_PUBLIC_API(JSScript *)
-JS_CompileUTF8File(JSContext *cx, JSObject *obj, const char *filename)
-{
+JS_CompileUTF8File(JSContext *cx, JSObject *obj_, const char *filename)
+{
+    RootedObject obj(cx, obj_);
+
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     AutoLastFrameCheck lfc(cx);
 
     FILE *fp;
     if (!filename || strcmp(filename, "-") == 0) {
@@ -5154,17 +5189,17 @@ CompileUCFunctionForPrincipalsCommon(JSC
     Bindings bindings;
     for (unsigned i = 0; i < nargs; i++) {
         uint16_t dummy;
         RootedAtom argAtom(cx, js_Atomize(cx, argnames[i], strlen(argnames[i])));
         if (!argAtom || !bindings.addArgument(cx, argAtom, &dummy))
             return NULL;
     }
 
-    JSFunction *fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, obj, funAtom);
+    RootedFunction fun(cx, js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, obj, funAtom));
     if (!fun)
         return NULL;
 
     if (!frontend::CompileFunctionBody(cx, fun, principals, NULL, &bindings,
                                        chars, length, filename, lineno, version))
     {
         return NULL;
     }
@@ -5209,22 +5244,24 @@ JS_CompileUCFunction(JSContext *cx, JSOb
                      const char *filename, unsigned lineno)
 {
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     return JS_CompileUCFunctionForPrincipals(cx, obj, NULL, name, nargs, argnames,
                                              chars, length, filename, lineno);
 }
 
 JS_PUBLIC_API(JSFunction *)
-JS_CompileFunctionForPrincipals(JSContext *cx, JSObject *obj,
+JS_CompileFunctionForPrincipals(JSContext *cx, JSObject *obj_,
                                 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_);
+
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     jschar *chars = InflateString(cx, bytes, &length);
     if (!chars)
         return NULL;
     JSFunction *fun = JS_CompileUCFunctionForPrincipals(cx, obj, principals, name,
                                                         nargs, argnames, chars, length,
                                                         filename, lineno);
     cx->free_(chars);
@@ -5291,18 +5328,20 @@ JS_DecompileFunctionBody(JSContext *cx, 
     assertSameCompartment(cx, fun);
     return js_DecompileToString(cx, "JS_DecompileFunctionBody", fun,
                                 indent & ~JS_DONT_PRETTY_PRINT,
                                 !(indent & JS_DONT_PRETTY_PRINT),
                                 false, false, js_DecompileFunctionBody);
 }
 
 JS_NEVER_INLINE JS_PUBLIC_API(JSBool)
-JS_ExecuteScript(JSContext *cx, JSObject *obj, JSScript *scriptArg, jsval *rval)
-{
+JS_ExecuteScript(JSContext *cx, JSObject *obj, JSScript *scriptArg_, jsval *rval)
+{
+    RootedScript scriptArg(cx, scriptArg_);
+
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     if (cx->compartment != obj->compartment())
         *(volatile int *) 0 = 0xf0;
     AutoLastFrameCheck lfc(cx);
 
@@ -5312,18 +5351,17 @@ JS_ExecuteScript(JSContext *cx, JSObject
      * 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()) {
-        RootedScript scriptArgRoot(cx, scriptArg);
-        script = CloneScript(cx, scriptArgRoot);
+        script = CloneScript(cx, scriptArg);
         if (!script.get())
             return false;
     } else {
         script = scriptArg;
     }
 
     return Execute(cx, script.get(), *obj, rval);
 }
@@ -5406,20 +5444,22 @@ JS_EvaluateUCScript(JSContext *cx, JSObj
                     const char *filename, unsigned lineno, jsval *rval)
 {
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     return JS_EvaluateUCScriptForPrincipals(cx, obj, NULL, chars, length, filename, lineno, 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 *obj_, JSPrincipals *principals,
                                const char *bytes, unsigned nbytes,
                                const char *filename, unsigned lineno, jsval *rval)
 {
+    RootedObject obj(cx, obj_);
+
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     size_t length = nbytes;
     jschar *chars = InflateString(cx, bytes, &length);
     if (!chars)
         return JS_FALSE;
     JSBool ok = JS_EvaluateUCScriptForPrincipals(cx, obj, principals, chars, length,
                                                  filename, lineno, rval);
     cx->free_(chars);
@@ -6344,18 +6384,20 @@ JS_ObjectIsDate(JSContext *cx, JSObject 
 }
 
 /************************************************************************/
 
 /*
  * Regular Expressions.
  */
 JS_PUBLIC_API(JSObject *)
-JS_NewRegExpObject(JSContext *cx, JSObject *obj, char *bytes, size_t length, unsigned flags)
-{
+JS_NewRegExpObject(JSContext *cx, JSObject *obj_, char *bytes, size_t length, unsigned flags)
+{
+    RootedObject obj(cx, obj_);
+
     AssertNoGC(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);
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -1284,17 +1284,17 @@ JSObject::allocateSlowArrayElements(JSCo
     if (!header)
         return false;
 
     elements = header->elements();
     return true;
 }
 
 static bool
-AddLengthProperty(JSContext *cx, JSObject *obj)
+AddLengthProperty(JSContext *cx, HandleObject obj)
 {
     /*
      * Add the 'length' property for a newly created or converted slow array,
      * and update the elements to be an empty array owned by the object.
      * The shared emptyObjectElements singleton cannot be used for slow arrays,
      * as accesses to 'length' will use the elements header.
      */
 
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -1206,18 +1206,17 @@ JSFunction *
 js_NewFunction(JSContext *cx, JSObject *funobj, Native native, unsigned nargs,
                unsigned flags, HandleObject parent, JSAtom *atom_, js::gc::AllocKind kind)
 {
     JS_ASSERT(kind == JSFunction::FinalizeKind || kind == JSFunction::ExtendedFinalizeKind);
     JS_ASSERT(sizeof(JSFunction) <= gc::Arena::thingSize(JSFunction::FinalizeKind));
     JS_ASSERT(sizeof(FunctionExtended) <= gc::Arena::thingSize(JSFunction::ExtendedFinalizeKind));
 
     RootedAtom atom(cx, atom_);
-
-    JSFunction *fun;
+    RootedFunction fun(cx);
 
     if (funobj) {
         JS_ASSERT(funobj->isFunction());
         JS_ASSERT(funobj->getParent() == parent);
     } else {
         funobj = NewObjectWithClassProto(cx, &FunctionClass, NULL, SkipScopeParent(parent), kind);
         if (!funobj)
             return NULL;
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -963,19 +963,22 @@ MarkPropertyAccessUnknown(JSContext *cx,
         target->addType(cx, Type::UnknownType());
 }
 
 /*
  * Handle a property access on a specific object. All property accesses go through
  * here, whether via x.f, x[f], or global name accesses.
  */
 static inline void
-PropertyAccess(JSContext *cx, JSScript *script, jsbytecode *pc, TypeObject *object,
+PropertyAccess(JSContext *cx, JSScript *script_, jsbytecode *pc, TypeObject *object_,
                bool assign, TypeSet *target, jsid id)
 {
+    RootedScript script(cx, script_);
+    Rooted<TypeObject*> object(cx, object_);
+
     /* Reads from objects with unknown properties are unknown, writes to such objects are ignored. */
     if (object->unknownProperties()) {
         if (!assign)
             MarkPropertyAccessUnknown(cx, script, pc, target);
         return;
     }
 
     /* Capture the effects of a standard property access. */
@@ -1825,32 +1828,31 @@ TypeCompartment::init(JSContext *cx)
     }
 }
 
 TypeObject *
 TypeCompartment::newTypeObject(JSContext *cx, JSScript *script,
                                JSProtoKey key, JSObject *proto_, bool unknown)
 {
     RootedObject proto(cx, proto_);
-
     TypeObject *object = gc::NewGCThing<TypeObject>(cx, gc::FINALIZE_TYPE_OBJECT, sizeof(TypeObject));
     if (!object)
         return NULL;
     new(object) TypeObject(proto, key == JSProto_Function, unknown);
 
     if (!cx->typeInferenceEnabled())
         object->flags |= OBJECT_FLAG_UNKNOWN_MASK;
     else
         object->setFlagsFromKey(cx, key);
 
     return object;
 }
 
 TypeObject *
-TypeCompartment::newAllocationSiteTypeObject(JSContext *cx, const AllocationSiteKey &key)
+TypeCompartment::newAllocationSiteTypeObject(JSContext *cx, AllocationSiteKey key)
 {
     AutoEnterTypeInference enter(cx);
 
     if (!allocationSiteTable) {
         allocationSiteTable = cx->new_<AllocationSiteTable>();
         if (!allocationSiteTable || !allocationSiteTable->init()) {
             cx->compartment->types.setPendingNukeTypes(cx);
             return NULL;
@@ -1859,21 +1861,23 @@ TypeCompartment::newAllocationSiteTypeOb
 
     AllocationSiteTable::AddPtr p = allocationSiteTable->lookupForAdd(key);
     JS_ASSERT(!p);
 
     JSObject *proto;
     if (!js_GetClassPrototype(cx, key.script->global(), key.kind, &proto, NULL))
         return NULL;
 
+    RootedScript keyScript(cx, key.script);
     TypeObject *res = newTypeObject(cx, key.script, key.kind, proto);
     if (!res) {
         cx->compartment->types.setPendingNukeTypes(cx);
         return NULL;
     }
+    key.script = keyScript;
 
     jsbytecode *pc = key.script->code + key.offset;
 
     if (JSOp(*pc) == JSOP_NEWOBJECT) {
         /*
          * This object is always constructed the same way and will not be
          * observed by other code before all properties have been added. Mark
          * all the properties as definite properties of the object.
@@ -2402,18 +2406,19 @@ struct types::ArrayTableKey
     }
 
     static inline bool match(const ArrayTableKey &v1, const ArrayTableKey &v2) {
         return v1.type == v2.type && v1.proto == v2.proto;
     }
 };
 
 void
-TypeCompartment::fixArrayType(JSContext *cx, JSObject *obj)
-{
+TypeCompartment::fixArrayType(JSContext *cx, JSObject *obj_)
+{
+    RootedObject obj(cx, obj_);
     AutoEnterTypeInference enter(cx);
 
     if (!arrayTypeTable) {
         arrayTypeTable = cx->new_<ArrayTypeTable>();
         if (!arrayTypeTable || !arrayTypeTable->init()) {
             arrayTypeTable = NULL;
             cx->compartment->types.setPendingNukeTypes(cx);
             return;
@@ -2449,16 +2454,17 @@ TypeCompartment::fixArrayType(JSContext 
     key.proto = obj->getProto();
     ArrayTypeTable::AddPtr p = arrayTypeTable->lookupForAdd(key);
 
     if (p) {
         obj->setType(p->value);
     } else {
         /* Make a new type to use for future arrays with the same elements. */
         TypeObject *objType = newTypeObject(cx, NULL, JSProto_Array, obj->getProto());
+        AssertRootingUnnecessary safe(cx);
         if (!objType) {
             cx->compartment->types.setPendingNukeTypes(cx);
             return;
         }
         obj->setType(objType);
 
         if (!objType->unknownProperties())
             objType->addPropertyType(cx, JSID_VOID, type);
@@ -2509,18 +2515,19 @@ struct types::ObjectTableKey
 
 struct types::ObjectTableEntry
 {
     ReadBarriered<TypeObject> object;
     Type *types;
 };
 
 void
-TypeCompartment::fixObjectType(JSContext *cx, JSObject *obj)
-{
+TypeCompartment::fixObjectType(JSContext *cx, JSObject *obj_)
+{
+    RootedObject obj(cx, obj_);
     AutoEnterTypeInference enter(cx);
 
     if (!objectTypeTable) {
         objectTypeTable = cx->new_<ObjectTypeTable>();
         if (!objectTypeTable || !objectTypeTable->init()) {
             objectTypeTable = NULL;
             cx->compartment->types.setPendingNukeTypes(cx);
             return;
@@ -2533,17 +2540,17 @@ TypeCompartment::fixObjectType(JSContext
      * is a type mismatch with previous objects of the same shape, use the
      * generic unknown type.
      */
     JS_ASSERT(obj->isObject());
 
     if (obj->slotSpan() == 0 || obj->inDictionaryMode())
         return;
 
-    ObjectTypeTable::AddPtr p = objectTypeTable->lookupForAdd(obj);
+    ObjectTypeTable::AddPtr p = objectTypeTable->lookupForAdd(obj.raw());
     const Shape *baseShape = obj->lastProperty();
 
     if (p) {
         /* The lookup ensures the shape matches, now check that the types match. */
         Type *types = p->value.types;
         for (unsigned i = 0; i < obj->slotSpan(); i++) {
             Type ntype = GetValueTypeForTable(cx, obj->getSlot(i));
             if (ntype != types[i]) {
@@ -2601,23 +2608,23 @@ TypeCompartment::fixObjectType(JSContext
             shape = shape->previous();
         }
 
         ObjectTableKey key;
         key.ids = ids;
         key.nslots = obj->slotSpan();
         key.nfixed = obj->numFixedSlots();
         key.proto = obj->getProto();
-        JS_ASSERT(ObjectTableKey::match(key, obj));
+        JS_ASSERT(ObjectTableKey::match(key, obj.raw()));
 
         ObjectTableEntry entry;
         entry.object = objType;
         entry.types = types;
 
-        p = objectTypeTable->lookupForAdd(obj);
+        p = objectTypeTable->lookupForAdd(obj.raw());
         if (!objectTypeTable->add(p, key, entry)) {
             cx->compartment->types.setPendingNukeTypes(cx);
             return;
         }
 
         obj->setType(objType);
     }
 }
@@ -2632,28 +2639,29 @@ TypeObject::getFromPrototypes(JSContext 
     if (!force && types->hasPropagatedProperty())
         return;
 
     types->setPropagatedProperty();
 
     if (!proto)
         return;
 
+    RootedTypeObject self(cx, this);
     if (proto->getType(cx)->unknownProperties()) {
         types->addType(cx, Type::UnknownType());
         return;
     }
 
-    TypeSet *protoTypes = proto->getType(cx)->getProperty(cx, id, false);
+    TypeSet *protoTypes = self->proto->getType(cx)->getProperty(cx, id, false);
     if (!protoTypes)
         return;
 
     protoTypes->addSubset(cx, types);
 
-    proto->getType(cx)->getFromPrototypes(cx, id, protoTypes);
+    self->proto->getType(cx)->getFromPrototypes(cx, id, protoTypes);
 }
 
 static inline void
 UpdatePropertyType(JSContext *cx, TypeSet *types, JSObject *obj, const Shape *shape, bool force)
 {
     types->setOwnProperty(cx, false);
     if (!shape->writable())
         types->setOwnProperty(cx, true);
@@ -5409,18 +5417,18 @@ JSScript::typeSetFunction(JSContext *cx,
         if (!fun->setSingletonType(cx))
             return false;
     } else {
         TypeObject *type = cx->compartment->types.newTypeObject(cx, this,
                                                                 JSProto_Function, fun->getProto());
         if (!type)
             return false;
 
-        fun->setType(type);
-        type->interpretedFunction = fun;
+        function_->setType(type);
+        type->interpretedFunction = function_;
     }
 
     return true;
 }
 
 #ifdef DEBUG
 
 /* static */ void
@@ -5492,18 +5500,18 @@ JSObject::splicePrototype(JSContext *cx,
 
     /* Inner objects may not appear on prototype chains. */
     JS_ASSERT_IF(proto, !proto->getClass()->ext.outerObject);
 
     /*
      * Force type instantiation when splicing lazy types. This may fail,
      * in which case inference will be disabled for the compartment.
      */
-    TypeObject *type = self->getType(cx);
-    TypeObject *protoType = NULL;
+    Rooted<TypeObject*> type(cx, self->getType(cx));
+    Rooted<TypeObject*> protoType(cx, NULL);
     if (proto) {
         protoType = proto->getType(cx);
         if (!proto->getNewType(cx))
             return false;
     }
 
     if (!cx->typeInferenceEnabled()) {
         TypeObject *type = proto ? proto->getNewType(cx) : cx->compartment->getEmptyType(cx);
@@ -5535,72 +5543,74 @@ JSObject::splicePrototype(JSContext *cx,
     return true;
 }
 
 void
 JSObject::makeLazyType(JSContext *cx)
 {
     JS_ASSERT(hasLazyType());
 
+    RootedObject self(cx, this);
     JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(getClass());
     TypeObject *type = cx->compartment->types.newTypeObject(cx, NULL, key, getProto());
+    AssertRootingUnnecessary safe(cx);
     if (!type) {
         if (cx->typeInferenceEnabled())
             cx->compartment->types.setPendingNukeTypes(cx);
         return;
     }
 
     if (!cx->typeInferenceEnabled()) {
         /* This can only happen if types were previously nuked. */
-        type_ = type;
+        self->type_ = type;
         return;
     }
 
     AutoEnterTypeInference enter(cx);
 
     /* Fill in the type according to the state of this object. */
 
-    type->singleton = this;
-
-    if (isFunction() && toFunction()->isInterpreted()) {
-        type->interpretedFunction = toFunction();
+    type->singleton = self;
+
+    if (self->isFunction() && self->toFunction()->isInterpreted()) {
+        type->interpretedFunction = self->toFunction();
         JSScript *script = type->interpretedFunction->script();
         if (script->uninlineable)
             type->flags |= OBJECT_FLAG_UNINLINEABLE;
         if (script->reentrantOuterFunction)
             type->flags |= OBJECT_FLAG_REENTRANT_FUNCTION;
     }
 
-    if (lastProperty()->hasObjectFlag(BaseShape::ITERATED_SINGLETON))
+    if (self->lastProperty()->hasObjectFlag(BaseShape::ITERATED_SINGLETON))
         type->flags |= OBJECT_FLAG_ITERATED;
 
 #if JS_HAS_XML_SUPPORT
     /*
      * XML objects do not have equality hooks but are treated special by EQ/NE
      * ops. Just mark the type as totally unknown.
      */
-    if (isXML() && !type->unknownProperties())
+    if (self->isXML() && !type->unknownProperties())
         type->markUnknown(cx);
 #endif
 
-    if (getClass()->ext.equality)
+    if (self->getClass()->ext.equality)
         type->flags |= OBJECT_FLAG_SPECIAL_EQUALITY;
 
     /*
      * Adjust flags for objects which will have the wrong flags set by just
      * looking at the class prototype key.
      */
 
     if (isSlowArray())
         type->flags |= OBJECT_FLAG_NON_DENSE_ARRAY | OBJECT_FLAG_NON_PACKED_ARRAY;
 
     if (IsTypedArrayProto(this))
         type->flags |= OBJECT_FLAG_NON_TYPED_ARRAY;
 
-    type_ = type;
+    self->type_ = type;
 }
 
 /* static */ inline HashNumber
 TypeObjectEntry::hash(JSObject *proto)
 {
     return PointerHasher<JSObject *, 3>::hash(proto);
 }
 
@@ -5723,18 +5733,19 @@ JSObject::getNewType(JSContext *cx, JSFu
      */
     if (type->unknownProperties())
         type->flags |= OBJECT_FLAG_SETS_MARKED_UNKNOWN;
 
     return type;
 }
 
 TypeObject *
-JSCompartment::getLazyType(JSContext *cx, JSObject *proto)
-{
+JSCompartment::getLazyType(JSContext *cx, JSObject *proto_)
+{
+    RootedObject proto(cx, proto_);
     MaybeCheckStackRoots(cx);
 
     TypeObjectSet &table = cx->compartment->lazyTypeObjects;
 
     if (!table.initialized() && !table.init())
         return NULL;
 
     TypeObjectSet::AddPtr p = table.lookupForAdd(proto);
--- a/js/src/jsinfer.h
+++ b/js/src/jsinfer.h
@@ -1201,17 +1201,17 @@ struct TypeCompartment
      * script. The 'key' parameter here may be an array, typed array, function
      * or JSProto_Object to indicate a type whose class is unknown (not just
      * js_ObjectClass).
      */
     TypeObject *newTypeObject(JSContext *cx, JSScript *script,
                               JSProtoKey kind, JSObject *proto, bool unknown = false);
 
     /* Make an object for an allocation site. */
-    TypeObject *newAllocationSiteTypeObject(JSContext *cx, const AllocationSiteKey &key);
+    TypeObject *newAllocationSiteTypeObject(JSContext *cx, AllocationSiteKey key);
 
     void nukeTypes(FreeOp *fop);
     void processPendingRecompiles(FreeOp *fop);
 
     /* Mark all types as needing destruction once inference has 'finished'. */
     void setPendingNukeTypes(JSContext *cx);
     void setPendingNukeTypesNoReport();
 
--- a/js/src/jsinferinlines.h
+++ b/js/src/jsinferinlines.h
@@ -8,16 +8,17 @@
 
 #include "jsarray.h"
 #include "jsanalyze.h"
 #include "jscompartment.h"
 #include "jsinfer.h"
 #include "jsprf.h"
 
 #include "gc/Marking.h"
+#include "gc/Root.h"
 #include "vm/GlobalObject.h"
 
 #include "vm/Stack-inl.h"
 
 #ifndef jsinferinlines_h___
 #define jsinferinlines_h___
 
 /////////////////////////////////////////////////////////////////////
@@ -300,21 +301,21 @@ MarkIteratorUnknown(JSContext *cx)
  * from within the interpreter.
  */
 inline bool
 TypeMonitorCall(JSContext *cx, const js::CallArgs &args, bool constructing)
 {
     extern void TypeMonitorCallSlow(JSContext *cx, JSObject *callee,
                                     const CallArgs &args, bool constructing);
 
-    JSObject *callee = &args.callee();
+    RootedObject callee(cx, &args.callee());
     if (callee->isFunction()) {
         JSFunction *fun = callee->toFunction();
         if (fun->isInterpreted()) {
-            JSScript *script = fun->script();
+            RootedScript script(cx, fun->script());
             if (!script->ensureRanAnalysis(cx, fun->environment()))
                 return false;
             if (cx->typeInferenceEnabled())
                 TypeMonitorCallSlow(cx, callee, args, constructing);
         }
     }
 
     return true;
@@ -551,17 +552,17 @@ TypeScript::InitObject(JSContext *cx, JS
 
     if (p)
         return p->value;
     return cx->compartment->types.newAllocationSiteTypeObject(cx, key);
 }
 
 /* Set the type to use for obj according to the site it was allocated at. */
 static inline bool
-SetInitializerObjectType(JSContext *cx, JSScript *script, jsbytecode *pc, JSObject *obj)
+SetInitializerObjectType(JSContext *cx, HandleScript script, jsbytecode *pc, HandleObject obj)
 {
     if (!cx->typeInferenceEnabled())
         return true;
 
     JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(obj->getClass());
     JS_ASSERT(key != JSProto_Null);
 
     if (UseNewTypeForInitializer(cx, script, pc, key)) {
@@ -1467,23 +1468,24 @@ JSScript::ensureRanAnalysis(JSContext *c
         return false;
     JS_ASSERT(self->analysis()->ranBytecode());
     return true;
 }
 
 inline bool
 JSScript::ensureRanInference(JSContext *cx)
 {
+    JS::RootedScript self(cx, this);
     if (!ensureRanAnalysis(cx, NULL))
         return false;
-    if (!analysis()->ranInference()) {
+    if (!self->analysis()->ranInference()) {
         js::types::AutoEnterTypeInference enter(cx);
-        analysis()->analyzeTypes(cx);
+        self->analysis()->analyzeTypes(cx);
     }
-    return !analysis()->OOM() &&
+    return !self->analysis()->OOM() &&
         !cx->compartment->types.pendingNukeTypes;
 }
 
 inline bool
 JSScript::hasAnalysis()
 {
     return types && types->analysis;
 }
@@ -1508,14 +1510,16 @@ js::analyze::ScriptAnalysis::addPushedTy
 {
     js::types::TypeSet *pushed = pushedTypes(offset, which);
     pushed->addType(cx, type);
 }
 
 inline js::types::TypeObject *
 JSCompartment::getEmptyType(JSContext *cx)
 {
-    if (!emptyTypeObject)
-        emptyTypeObject = types.newTypeObject(cx, NULL, JSProto_Object, NULL, true);
+    if (!emptyTypeObject) {
+        JS::RootedObject nullproto(cx, NULL);
+        emptyTypeObject = types.newTypeObject(cx, NULL, JSProto_Object, nullproto, true);
+    }
     return emptyTypeObject;
 }
 
 #endif // jsinferinlines_h___
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -2770,17 +2770,18 @@ BEGIN_CASE(JSOP_ARGUMENTS)
         PUSH_COPY(ObjectValue(*obj));
     } else {
         PUSH_COPY(MagicValue(JS_OPTIMIZED_ARGUMENTS));
     }
 END_CASE(JSOP_ARGUMENTS)
 
 BEGIN_CASE(JSOP_REST)
 {
-    JSObject *rest = regs.fp()->createRestParameter(cx);
+    RootedObject &rest = rootObject0;
+    rest = regs.fp()->createRestParameter(cx);
     if (!rest)
         goto error;
     PUSH_COPY(ObjectValue(*rest));
     if (!SetInitializerObjectType(cx, script, regs.pc, rest))
         goto error;
 }
 END_CASE(JSOP_REST)
 
@@ -3091,17 +3092,17 @@ BEGIN_CASE(JSOP_HOLE)
     PUSH_HOLE();
 END_CASE(JSOP_HOLE)
 
 BEGIN_CASE(JSOP_NEWINIT)
 {
     uint8_t i = GET_UINT8(regs.pc);
     JS_ASSERT(i == JSProto_Array || i == JSProto_Object);
 
-    JSObject *obj;
+    RootedObject &obj = rootObject0;
     if (i == JSProto_Array) {
         obj = NewDenseEmptyArray(cx);
     } else {
         gc::AllocKind kind = GuessObjectGCKind(0);
         obj = NewBuiltinClassInstance(cx, &ObjectClass, kind);
     }
     if (!obj || !SetInitializerObjectType(cx, script, regs.pc, obj))
         goto error;
@@ -3111,17 +3112,18 @@ BEGIN_CASE(JSOP_NEWINIT)
 
     CHECK_INTERRUPT_HANDLER();
 }
 END_CASE(JSOP_NEWINIT)
 
 BEGIN_CASE(JSOP_NEWARRAY)
 {
     unsigned count = GET_UINT24(regs.pc);
-    JSObject *obj = NewDenseAllocatedArray(cx, count);
+    RootedObject &obj = rootObject0;
+    obj = NewDenseAllocatedArray(cx, count);
     if (!obj || !SetInitializerObjectType(cx, script, regs.pc, obj))
         goto error;
 
     PUSH_OBJECT(*obj);
     TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
 
     CHECK_INTERRUPT_HANDLER();
 }
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -2555,21 +2555,20 @@ JSObject::getSealedOrFrozenAttributes(un
     if (it == FREEZE && !(attrs & (JSPROP_GETTER | JSPROP_SETTER)))
         return JSPROP_PERMANENT | JSPROP_READONLY;
     return JSPROP_PERMANENT;
 }
 
 bool
 JSObject::sealOrFreeze(JSContext *cx, ImmutabilityType it)
 {
+    RootedObject self(cx, this);
     assertSameCompartment(cx, this);
     JS_ASSERT(it == SEAL || it == FREEZE);
 
-    RootedObject self(cx, this);
-
     if (isExtensible() && !preventExtensions(cx))
         return false;
 
     AutoIdVector props(cx);
     if (!GetPropertyNames(cx, self, JSITER_HIDDEN | JSITER_OWNONLY, &props))
         return false;
 
     /* preventExtensions must slowify dense arrays, so we can assign to holes without checks. */
@@ -2765,34 +2764,34 @@ JSFunctionSpec object_static_methods[] =
     JS_FN("seal",                      obj_seal,                    1,0),
     JS_FN("isSealed",                  obj_isSealed,                1,0),
     JS_FS_END
 };
 
 JSBool
 js_Object(JSContext *cx, unsigned argc, Value *vp)
 {
-    JSObject *obj;
+    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))
+        if (!js_ValueToObjectOrNull(cx, vp[2], obj.address()))
             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)
             return JS_FALSE;
         jsbytecode *pc;
-        JSScript *script = cx->stack.currentScript(&pc);
+        RootedScript script(cx, cx->stack.currentScript(&pc));
         if (script) {
             /* Try to specialize the type of the object to the scripted call site. */
             if (!types::SetInitializerObjectType(cx, script, pc, obj))
                 return JS_FALSE;
         }
     }
     vp->setObject(*obj);
     return JS_TRUE;
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -25,16 +25,17 @@
 #include "jsscope.h"
 #include "jsstr.h"
 #include "jstypedarray.h"
 #include "jsxml.h"
 #include "jswrapper.h"
 
 #include "gc/Barrier.h"
 #include "gc/Marking.h"
+#include "gc/Root.h"
 #include "js/TemplateLib.h"
 #include "vm/BooleanObject.h"
 #include "vm/GlobalObject.h"
 #include "vm/NumberObject.h"
 #include "vm/RegExpStatics.h"
 #include "vm/StringObject.h"
 
 #include "jsatominlines.h"
@@ -660,33 +661,35 @@ JSObject::setQNameLocalName(JSAtom *name
 #endif
 
 inline bool
 JSObject::setSingletonType(JSContext *cx)
 {
     if (!cx->typeInferenceEnabled())
         return true;
 
+    JS::Rooted<JSObject*> self(cx, this);
     JS_ASSERT(!hasLazyType());
-    JS_ASSERT_IF(getProto(), type() == getProto()->getNewType(cx, NULL));
+    JS_ASSERT_IF(self->getProto(), self->type() == self->getProto()->getNewType(cx, NULL));
 
-    js::types::TypeObject *type = cx->compartment->getLazyType(cx, getProto());
+    js::types::TypeObject *type = cx->compartment->getLazyType(cx, self->getProto());
     if (!type)
         return false;
 
-    type_ = type;
+    self->type_ = type;
     return true;
 }
 
 inline js::types::TypeObject *
 JSObject::getType(JSContext *cx)
 {
-    if (hasLazyType())
-        makeLazyType(cx);
-    return type_;
+    JS::RootedObject self(cx, this);
+    if (self->hasLazyType())
+        self->makeLazyType(cx);
+    return self->type_;
 }
 
 inline bool
 JSObject::clearType(JSContext *cx)
 {
     JS_ASSERT(!hasSingletonType());
 
     js::types::TypeObject *type = cx->compartment->getEmptyType(cx);
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -1071,18 +1071,19 @@ ScriptDataSize(uint32_t length, uint32_t
     size += length * sizeof(jsbytecode);
     size += nsrcnotes * sizeof(jssrcnote);
     return size;
 }
 
 JSScript *
 JSScript::Create(JSContext *cx, bool savedCallerFun, JSPrincipals *principals,
                  JSPrincipals *originPrincipals, bool compileAndGo, bool noScriptRval,
-                 GlobalObject *globalObject, JSVersion version, unsigned staticLevel)
+                 GlobalObject *globalObject_, JSVersion version, unsigned staticLevel)
 {
+    Rooted<GlobalObject*> globalObject(cx, globalObject_);
     JSScript *script = js_NewGCScript(cx);
     if (!script)
         return NULL;
 
     PodZero(script);
 
     script->savedCallerFun = savedCallerFun;
 
@@ -1331,17 +1332,17 @@ JSScript::fullyInitFromEmitter(JSContext
 
     if (nClosedArgs)
         PodCopy<uint32_t>(script->closedArgs()->vector, &bce->closedArgs[0], nClosedArgs);
     if (nClosedVars)
         PodCopy<uint32_t>(script->closedVars()->vector, &bce->closedVars[0], nClosedVars);
 
     script->bindings.transfer(&bce->sc->bindings);
 
-    JSFunction *fun = NULL;
+    RootedFunction fun(cx, NULL);
     if (bce->sc->inFunction()) {
         JS_ASSERT(!bce->script->noScriptRval);
 
         script->isGenerator = bce->sc->funIsGenerator();
 
         /*
          * We initialize fun->script() to be the script constructed above
          * so that the debugger has a valid fun->script().
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -3428,16 +3428,19 @@ namespace js {
 
 jschar *
 InflateString(JSContext *cx, const char *bytes, size_t *lengthp, FlationCoding fc)
 {
     size_t nchars;
     jschar *chars;
     size_t nbytes = *lengthp;
 
+    // Malformed UTF8 chars could trigger errors and hence GC
+    MaybeCheckStackRoots(cx);
+
     if (js_CStringsAreUTF8 || fc == CESU8Encoding) {
         if (!InflateUTF8StringToBuffer(cx, bytes, nbytes, NULL, &nchars, fc))
             goto bad;
         chars = (jschar *) cx->malloc_((nchars + 1) * sizeof (jschar));
         if (!chars)
             goto bad;
         JS_ALWAYS_TRUE(InflateUTF8StringToBuffer(cx, bytes, nbytes, chars, &nchars, fc));
     } else {
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -1359,17 +1359,17 @@ class TypedArrayTemplate
                 return NULL;
             obj->setType(type);
         } else if (cx->typeInferenceEnabled()) {
             if (len * sizeof(NativeType) >= TypedArray::SINGLETON_TYPE_BYTE_LENGTH) {
                 if (!obj->setSingletonType(cx))
                     return NULL;
             } else {
                 jsbytecode *pc;
-                JSScript *script = cx->stack.currentScript(&pc);
+                RootedScript script(cx, cx->stack.currentScript(&pc));
                 if (script) {
                     if (!types::SetInitializerObjectType(cx, script, pc, obj))
                         return NULL;
                 }
             }
         }
 
         obj->setSlot(FIELD_TYPE, Int32Value(ArrayTypeID()));
--- a/js/src/jstypedarrayinlines.h
+++ b/js/src/jstypedarrayinlines.h
@@ -158,17 +158,17 @@ DataViewObject::create(JSContext *cx, ui
             return NULL;
         obj->setType(type);
     } else if (cx->typeInferenceEnabled()) {
         if (byteLength >= TypedArray::SINGLETON_TYPE_BYTE_LENGTH) {
             if (!obj->setSingletonType(cx))
                 return NULL;
         } else {
             jsbytecode *pc;
-            JSScript *script = cx->stack.currentScript(&pc);
+            RootedScript script(cx, cx->stack.currentScript(&pc));
             if (script) {
                 if (!types::SetInitializerObjectType(cx, script, pc, obj))
                     return NULL;
             }
         }
     }
 
     JS_ASSERT(arrayBuffer->isArrayBuffer());
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -49,17 +49,17 @@ using namespace js::analyze;
  * Number of times a script must be called or had a backedge before we try to
  * inline its calls.
  */
 static const size_t USES_BEFORE_INLINING = 10000;
 
 mjit::Compiler::Compiler(JSContext *cx, JSScript *outerScript,
                          unsigned chunkIndex, bool isConstructing)
   : BaseCompiler(cx),
-    outerScript(outerScript),
+    outerScript(cx, outerScript),
     chunkIndex(chunkIndex),
     isConstructing(isConstructing),
     outerChunk(outerJIT()->chunkDescriptor(chunkIndex)),
     ssa(cx, outerScript),
     globalObj(cx, outerScript->hasGlobal() ? outerScript->global() : NULL),
     globalSlots(globalObj ? globalObj->getRawSlots() : NULL),
     frame(cx, *thisFromCtor(), masm, stubcc),
     a(NULL), outer(NULL), script(NULL), PC(NULL), loop(NULL),
@@ -123,17 +123,17 @@ mjit::Compiler::compile()
                                        types::OBJECT_FLAG_UNINLINEABLE);
         }
     }
 
     return status;
 }
 
 CompileStatus
-mjit::Compiler::checkAnalysis(JSScript *script)
+mjit::Compiler::checkAnalysis(HandleScript script)
 {
     if (script->hasClearedGlobal()) {
         JaegerSpew(JSpew_Abort, "script has a cleared global\n");
         return Compile_Abort;
     }
 
     if (!script->ensureRanAnalysis(cx, NULL))
         return Compile_Error;
@@ -152,17 +152,17 @@ mjit::Compiler::checkAnalysis(JSScript *
         JaegerSpew(JSpew_Abort, "couldn't analyze bytecode; probably switchX or OOM\n");
         return Compile_Abort;
     }
 
     return Compile_Okay;
 }
 
 CompileStatus
-mjit::Compiler::addInlineFrame(JSScript *script, uint32_t depth,
+mjit::Compiler::addInlineFrame(HandleScript script, uint32_t depth,
                                uint32_t parent, jsbytecode *parentpc)
 {
     JS_ASSERT(inlining());
 
     CompileStatus status = checkAnalysis(script);
     if (status != Compile_Okay)
         return status;
 
@@ -264,17 +264,17 @@ mjit::Compiler::scanInlineCalls(uint32_t
                 break;
             }
 
             JSFunction *fun = obj->toFunction();
             if (!fun->isInterpreted()) {
                 okay = false;
                 break;
             }
-            JSScript *script = fun->script();
+            RootedScript script(cx, fun->script());
 
             /*
              * Don't inline calls to scripts which haven't been analyzed.
              * We need to analyze the inlined scripts to compile them, and
              * doing so can change type information we have queried already
              * in making inlining decisions.
              */
             if (!script->hasAnalysis() || !script->analysis()->ranInference()) {
@@ -352,17 +352,17 @@ mjit::Compiler::scanInlineCalls(uint32_t
          * back up when compiling the call site.
          */
         for (unsigned i = 0; i < count; i++) {
             JSObject *obj = calleeTypes->getSingleObject(i);
             if (!obj)
                 continue;
 
             JSFunction *fun = obj->toFunction();
-            JSScript *script = fun->script();
+            RootedScript script(cx, fun->script());
 
             CompileStatus status = addInlineFrame(script, nextDepth, index, pc);
             if (status != Compile_Okay)
                 return status;
         }
     }
 
     return Compile_Okay;
@@ -4410,17 +4410,17 @@ mjit::Compiler::inlineScriptedFunction(u
     AnyRegisterID returnRegister;
     const FrameEntry *returnEntry = NULL;
 
     Vector<Jump, 4, CompilerAllocPolicy> returnJumps(CompilerAllocPolicy(cx, *this));
 
     for (unsigned i = 0; i < inlineCallees.length(); i++) {
         if (entrySnapshot)
             frame.restoreFromSnapshot(entrySnapshot);
-
+        
         JSScript *script = inlineCallees[i];
         CompileStatus status;
 
         status = pushActiveFrame(script, argc);
         if (status != Compile_Okay)
             return status;
 
         a->exitState = exitState;
--- a/js/src/methodjit/Compiler.h
+++ b/js/src/methodjit/Compiler.h
@@ -359,17 +359,17 @@ class Compiler : public BaseCompiler
 
     struct SlotType
     {
         uint32_t slot;
         VarType vt;
         SlotType(uint32_t slot, VarType vt) : slot(slot), vt(vt) {}
     };
 
-    JSScript *outerScript;
+    RootedScript outerScript;
     unsigned chunkIndex;
     bool isConstructing;
     ChunkDescriptor outerChunk;
 
     /* SSA information for the outer script and all frames we will be inlining. */
     analyze::CrossScriptSSA ssa;
 
     Rooted<GlobalObject*> globalObj;
@@ -553,19 +553,19 @@ private:
     void restoreVarType();
     JSValueType knownPushedType(uint32_t pushed);
     bool mayPushUndefined(uint32_t pushed);
     types::TypeSet *pushedTypeSet(uint32_t which);
     bool monitored(jsbytecode *pc);
     bool hasTypeBarriers(jsbytecode *pc);
     bool testSingletonProperty(HandleObject obj, HandleId id);
     bool testSingletonPropertyTypes(FrameEntry *top, HandleId id, bool *testObject);
-    CompileStatus addInlineFrame(JSScript *script, uint32_t depth, uint32_t parent, jsbytecode *parentpc);
+    CompileStatus addInlineFrame(HandleScript script, uint32_t depth, uint32_t parent, jsbytecode *parentpc);
     CompileStatus scanInlineCalls(uint32_t index, uint32_t depth);
-    CompileStatus checkAnalysis(JSScript *script);
+    CompileStatus checkAnalysis(HandleScript script);
 
     struct BarrierState {
         MaybeJump jump;
         RegisterID typeReg;
         RegisterID dataReg;
     };
 
     MaybeJump trySingleTypeTest(types::TypeSet *types, RegisterID typeReg);
--- a/js/src/methodjit/StubCalls.cpp
+++ b/js/src/methodjit/StubCalls.cpp
@@ -858,54 +858,55 @@ stubs::Neg(VMFrame &f)
     d = -d;
     if (!f.regs.sp[-1].setNumber(d))
         TypeScript::MonitorOverflow(f.cx, f.script(), f.pc());
 }
 
 void JS_FASTCALL
 stubs::NewInitArray(VMFrame &f, uint32_t count)
 {
-    JSObject *obj = NewDenseAllocatedArray(f.cx, count);
+    RootedObject obj(f.cx, NewDenseAllocatedArray(f.cx, count));
     if (!obj)
         THROW();
 
     TypeObject *type = (TypeObject *) f.scratch;
     if (type) {
         obj->setType(type);
     } else {
-        if (!SetInitializerObjectType(f.cx, f.script(), f.pc(), obj))
+        RootedScript script(f.cx, f.script());
+        if (!SetInitializerObjectType(f.cx, script, f.pc(), obj))
             THROW();
     }
 
     f.regs.sp[0].setObject(*obj);
 }
 
 void JS_FASTCALL
 stubs::NewInitObject(VMFrame &f, JSObject *baseobj)
 {
     JSContext *cx = f.cx;
     TypeObject *type = (TypeObject *) f.scratch;
 
-    JSObject *obj;
-
+    RootedObject obj(cx);
     if (baseobj) {
         Rooted<JSObject*> base(cx, baseobj);
         obj = CopyInitializerObject(cx, base);
     } else {
         gc::AllocKind kind = GuessObjectGCKind(0);
         obj = NewBuiltinClassInstance(cx, &ObjectClass, kind);
     }
 
     if (!obj)
         THROW();
 
     if (type) {
         obj->setType(type);
     } else {
-        if (!SetInitializerObjectType(cx, f.script(), f.pc(), obj))
+        RootedScript script(f.cx, f.script());
+        if (!SetInitializerObjectType(cx, script, f.pc(), obj))
             THROW();
     }
 
     f.regs.sp[0].setObject(*obj);
 }
 
 void JS_FASTCALL
 stubs::InitElem(VMFrame &f, uint32_t last)
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -156,18 +156,18 @@ GlobalObject::initFunctionAndObjectClass
      * Install |Object| and |Object.prototype| for the benefit of subsequent
      * code that looks for them.
      */
     self->setObjectClassDetails(objectCtor, objectProto);
 
     /* Create |Function| so it and |Function.prototype| can be installed. */
     RootedFunction functionCtor(cx);
     {
-        JSObject *ctor =
-            NewObjectWithGivenProto(cx, &FunctionClass, functionProto, self);
+        // Note that ctor is rooted purely for the JS_ASSERT at the end
+        RootedObject ctor(cx, NewObjectWithGivenProto(cx, &FunctionClass, functionProto, self));
         if (!ctor)
             return NULL;
         functionCtor = js_NewFunction(cx, ctor, Function, 1, JSFUN_CONSTRUCTOR, self,
                                       CLASS_NAME(cx, Function));
         if (!functionCtor)
             return NULL;
         JS_ASSERT(ctor == functionCtor);
     }
@@ -375,31 +375,32 @@ GlobalObject::createConstructor(JSContex
 }
 
 static JSObject *
 CreateBlankProto(JSContext *cx, Class *clasp, JSObject &proto, GlobalObject &global)
 {
     JS_ASSERT(clasp != &ObjectClass);
     JS_ASSERT(clasp != &FunctionClass);
 
-    JSObject *blankProto = NewObjectWithGivenProto(cx, clasp, &proto, &global);
+    RootedObject blankProto(cx, NewObjectWithGivenProto(cx, clasp, &proto, &global));
     if (!blankProto || !blankProto->setSingletonType(cx))
         return NULL;
 
     return blankProto;
 }
 
 JSObject *
 GlobalObject::createBlankPrototype(JSContext *cx, Class *clasp)
 {
+    Rooted<GlobalObject*> self(cx, this);
     JSObject *objectProto = getOrCreateObjectPrototype(cx);
     if (!objectProto)
         return NULL;
 
-    return CreateBlankProto(cx, clasp, *objectProto, *this);
+    return CreateBlankProto(cx, clasp, *objectProto, *self.reference());
 }
 
 JSObject *
 GlobalObject::createBlankPrototypeInheriting(JSContext *cx, Class *clasp, JSObject &proto)
 {
     return CreateBlankProto(cx, clasp, proto, *this);
 }