Use handles in API object hooks where possible, bug 750733. r=billm
authorBrian Hackett <bhackett1024@gmail.com>
Sat, 19 May 2012 15:03:45 -0700
changeset 98960 32cfab3a6aa5f8d46189e62dc3e8f319fed2669f
parent 98958 da3c5b7c2c7e8b34f789c67ce870bfa16460df9e
child 98961 ed488f577c84d1213600d2459ad913de0952adb1
push id173
push userlsblakk@mozilla.com
push dateFri, 24 Aug 2012 15:39:16 +0000
treeherdermozilla-release@bcc45eb1fb41 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm
bugs750733
milestone15.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
Use handles in API object hooks where possible, bug 750733. r=billm
caps/include/nsScriptSecurityManager.h
caps/src/nsScriptSecurityManager.cpp
content/canvas/src/CustomQS_Canvas2D.h
content/xbl/src/nsXBLBinding.cpp
content/xbl/src/nsXBLDocumentInfo.cpp
content/xul/document/src/nsXULPrototypeDocument.cpp
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfo.h
dom/base/nsDOMWindowUtils.cpp
dom/bindings/Codegen.py
dom/plugins/base/nsJSNPRuntime.cpp
dom/workers/ChromeWorkerScope.cpp
dom/workers/Events.cpp
dom/workers/Exceptions.cpp
dom/workers/File.cpp
dom/workers/ImageData.cpp
dom/workers/Location.cpp
dom/workers/Navigator.cpp
dom/workers/RuntimeService.cpp
dom/workers/Worker.cpp
dom/workers/WorkerScope.cpp
dom/workers/Workers.h
gfx/skia/src/xml/SkJS.cpp
js/ipc/ObjectWrapperParent.cpp
js/ipc/ObjectWrapperParent.h
js/src/builtin/RegExp.cpp
js/src/ctypes/CTypes.cpp
js/src/frontend/BytecodeEmitter.cpp
js/src/gc/Root.h
js/src/jsapi-tests/testAddPropertyPropcache.cpp
js/src/jsapi-tests/testClassGetter.cpp
js/src/jsapi-tests/testCustomIterator.cpp
js/src/jsapi-tests/testExtendedEq.cpp
js/src/jsapi-tests/testLookup.cpp
js/src/jsapi-tests/testOps.cpp
js/src/jsapi-tests/testPropCache.cpp
js/src/jsapi-tests/testResolveRecursion.cpp
js/src/jsapi-tests/testSetProperty.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jsarray.cpp
js/src/jsarray.h
js/src/jsclass.h
js/src/jscntxt.cpp
js/src/jscntxtinlines.h
js/src/jscompartment.cpp
js/src/jsdate.cpp
js/src/jsdbgapi.cpp
js/src/jsexn.cpp
js/src/jsfriendapi.cpp
js/src/jsfriendapi.h
js/src/jsfun.cpp
js/src/jsfun.h
js/src/jsinfer.cpp
js/src/jsinterp.cpp
js/src/jsinterp.h
js/src/jsinterpinlines.h
js/src/jsiter.cpp
js/src/jsnum.cpp
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsobjinlines.h
js/src/json.cpp
js/src/jsonparser.cpp
js/src/jsopcode.tbl
js/src/jsproxy.cpp
js/src/jsprvtd.h
js/src/jsreflect.cpp
js/src/jsscope.h
js/src/jsscopeinlines.h
js/src/jsstr.cpp
js/src/jstypedarray.cpp
js/src/jstypedarray.h
js/src/jsweakmap.cpp
js/src/jswrapper.cpp
js/src/jsxml.cpp
js/src/methodjit/Compiler.cpp
js/src/methodjit/Compiler.h
js/src/methodjit/FastOps.cpp
js/src/methodjit/PolyIC.cpp
js/src/methodjit/StubCalls.cpp
js/src/perf/jsperf.cpp
js/src/shell/js.cpp
js/src/vm/ArgumentsObject.cpp
js/src/vm/Debugger.cpp
js/src/vm/GlobalObject.cpp
js/src/vm/ScopeObject.cpp
js/src/vm/ScopeObject.h
js/xpconnect/shell/xpcshell.cpp
js/xpconnect/src/XPCComponents.cpp
js/xpconnect/src/XPCQuickStubs.cpp
js/xpconnect/src/XPCQuickStubs.h
js/xpconnect/src/XPCRuntimeService.cpp
js/xpconnect/src/XPCThreadContext.cpp
js/xpconnect/src/XPCWrappedNativeJSOps.cpp
js/xpconnect/src/codegen.py
js/xpconnect/src/dombindings.cpp
js/xpconnect/src/dombindings.h
js/xpconnect/src/qsgen.py
js/xpconnect/src/xpcprivate.h
js/xpconnect/wrappers/XrayWrapper.cpp
js/xpconnect/wrappers/XrayWrapper.h
--- a/caps/include/nsScriptSecurityManager.h
+++ b/caps/include/nsScriptSecurityManager.h
@@ -421,18 +421,18 @@ public:
 
 private:
 
     // GetScriptSecurityManager is the only call that can make one
     nsScriptSecurityManager();
     virtual ~nsScriptSecurityManager();
 
     static JSBool
-    CheckObjectAccess(JSContext *cx, JSObject *obj,
-                      jsid id, JSAccessMode mode,
+    CheckObjectAccess(JSContext *cx, JSHandleObject obj,
+                      JSHandleId id, JSAccessMode mode,
                       jsval *vp);
 
     static JSPrincipals *
     ObjectPrincipalFinder(JSObject *obj);
     
     // Decides, based on CSP, whether or not eval() and stuff can be executed.
     static JSBool
     ContentSecurityPolicyPermitsJSAction(JSContext *cx);
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -626,18 +626,18 @@ nsScriptSecurityManager::ContentSecurity
                                  lineNum);
     }
 
     return evalOK;
 }
 
 
 JSBool
-nsScriptSecurityManager::CheckObjectAccess(JSContext *cx, JSObject *obj,
-                                           jsid id, JSAccessMode mode,
+nsScriptSecurityManager::CheckObjectAccess(JSContext *cx, JSHandleObject obj,
+                                           JSHandleId id, JSAccessMode mode,
                                            jsval *vp)
 {
     // Get the security manager
     nsScriptSecurityManager *ssm =
         nsScriptSecurityManager::GetScriptSecurityManager();
 
     NS_ASSERTION(ssm, "Failed to get security manager service");
     if (!ssm)
--- a/content/canvas/src/CustomQS_Canvas2D.h
+++ b/content/canvas/src/CustomQS_Canvas2D.h
@@ -130,35 +130,35 @@ Canvas2D_GetStyleHelper(JSContext *cx, J
                                         &interfaces[k_nsIDOMCanvasGradient], vp);
     }
     default:
         return xpc_qsThrowGetterSetterFailed(cx, NS_ERROR_FAILURE, JSVAL_TO_OBJECT(*vp), id);
     }
 }
 
 static JSBool
-nsIDOMCanvasRenderingContext2D_SetStrokeStyle(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
+nsIDOMCanvasRenderingContext2D_SetStrokeStyle(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, jsval *vp)
 {
     return Canvas2D_SetStyleHelper(cx, obj, id, vp, &nsIDOMCanvasRenderingContext2D::SetStrokeStyle_multi);
 }
 
 static JSBool
-nsIDOMCanvasRenderingContext2D_GetStrokeStyle(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+nsIDOMCanvasRenderingContext2D_GetStrokeStyle(JSContext *cx, JSHandleObject obj, JSHandleId id, jsval *vp)
 {
     return Canvas2D_GetStyleHelper(cx, obj, id, vp, &nsIDOMCanvasRenderingContext2D::GetStrokeStyle_multi);
 }
 
 static JSBool
-nsIDOMCanvasRenderingContext2D_SetFillStyle(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
+nsIDOMCanvasRenderingContext2D_SetFillStyle(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, jsval *vp)
 {
     return Canvas2D_SetStyleHelper(cx, obj, id, vp, &nsIDOMCanvasRenderingContext2D::SetFillStyle_multi);
 }
 
 static JSBool
-nsIDOMCanvasRenderingContext2D_GetFillStyle(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+nsIDOMCanvasRenderingContext2D_GetFillStyle(JSContext *cx, JSHandleObject obj, JSHandleId id, jsval *vp)
 {
     return Canvas2D_GetStyleHelper(cx, obj, id, vp, &nsIDOMCanvasRenderingContext2D::GetFillStyle_multi);
 }
 
 static bool
 CreateImageData(JSContext* cx, JSObject* obj, uint32_t w, uint32_t h, jsval* vp)
 {
     using mozilla::CheckedInt;
--- a/content/xbl/src/nsXBLBinding.cpp
+++ b/content/xbl/src/nsXBLBinding.cpp
@@ -108,17 +108,17 @@ XBLFinalize(JSFreeOp *fop, JSObject *obj
     static_cast<nsXBLDocumentInfo*>(::JS_GetPrivate(obj));
   NS_RELEASE(docInfo);
   
   nsXBLJSClass* c = static_cast<nsXBLJSClass*>(::JS_GetClass(obj));
   c->Drop();
 }
 
 static JSBool
-XBLResolve(JSContext *cx, JSObject *obj, jsid id, unsigned flags,
+XBLResolve(JSContext *cx, JSHandleObject obj, JSHandleId id, unsigned flags,
            JSObject **objp)
 {
   // Note: if we get here, that means that the implementation for some binding
   // was installed, which means that AllowScripts() tested true.  Hence no need
   // to do checks like that here.
   
   // Default to not resolving things.
   NS_ASSERTION(*objp, "Must have starting object");
--- a/content/xbl/src/nsXBLDocumentInfo.cpp
+++ b/content/xbl/src/nsXBLDocumentInfo.cpp
@@ -138,33 +138,33 @@ nsXBLDocGlobalObject::doCheckAccess(JSCo
   }
 
   nsresult rv = ssm->CheckPropertyAccess(cx, obj, JS_GetClass(obj)->name,
                                          id, accessType);
   return NS_SUCCEEDED(rv);
 }
 
 static JSBool
-nsXBLDocGlobalObject_getProperty(JSContext *cx, JSObject *obj,
-                                 jsid id, jsval *vp)
+nsXBLDocGlobalObject_getProperty(JSContext *cx, JSHandleObject obj,
+                                 JSHandleId id, jsval *vp)
 {
   return nsXBLDocGlobalObject::
     doCheckAccess(cx, obj, id, nsIXPCSecurityManager::ACCESS_GET_PROPERTY);
 }
 
 static JSBool
-nsXBLDocGlobalObject_setProperty(JSContext *cx, JSObject *obj,
-                                 jsid id, JSBool strict, jsval *vp)
+nsXBLDocGlobalObject_setProperty(JSContext *cx, JSHandleObject obj,
+                                 JSHandleId id, JSBool strict, jsval *vp)
 {
   return nsXBLDocGlobalObject::
     doCheckAccess(cx, obj, id, nsIXPCSecurityManager::ACCESS_SET_PROPERTY);
 }
 
 static JSBool
-nsXBLDocGlobalObject_checkAccess(JSContext *cx, JSObject *obj, jsid id,
+nsXBLDocGlobalObject_checkAccess(JSContext *cx, JSHandleObject obj, JSHandleId id,
                                  JSAccessMode mode, jsval *vp)
 {
   PRUint32 translated;
   if (mode & JSACC_WRITE) {
     translated = nsIXPCSecurityManager::ACCESS_SET_PROPERTY;
   } else {
     translated = nsIXPCSecurityManager::ACCESS_GET_PROPERTY;
   }
@@ -185,17 +185,17 @@ nsXBLDocGlobalObject_finalize(JSFreeOp *
 
   // The addref was part of JSObject construction
   NS_RELEASE(nativeThis);
 
   DestroyProtoOrIfaceCache(obj);
 }
 
 static JSBool
-nsXBLDocGlobalObject_resolve(JSContext *cx, JSObject *obj, jsid id)
+nsXBLDocGlobalObject_resolve(JSContext *cx, JSHandleObject obj, JSHandleId id)
 {
   JSBool did_resolve = JS_FALSE;
   return JS_ResolveStandardClass(cx, obj, id, &did_resolve);
 }
 
 
 JSClass nsXBLDocGlobalObject::gSharedGlobalClass = {
     "nsXBLPrototypeScript compilation scope",
--- a/content/xul/document/src/nsXULPrototypeDocument.cpp
+++ b/content/xul/document/src/nsXULPrototypeDocument.cpp
@@ -132,17 +132,17 @@ nsXULPDGlobalObject_finalize(JSFreeOp *f
     // The addref was part of JSObject construction
     NS_RELEASE(nativeThis);
 
     DestroyProtoOrIfaceCache(obj);
 }
 
 
 JSBool
-nsXULPDGlobalObject_resolve(JSContext *cx, JSObject *obj, jsid id)
+nsXULPDGlobalObject_resolve(JSContext *cx, JSHandleObject obj, JSHandleId id)
 {
     JSBool did_resolve = JS_FALSE;
 
     return JS_ResolveStandardClass(cx, obj, id, &did_resolve);
 }
 
 
 JSClass nsXULPDGlobalObject::gSharedGlobalClass = {
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -5241,18 +5241,18 @@ static JSClass sGlobalScopePolluterClass
   (JSResolveOp)nsWindowSH::GlobalScopePolluterNewResolve,
   JS_ConvertStub,
   nsHTMLDocumentSH::ReleaseDocument
 };
 
 
 // static
 JSBool
-nsWindowSH::GlobalScopePolluterGetProperty(JSContext *cx, JSObject *obj,
-                                           jsid id, jsval *vp)
+nsWindowSH::GlobalScopePolluterGetProperty(JSContext *cx, JSHandleObject obj,
+                                           JSHandleId id, jsval *vp)
 {
   // Someone is accessing a element by referencing its name/id in the
   // global scope, do a security check to make sure that's ok.
 
   nsresult rv =
     sSecMan->CheckPropertyAccess(cx, ::JS_GetGlobalForObject(cx, obj),
                                  "Window", id,
                                  nsIXPCSecurityManager::ACCESS_GET_PROPERTY);
@@ -5268,17 +5268,17 @@ nsWindowSH::GlobalScopePolluterGetProper
   // catch and fix these mistakes.
   PrintWarningOnConsole(cx, "GlobalScopeElementReference");
 
   return JS_TRUE;
 }
 
 // static
 JSBool
-nsWindowSH::SecurityCheckOnAddDelProp(JSContext *cx, JSObject *obj, jsid id,
+nsWindowSH::SecurityCheckOnAddDelProp(JSContext *cx, JSHandleObject obj, JSHandleId id,
                                       jsval *vp)
 {
   // Someone is accessing a element by referencing its name/id in the
   // global scope, do a security check to make sure that's ok.
 
   nsresult rv =
     sSecMan->CheckPropertyAccess(cx, ::JS_GetGlobalForObject(cx, obj),
                                  "Window", id,
@@ -5286,33 +5286,33 @@ nsWindowSH::SecurityCheckOnAddDelProp(JS
 
   // If !NS_SUCCEEDED(rv) the security check failed. The security
   // manager set a JS exception for us.
   return NS_SUCCEEDED(rv);
 }
 
 // static
 JSBool
-nsWindowSH::SecurityCheckOnSetProp(JSContext *cx, JSObject *obj, jsid id, JSBool strict,
+nsWindowSH::SecurityCheckOnSetProp(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict,
                                    jsval *vp)
 {
   return SecurityCheckOnAddDelProp(cx, obj, id, vp);
 }
 
 static nsHTMLDocument*
 GetDocument(JSObject *obj)
 {
   return static_cast<nsHTMLDocument*>(
     static_cast<nsIHTMLDocument*>(::JS_GetPrivate(obj)));
 }
 
 // static
 JSBool
-nsWindowSH::GlobalScopePolluterNewResolve(JSContext *cx, JSObject *obj,
-                                          jsid id, unsigned flags,
+nsWindowSH::GlobalScopePolluterNewResolve(JSContext *cx, JSHandleObject obj,
+                                          JSHandleId id, unsigned flags,
                                           JSObject **objp)
 {
   if (flags & (JSRESOLVE_ASSIGNING | JSRESOLVE_DECLARING |
                JSRESOLVE_CLASSNAME | JSRESOLVE_QUALIFIED) ||
       !JSID_IS_STRING(id)) {
     // Nothing to do here if we're either assigning or declaring,
     // resolving a class name, doing a qualified resolve, or
     // resolving a number.
@@ -5791,17 +5791,17 @@ static const IDBConstant sIDBConstants[]
   { IDBConstant::IDBRequest,     "LOADING",           "pending" },
   { IDBConstant::IDBRequest,     "DONE",              "done" },
   { IDBConstant::IDBTransaction, "READ_ONLY",         "readonly" },
   { IDBConstant::IDBTransaction, "READ_WRITE",        "readwrite" },
   { IDBConstant::IDBTransaction, "VERSION_CHANGE",    "versionchange" },
 };
 
 static JSBool
-IDBConstantGetter(JSContext *cx, JSObject *obj, jsid id, jsval* vp)
+IDBConstantGetter(JSContext *cx, JSHandleObject obj, JSHandleId id, jsval* vp)
 {
   MOZ_ASSERT(JSID_IS_INT(id));
   
   int8_t index = JSID_TO_INT(id);
   
   MOZ_ASSERT((uint8_t)index < mozilla::ArrayLength(sIDBConstants));
 
   const IDBConstant& c = sIDBConstants[index];
@@ -6926,47 +6926,52 @@ LocationSetterGuts(JSContext *cx, JSObje
   nsDependentJSString depStr;
   NS_ENSURE_TRUE(depStr.init(cx, val), NS_ERROR_UNEXPECTED);
   
   return location->SetHref(depStr);
 }
 
 template<class Interface>
 static JSBool
-LocationSetter(JSContext *cx, JSObject *obj, jsid id, JSBool strict,
+LocationSetter(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict,
                jsval *vp)
 {
   nsresult rv = LocationSetterGuts<Interface>(cx, obj, vp);
   if (NS_FAILED(rv)) {
     if (!::JS_IsExceptionPending(cx)) {
       nsDOMClassInfo::ThrowJSException(cx, rv);
     }
     return JS_FALSE;
   }
 
   return JS_TRUE;
 }
 
 static JSBool
-LocationSetterUnwrapper(JSContext *cx, JSObject *obj, jsid id, JSBool strict,
+LocationSetterUnwrapper(JSContext *cx, JSHandleObject obj_, JSHandleId id, JSBool strict,
                         jsval *vp)
 {
+  JS::RootedVarObject obj(cx, obj_);
+
   JSObject *wrapped = XPCWrapper::UnsafeUnwrapSecurityWrapper(obj);
   if (wrapped) {
     obj = wrapped;
   }
 
   return LocationSetter<nsIDOMWindow>(cx, obj, id, strict, vp);
 }
 
 NS_IMETHODIMP
 nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                       JSObject *obj, jsid id, PRUint32 flags,
+                       JSObject *obj_, jsid id_, PRUint32 flags,
                        JSObject **objp, bool *_retval)
 {
+  JS::RootedVarObject obj(cx, obj_);
+  JS::RootedVarId id(cx, id_);
+
   nsGlobalWindow *win = nsGlobalWindow::FromWrapper(wrapper);
 
   if (!JSID_IS_STRING(id)) {
     if (JSID_IS_INT(id) && JSID_TO_INT(id) >= 0 && !(flags & JSRESOLVE_ASSIGNING)) {
       // If we're resolving a numeric property, treat that as if
       // window.frames[n] is resolved (since window.frames ===
       // window), if window.frames[n] is a child frame, define a
       // property for this index.
@@ -7052,29 +7057,29 @@ nsWindowSH::NewResolve(nsIXPConnectWrapp
 
     return NS_OK;
   }
 
   if (!(flags & JSRESOLVE_ASSIGNING)) {
     // We want this code to be before the child frame lookup code
     // below so that a child frame named 'constructor' doesn't
     // shadow the window's constructor property.
-    if (id == sConstructor_id) {
+    if (sConstructor_id == id) {
       return ResolveConstructor(cx, obj, objp);
     }
   }
 
   if (!my_context || !my_context->IsContextInitialized()) {
     // The context is not yet initialized so there's nothing we can do
     // here yet.
 
     return NS_OK;
   }
 
-  if (id == sLocation_id) {
+  if (sLocation_id == id) {
     // This must be done even if we're just getting the value of
     // window.location (i.e. no checking flags & JSRESOLVE_ASSIGNING
     // here) since we must define window.location to prevent the
     // getter from being overriden (for security reasons).
 
     // Note: Because we explicitly don't forward to the inner window
     // above, we have to ensure here that our window has a current
     // inner window so that the location object we return will work.
@@ -7203,17 +7208,17 @@ nsWindowSH::NewResolve(nsIXPConnectWrapp
     if (did_resolve) {
       // GlobalResolve() resolved something, so we're done here.
       *objp = obj;
 
       return NS_OK;
     }
   }
 
-  if (id == s_content_id) {
+  if (s_content_id == id) {
     // Map window._content to window.content for backwards
     // compatibility, this should spit out an message on the JS
     // console.
 
     JSObject *windowObj = win->GetGlobalJSObject();
 
     JSAutoRequest ar(cx);
 
@@ -7252,17 +7257,17 @@ nsWindowSH::NewResolve(nsIXPConnectWrapp
                                    JS_StrictPropertyStub, JSPROP_ENUMERATE)) {
         return NS_ERROR_FAILURE;
       }
       *objp = obj;
 
       return NS_OK;
     }
   } else {
-    if (id == sNavigator_id) {
+    if (sNavigator_id == id) {
       nsCOMPtr<nsIDOMNavigator> navigator;
       rv = win->GetNavigator(getter_AddRefs(navigator));
       NS_ENSURE_SUCCESS(rv, rv);
 
       jsval v;
       nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
       rv = WrapNative(cx, obj, navigator, &NS_GET_IID(nsIDOMNavigator), true,
                       &v, getter_AddRefs(holder));
@@ -7275,17 +7280,17 @@ nsWindowSH::NewResolve(nsIXPConnectWrapp
                                    JSPROP_ENUMERATE)) {
         return NS_ERROR_FAILURE;
       }
       *objp = obj;
 
       return NS_OK;
     }
 
-    if (id == sDocument_id) {
+    if (sDocument_id == id) {
       nsCOMPtr<nsIDOMDocument> document;
       rv = win->GetDocument(getter_AddRefs(document));
       NS_ENSURE_SUCCESS(rv, rv);
 
       // FIXME Ideally we'd have an nsIDocument here and get nsWrapperCache
       //       from it.
       jsval v;
       nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
@@ -7309,17 +7314,17 @@ nsWindowSH::NewResolve(nsIXPConnectWrapp
         if (!*_retval) {
           return NS_ERROR_UNEXPECTED;
         }
       }
 
       return NS_OK;
     }
 
-    if (id == sDialogArguments_id && win->IsModalContentWindow()) {
+    if (sDialogArguments_id == id && win->IsModalContentWindow()) {
       nsCOMPtr<nsIArray> args;
       ((nsGlobalModalWindow *)win)->GetDialogArguments(getter_AddRefs(args));
 
       nsIScriptContext *script_cx = win->GetContext();
       if (script_cx) {
         JSAutoSuspendRequest asr(cx);
 
         // Make nsJSContext::SetProperty()'s magic argument array
@@ -7597,17 +7602,17 @@ nsNavigatorSH::PreCreate(nsISupports *na
   }
   return SetParentToWindow(win, parentObj);
 }
 
 // DOM Node helper
 
 template<nsresult (*func)(JSContext *cx, JSObject *obj, jsval *vp)>
 static JSBool
-GetterShim(JSContext *cx, JSObject *obj, jsid /* unused */, jsval *vp)
+GetterShim(JSContext *cx, JSHandleObject obj, JSHandleId /* unused */, jsval *vp)
 {
   nsresult rv = (*func)(cx, obj, vp);
   if (NS_FAILED(rv)) {
     if (!::JS_IsExceptionPending(cx)) {
       nsDOMClassInfo::ThrowJSException(cx, rv);
     }
     return JS_FALSE;
   }
@@ -8778,24 +8783,26 @@ nsHTMLDocumentSH::GetDocumentAllNodeList
 
     return JS_FALSE;
   }
 
   return *nodeList != nsnull;
 }
 
 JSBool
-nsHTMLDocumentSH::DocumentAllGetProperty(JSContext *cx, JSObject *obj,
-                                         jsid id, jsval *vp)
-{
+nsHTMLDocumentSH::DocumentAllGetProperty(JSContext *cx, JSHandleObject obj_,
+                                         JSHandleId id, jsval *vp)
+{
+  JSObject *obj = obj_;
+
   // document.all.item and .namedItem get their value in the
   // newResolve hook, so nothing to do for those properties here. And
   // we need to return early to prevent <div id="item"> from shadowing
   // document.all.item(), etc.
-  if (id == sItem_id || id == sNamedItem_id) {
+  if (sItem_id == id || sNamedItem_id == id) {
     return JS_TRUE;
   }
 
   while (js::GetObjectJSClass(obj) != &sHTMLDocumentAllClass) {
     obj = js::GetObjectProto(obj);
 
     if (!obj) {
       NS_ERROR("The JS engine lies!");
@@ -8805,17 +8812,17 @@ nsHTMLDocumentSH::DocumentAllGetProperty
   }
 
   nsHTMLDocument *doc = GetDocument(obj);
   nsISupports *result;
   nsWrapperCache *cache;
   nsresult rv = NS_OK;
 
   if (JSID_IS_STRING(id)) {
-    if (id == sLength_id) {
+    if (sLength_id == id) {
       // Map document.all.length to the length of the collection
       // document.getElementsByTagName("*"), and make sure <div
       // id="length"> doesn't shadow document.all.length.
 
       nsRefPtr<nsContentList> nodeList;
       if (!GetDocumentAllNodeList(cx, obj, doc, getter_AddRefs(nodeList))) {
         return JS_FALSE;
       }
@@ -8827,17 +8834,17 @@ nsHTMLDocumentSH::DocumentAllGetProperty
         nsDOMClassInfo::ThrowJSException(cx, rv);
 
         return JS_FALSE;
       }
 
       *vp = INT_TO_JSVAL(length);
 
       return JS_TRUE;
-    } else if (id != sTags_id) {
+    } else if (sTags_id != id) {
       // For all other strings, look for an element by id or name.
 
       nsDependentJSString str(id);
 
       result = doc->GetDocumentAllResult(str, &cache, &rv);
 
       if (NS_FAILED(rv)) {
         nsDOMClassInfo::ThrowJSException(cx, rv);
@@ -8875,45 +8882,45 @@ nsHTMLDocumentSH::DocumentAllGetProperty
   } else {
     *vp = JSVAL_VOID;
   }
 
   return JS_TRUE;
 }
 
 JSBool
-nsHTMLDocumentSH::DocumentAllNewResolve(JSContext *cx, JSObject *obj, jsid id,
+nsHTMLDocumentSH::DocumentAllNewResolve(JSContext *cx, JSHandleObject obj, JSHandleId id,
                                         unsigned flags, JSObject **objp)
 {
   if (flags & JSRESOLVE_ASSIGNING) {
     // Nothing to do here if we're assigning
 
     return JS_TRUE;
   }
 
   jsval v = JSVAL_VOID;
 
-  if (id == sItem_id || id == sNamedItem_id) {
+  if (sItem_id == id || sNamedItem_id == id) {
     // Define the item() or namedItem() method.
 
     JSFunction *fnc = ::JS_DefineFunctionById(cx, obj, id, CallToGetPropMapper,
                                               0, JSPROP_ENUMERATE);
     *objp = obj;
 
     return fnc != nsnull;
   }
 
-  if (id == sLength_id) {
+  if (sLength_id == id) {
     // document.all.length. Any jsval other than undefined would do
     // here, all we need is to get into the code below that defines
     // this propery on obj, the rest happens in
     // DocumentAllGetProperty().
 
     v = JSVAL_ONE;
-  } else if (id == sTags_id) {
+  } else if (sTags_id == id) {
     nsHTMLDocument *doc = GetDocument(obj);
 
     JSObject *tags = ::JS_NewObject(cx, &sHTMLDocumentAllTagsClass, nsnull,
                                     ::JS_GetGlobalForObject(cx, obj));
     if (!tags) {
       return JS_FALSE;
     }
 
@@ -9013,20 +9020,20 @@ FlagsToPrivate(PRUint32 flags)
 static inline PRUint32
 PrivateToFlags(void *priv)
 {
   JS_ASSERT(size_t(priv) <= PR_UINT32_MAX && (size_t(priv) & 1) == 0);
   return (PRUint32)(size_t(priv) >> 1);
 }
 
 JSBool
-nsHTMLDocumentSH::DocumentAllHelperGetProperty(JSContext *cx, JSObject *obj,
-                                               jsid id, JS::Value *vp)
-{
-  if (id != nsDOMClassInfo::sAll_id) {
+nsHTMLDocumentSH::DocumentAllHelperGetProperty(JSContext *cx, JSHandleObject obj,
+                                               JSHandleId id, JS::Value *vp)
+{
+  if (nsDOMClassInfo::sAll_id != id) {
     return JS_TRUE;
   }
 
   JSObject *helper = GetDocumentAllHelper(obj);
 
   if (!helper) {
     NS_ERROR("Uh, how'd we get here?");
 
@@ -9072,21 +9079,21 @@ nsHTMLDocumentSH::DocumentAllHelperGetPr
       vp->setObject(*all);
     }
   }
 
   return JS_TRUE;
 }
 
 JSBool
-nsHTMLDocumentSH::DocumentAllHelperNewResolve(JSContext *cx, JSObject *obj,
-                                              jsid id, unsigned flags,
+nsHTMLDocumentSH::DocumentAllHelperNewResolve(JSContext *cx, JSHandleObject obj,
+                                              JSHandleId id, unsigned flags,
                                               JSObject **objp)
 {
-  if (id == nsDOMClassInfo::sAll_id) {
+  if (nsDOMClassInfo::sAll_id == id) {
     // document.all is resolved for the first time. Define it.
     JSObject *helper = GetDocumentAllHelper(obj);
 
     if (helper) {
       if (!::JS_DefineProperty(cx, helper, "all", JSVAL_VOID, nsnull, nsnull,
                                JSPROP_ENUMERATE)) {
         return JS_FALSE;
       }
@@ -9095,18 +9102,18 @@ nsHTMLDocumentSH::DocumentAllHelperNewRe
     }
   }
 
   return JS_TRUE;
 }
 
 
 JSBool
-nsHTMLDocumentSH::DocumentAllTagsNewResolve(JSContext *cx, JSObject *obj,
-                                            jsid id, unsigned flags,
+nsHTMLDocumentSH::DocumentAllTagsNewResolve(JSContext *cx, JSHandleObject obj,
+                                            JSHandleId id, unsigned flags,
                                             JSObject **objp)
 {
   if (JSID_IS_STRING(id)) {
     nsDocument *doc = GetDocument(obj);
 
     JSObject *proto = ::JS_GetPrototype(obj);
     if (NS_UNLIKELY(!proto)) {
       return JS_TRUE;
--- a/dom/base/nsDOMClassInfo.h
+++ b/dom/base/nsDOMClassInfo.h
@@ -416,24 +416,24 @@ public:
   NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                         JSObject *obj, jsid id, PRUint32 flags,
                         JSObject **objp, bool *_retval);
   NS_IMETHOD Finalize(nsIXPConnectWrappedNative *wrapper, JSFreeOp *fop,
                       JSObject *obj);
   NS_IMETHOD OuterObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
                          JSObject * obj, JSObject * *_retval);
 
-  static JSBool GlobalScopePolluterNewResolve(JSContext *cx, JSObject *obj,
-                                              jsid id, unsigned flags,
+  static JSBool GlobalScopePolluterNewResolve(JSContext *cx, JSHandleObject obj,
+                                              JSHandleId id, unsigned flags,
                                               JSObject **objp);
-  static JSBool GlobalScopePolluterGetProperty(JSContext *cx, JSObject *obj,
-                                               jsid id, jsval *vp);
-  static JSBool SecurityCheckOnAddDelProp(JSContext *cx, JSObject *obj, jsid id,
+  static JSBool GlobalScopePolluterGetProperty(JSContext *cx, JSHandleObject obj,
+                                               JSHandleId id, jsval *vp);
+  static JSBool SecurityCheckOnAddDelProp(JSContext *cx, JSHandleObject obj, JSHandleId id,
                                           jsval *vp);
-  static JSBool SecurityCheckOnSetProp(JSContext *cx, JSObject *obj, jsid id,
+  static JSBool SecurityCheckOnSetProp(JSContext *cx, JSHandleObject obj, JSHandleId id,
                                        JSBool strict, jsval *vp);
   static void InvalidateGlobalScopePolluter(JSContext *cx, JSObject *obj);
   static nsresult InstallGlobalScopePolluter(JSContext *cx, JSObject *obj,
                                              nsIHTMLDocument *doc);
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsWindowSH(aData);
   }
@@ -789,29 +789,29 @@ protected:
   {
   }
 
   static JSBool GetDocumentAllNodeList(JSContext *cx, JSObject *obj,
                                        nsDocument *doc,
                                        nsContentList **nodeList);
 
 public:
-  static JSBool DocumentAllGetProperty(JSContext *cx, JSObject *obj, jsid id,
+  static JSBool DocumentAllGetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id,
                                        jsval *vp);
-  static JSBool DocumentAllNewResolve(JSContext *cx, JSObject *obj, jsid id,
+  static JSBool DocumentAllNewResolve(JSContext *cx, JSHandleObject obj, JSHandleId id,
                                       unsigned flags, JSObject **objp);
   static void ReleaseDocument(JSFreeOp *fop, JSObject *obj);
   static JSBool CallToGetPropMapper(JSContext *cx, unsigned argc, jsval *vp);
-  static JSBool DocumentAllHelperGetProperty(JSContext *cx, JSObject *obj,
-                                             jsid id, jsval *vp);
-  static JSBool DocumentAllHelperNewResolve(JSContext *cx, JSObject *obj,
-                                            jsid id, unsigned flags,
+  static JSBool DocumentAllHelperGetProperty(JSContext *cx, JSHandleObject obj,
+                                             JSHandleId id, jsval *vp);
+  static JSBool DocumentAllHelperNewResolve(JSContext *cx, JSHandleObject obj,
+                                            JSHandleId id, unsigned flags,
                                             JSObject **objp);
-  static JSBool DocumentAllTagsNewResolve(JSContext *cx, JSObject *obj,
-                                          jsid id, unsigned flags,
+  static JSBool DocumentAllTagsNewResolve(JSContext *cx, JSHandleObject obj,
+                                          JSHandleId id, unsigned flags,
                                           JSObject **objp);
 
   NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                         JSObject *obj, jsid id, PRUint32 flags,
                         JSObject **objp, bool *_retval);
   NS_IMETHOD GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                          JSObject *obj, jsid id, jsval *vp, bool *_retval);
 
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -1815,17 +1815,17 @@ nsDOMWindowUtils::GetParent(const JS::Va
   }
 
   JSObject* parent = JS_GetParent(JSVAL_TO_OBJECT(aObject));
   *aParent = OBJECT_TO_JSVAL(parent);
 
   // Outerize if necessary.
   if (parent) {
     if (JSObjectOp outerize = js::GetObjectClass(parent)->ext.outerObject) {
-      *aParent = OBJECT_TO_JSVAL(outerize(aCx, parent));
+      *aParent = OBJECT_TO_JSVAL(outerize(aCx, JS::RootedVarObject(aCx, parent)));
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetOuterWindowID(PRUint64 *aWindowID)
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -468,18 +468,18 @@ class CGAbstractClassHook(CGAbstractStat
         # Override me
         assert(False)
 
 class CGAddPropertyHook(CGAbstractClassHook):
     """
     A hook for addProperty, used to preserve our wrapper from GC.
     """
     def __init__(self, descriptor):
-        args = [Argument('JSContext*', 'cx'), Argument('JSObject*', 'obj'),
-                Argument('jsid', 'id'), Argument('jsval*', 'vp')]
+        args = [Argument('JSContext*', 'cx'), Argument('JSHandleObject', 'obj'),
+                Argument('JSHandleId', 'id'), Argument('jsval*', 'vp')]
         CGAbstractClassHook.__init__(self, descriptor, ADDPROPERTY_HOOK_NAME,
                                      'JSBool', args)
 
     def generate_code(self):
         return """
   JSCompartment* compartment = js::GetObjectCompartment(obj);
   xpc::CompartmentPrivate* priv =
     static_cast<xpc::CompartmentPrivate*>(JS_GetCompartmentPrivate(compartment));
@@ -576,17 +576,17 @@ class CGClassConstructHook(CGAbstractSta
         nativeName = "_" + MakeNativeName(self._ctor.identifier.name)
         nativeName = self.descriptor.binaryNames.get(name, nativeName)
         callGenerator = CGMethodCall(preArgs, nativeName, True,
                                      self.descriptor, self._ctor, {})
         return preamble + callGenerator.define();
 
 class CGClassHasInstanceHook(CGAbstractStaticMethod):
     def __init__(self, descriptor):
-        args = [Argument('JSContext*', 'cx'), Argument('JSObject*', 'obj'),
+        args = [Argument('JSContext*', 'cx'), Argument('JSHandleObject', 'obj'),
                 Argument('const jsval*', 'v'), Argument('JSBool*', 'bp')]
         CGAbstractStaticMethod.__init__(self, descriptor, HASINSTANCE_HOOK_NAME,
                                         'JSBool', args)
 
     def define(self):
         if not self.descriptor.hasInstanceInterface:
             return ""
         return CGAbstractStaticMethod.define(self)
@@ -603,22 +603,22 @@ class CGClassHasInstanceHook(CGAbstractS
   jsval protov;
   if (!JS_GetProperty(cx, obj, "prototype", &protov))
     return false;
   if (!protov.isObject()) {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_PROTOTYPE,
                          "%s");
     return false;
   }
-  obj = &protov.toObject();
+  JSObject *objProto = &protov.toObject();
 
   JSObject* instance = &v->toObject();
   JSObject* proto = JS_GetPrototype(instance);
   while (proto) {
-    if (proto == obj) {
+    if (proto == objProto) {
       *bp = true;
       return true;
     }
     proto = JS_GetPrototype(proto);
   }
 
   nsISupports* native =
     nsContentUtils::XPConnect()->GetNativeOfWrapper(cx, instance);
@@ -2423,18 +2423,18 @@ class CGNativeGetter(CGAbstractBindingMe
     """
     def __init__(self, descriptor, attr):
         self.attr = attr
         name = 'get_' + attr.identifier.name
         if generateNativeAccessors:
             args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'),
                     Argument('JS::Value*', 'vp')]
         else:
-            args = [Argument('JSContext*', 'cx'), Argument('JSObject*', 'obj'),
-                    Argument('jsid', 'id'), Argument('JS::Value*', 'vp')]
+            args = [Argument('JSContext*', 'cx'), Argument('JSHandleObject', 'obj'),
+                    Argument('JSHandleId', 'id'), Argument('JS::Value*', 'vp')]
         CGAbstractBindingMethod.__init__(self, descriptor, name, args,
                                          descriptor.getExtendedAttributes(self.attr, getter=True))
 
     def getThis(self):
         if generateNativeAccessors:
             return CGAbstractBindingMethod.getThis(self)
         return CGIndenter(
             CGGeneric("%s* self;" % self.descriptor.nativeType))
@@ -2452,18 +2452,18 @@ class CGNativeSetter(CGAbstractBindingMe
     def __init__(self, descriptor, attr):
         self.attr = attr
         baseName = attr.identifier.name
         name = 'set_' + attr.identifier.name
         if generateNativeAccessors:
             args = [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'),
                     Argument('JS::Value*', 'vp')]
         else:
-            args = [Argument('JSContext*', 'cx'), Argument('JSObject*', 'obj'),
-                    Argument('jsid', 'id'), Argument('JSBool', 'strict'),
+            args = [Argument('JSContext*', 'cx'), Argument('JSHandleObject', 'obj'),
+                    Argument('JSHandleId', 'id'), Argument('JSBool', 'strict'),
                     Argument('JS::Value*', 'vp')]
         CGAbstractBindingMethod.__init__(self, descriptor, name, args,
                                          descriptor.getExtendedAttributes(self.attr, setter=True))
 
     def getThis(self):
         if generateNativeAccessors:
             return CGAbstractBindingMethod.getThis(self)
         return CGIndenter(
--- a/dom/plugins/base/nsJSNPRuntime.cpp
+++ b/dom/plugins/base/nsJSNPRuntime.cpp
@@ -138,37 +138,37 @@ NPClass nsJSObjWrapper::sJSObjWrapperNPC
     nsJSObjWrapper::NP_GetProperty,
     nsJSObjWrapper::NP_SetProperty,
     nsJSObjWrapper::NP_RemoveProperty,
     nsJSObjWrapper::NP_Enumerate,
     nsJSObjWrapper::NP_Construct
   };
 
 static JSBool
-NPObjWrapper_AddProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
+NPObjWrapper_AddProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, jsval *vp);
 
 static JSBool
-NPObjWrapper_DelProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
+NPObjWrapper_DelProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, jsval *vp);
 
 static JSBool
-NPObjWrapper_SetProperty(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp);
+NPObjWrapper_SetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, jsval *vp);
 
 static JSBool
-NPObjWrapper_GetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
+NPObjWrapper_GetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, jsval *vp);
 
 static JSBool
-NPObjWrapper_newEnumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
+NPObjWrapper_newEnumerate(JSContext *cx, JSHandleObject obj, JSIterateOp enum_op,
                           jsval *statep, jsid *idp);
 
 static JSBool
-NPObjWrapper_NewResolve(JSContext *cx, JSObject *obj, jsid id, unsigned flags,
+NPObjWrapper_NewResolve(JSContext *cx, JSHandleObject obj, JSHandleId id, unsigned flags,
                         JSObject **objp);
 
 static JSBool
-NPObjWrapper_Convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp);
+NPObjWrapper_Convert(JSContext *cx, JSHandleObject obj, JSType type, jsval *vp);
 
 static void
 NPObjWrapper_Finalize(JSFreeOp *fop, JSObject *obj);
 
 static JSBool
 NPObjWrapper_Call(JSContext *cx, unsigned argc, jsval *vp);
 
 static JSBool
@@ -199,17 +199,17 @@ static JSClass sNPObjectJSWrapperClass =
 typedef struct NPObjectMemberPrivate {
     JSObject *npobjWrapper;
     jsval fieldValue;
     NPIdentifier methodName;
     NPP   npp;
 } NPObjectMemberPrivate;
 
 static JSBool
-NPObjectMember_Convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp);
+NPObjectMember_Convert(JSContext *cx, JSHandleObject obj, JSType type, jsval *vp);
 
 static void
 NPObjectMember_Finalize(JSFreeOp *fop, JSObject *obj);
 
 static JSBool
 NPObjectMember_Call(JSContext *cx, unsigned argc, jsval *vp);
 
 static void
@@ -1172,17 +1172,17 @@ GetNPObject(JSObject *obj)
 
   return (NPObject *)::JS_GetPrivate(obj);
 }
 
 
 // Does not actually add a property because this is always followed by a
 // SetProperty call.
 static JSBool
-NPObjWrapper_AddProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+NPObjWrapper_AddProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, jsval *vp)
 {
   NPObject *npobj = GetNPObject(obj);
 
   if (!npobj || !npobj->_class || !npobj->_class->hasProperty ||
       !npobj->_class->hasMethod) {
     ThrowJSException(cx, "Bad NPObject as private data!");
 
     return JS_FALSE;
@@ -1213,17 +1213,17 @@ NPObjWrapper_AddProperty(JSContext *cx, 
 
     return JS_FALSE;
   }
 
   return JS_TRUE;
 }
 
 static JSBool
-NPObjWrapper_DelProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+NPObjWrapper_DelProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, jsval *vp)
 {
   NPObject *npobj = GetNPObject(obj);
 
   if (!npobj || !npobj->_class || !npobj->_class->hasProperty ||
       !npobj->_class->removeProperty) {
     ThrowJSException(cx, "Bad NPObject as private data!");
 
     return JS_FALSE;
@@ -1244,17 +1244,17 @@ NPObjWrapper_DelProperty(JSContext *cx, 
 
   if (!npobj->_class->removeProperty(npobj, identifier))
     *vp = JSVAL_FALSE;
 
   return ReportExceptionIfPending(cx);
 }
 
 static JSBool
-NPObjWrapper_SetProperty(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
+NPObjWrapper_SetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, jsval *vp)
 {
   NPObject *npobj = GetNPObject(obj);
 
   if (!npobj || !npobj->_class || !npobj->_class->hasProperty ||
       !npobj->_class->setProperty) {
     ThrowJSException(cx, "Bad NPObject as private data!");
 
     return JS_FALSE;
@@ -1303,17 +1303,17 @@ NPObjWrapper_SetProperty(JSContext *cx, 
 
     return JS_FALSE;
   }
 
   return JS_TRUE;
 }
 
 static JSBool
-NPObjWrapper_GetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+NPObjWrapper_GetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, jsval *vp)
 {
   NPObject *npobj = GetNPObject(obj);
 
   if (!npobj || !npobj->_class || !npobj->_class->hasProperty ||
       !npobj->_class->hasMethod || !npobj->_class->getProperty) {
     ThrowJSException(cx, "Bad NPObject as private data!");
 
     return JS_FALSE;
@@ -1543,17 +1543,17 @@ CallNPMethod(JSContext *cx, unsigned arg
 
 struct NPObjectEnumerateState {
   PRUint32     index;
   PRUint32     length;
   NPIdentifier *value;
 };
 
 static JSBool
-NPObjWrapper_newEnumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
+NPObjWrapper_newEnumerate(JSContext *cx, JSHandleObject obj, JSIterateOp enum_op,
                           jsval *statep, jsid *idp)
 {
   NPObject *npobj = GetNPObject(obj);
   NPIdentifier *enum_value;
   uint32_t length;
   NPObjectEnumerateState *state;
 
   if (!npobj || !npobj->_class) {
@@ -1623,17 +1623,17 @@ NPObjWrapper_newEnumerate(JSContext *cx,
 
     break;
   }
 
   return JS_TRUE;
 }
 
 static JSBool
-NPObjWrapper_NewResolve(JSContext *cx, JSObject *obj, jsid id, unsigned flags,
+NPObjWrapper_NewResolve(JSContext *cx, JSHandleObject obj, JSHandleId id, unsigned flags,
                         JSObject **objp)
 {
   NPObject *npobj = GetNPObject(obj);
 
   if (!npobj || !npobj->_class || !npobj->_class->hasProperty ||
       !npobj->_class->hasMethod) {
     ThrowJSException(cx, "Bad NPObject as private data!");
 
@@ -1677,17 +1677,17 @@ NPObjWrapper_NewResolve(JSContext *cx, J
     return fnc != nsnull;
   }
 
   // no property or method
   return JS_TRUE;
 }
 
 static JSBool
-NPObjWrapper_Convert(JSContext *cx, JSObject *obj, JSType hint, jsval *vp)
+NPObjWrapper_Convert(JSContext *cx, JSHandleObject obj, JSType hint, jsval *vp)
 {
   JS_ASSERT(hint == JSTYPE_NUMBER || hint == JSTYPE_STRING || hint == JSTYPE_VOID);
 
   // Plugins do not simply use JS_ConvertStub, and the default [[DefaultValue]]
   // behavior, because that behavior involves calling toString or valueOf on
   // objects which weren't designed to accommodate this.  Usually this wouldn't
   // be a problem, because the absence of either property, or the presence of
   // either property with a value that isn't callable, will cause that property
@@ -2180,17 +2180,17 @@ CreateNPObjectMember(NPP npp, JSContext 
   memberPrivate->npp = npp;
 
   ::JS_RemoveValueRoot(cx, vp);
 
   return JS_TRUE;
 }
 
 static JSBool
-NPObjectMember_Convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
+NPObjectMember_Convert(JSContext *cx, JSHandleObject obj, JSType type, jsval *vp)
 {
   NPObjectMemberPrivate *memberPrivate =
     (NPObjectMemberPrivate *)::JS_GetInstancePrivate(cx, obj,
                                                      &sNPObjectMemberClass,
                                                      nsnull);
   if (!memberPrivate) {
     NS_ERROR("no Ambiguous Member Private data!");
     return JS_FALSE;
--- a/dom/workers/ChromeWorkerScope.cpp
+++ b/dom/workers/ChromeWorkerScope.cpp
@@ -41,17 +41,17 @@ UnicodeToNative(JSContext* aCx, const js
   return result;
 }
 
 JSCTypesCallbacks gCTypesCallbacks = {
   UnicodeToNative
 };
 
 JSBool
-CTypesLazyGetter(JSContext* aCx, JSObject* aObj, jsid aId, jsval* aVp)
+CTypesLazyGetter(JSContext* aCx, JSHandleObject aObj, JSHandleId aId, jsval* aVp)
 {
   NS_ASSERTION(JS_GetGlobalObject(aCx) == aObj, "Not a global object!");
   NS_ASSERTION(JSID_IS_STRING(aId), "Bad id!");
   NS_ASSERTION(JS_FlatStringEqualsAscii(JSID_TO_FLAT_STRING(aId), CTYPES_STR),
                "Bad id!");
 
   WorkerPrivate* worker = GetWorkerPrivateFromContext(aCx);
   NS_ASSERTION(worker->IsChromeWorker(), "This should always be true!");
--- a/dom/workers/Events.cpp
+++ b/dom/workers/Events.cpp
@@ -248,33 +248,33 @@ private:
   static void
   Finalize(JSFreeOp* aFop, JSObject* aObj)
   {
     JS_ASSERT(IsThisClass(JS_GetClass(aObj)));
     delete GetJSPrivateSafeish<Event>(aObj);
   }
 
   static JSBool
-  GetProperty(JSContext* aCx, JSObject* aObj, jsid aIdval, jsval* aVp)
+  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
   {
     JS_ASSERT(JSID_IS_INT(aIdval));
 
     int32 slot = JSID_TO_INT(aIdval);
 
     const char*& name = sProperties[slot - SLOT_FIRST].name;
     if (!GetInstancePrivate(aCx, aObj, name)) {
       return false;
     }
 
     *aVp = JS_GetReservedSlot(aObj, slot);
     return true;
   }
 
   static JSBool
-  GetConstant(JSContext* aCx, JSObject* aObj, jsid idval, jsval* aVp)
+  GetConstant(JSContext* aCx, JSHandleObject aObj, JSHandleId idval, jsval* aVp)
   {
     JS_ASSERT(JSID_IS_INT(idval));
     JS_ASSERT(JSID_TO_INT(idval) >= CAPTURING_PHASE &&
               JSID_TO_INT(idval) <= BUBBLING_PHASE);
 
     *aVp = INT_TO_JSVAL(JSID_TO_INT(idval));
     return true;
   }
@@ -538,17 +538,17 @@ private:
 #ifdef DEBUG
       priv->mData = NULL;
 #endif
       delete priv;
     }
   }
 
   static JSBool
-  GetProperty(JSContext* aCx, JSObject* aObj, jsid aIdval, jsval* aVp)
+  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
   {
     JS_ASSERT(JSID_IS_INT(aIdval));
 
     int32 slot = JSID_TO_INT(aIdval);
 
     JS_ASSERT(slot >= SLOT_data && slot < SLOT_COUNT);
 
     const char*& name = sProperties[slot - SLOT_FIRST].name;
@@ -746,17 +746,17 @@ private:
   static void
   Finalize(JSFreeOp* aFop, JSObject* aObj)
   {
     JS_ASSERT(IsThisClass(JS_GetClass(aObj)));
     delete GetJSPrivateSafeish<ErrorEvent>(aObj);
   }
 
   static JSBool
-  GetProperty(JSContext* aCx, JSObject* aObj, jsid aIdval, jsval* aVp)
+  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
   {
     JS_ASSERT(JSID_IS_INT(aIdval));
 
     int32 slot = JSID_TO_INT(aIdval);
 
     JS_ASSERT(slot >= SLOT_message && slot < SLOT_COUNT);
 
     const char*& name = sProperties[slot - SLOT_FIRST].name;
@@ -926,17 +926,17 @@ private:
   static void
   Finalize(JSFreeOp* aFop, JSObject* aObj)
   {
     JS_ASSERT(JS_GetClass(aObj) == &sClass);
     delete GetJSPrivateSafeish<ProgressEvent>(aObj);
   }
 
   static JSBool
-  GetProperty(JSContext* aCx, JSObject* aObj, jsid aIdval, jsval* aVp)
+  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
   {
     JS_ASSERT(JSID_IS_INT(aIdval));
 
     int32 slot = JSID_TO_INT(aIdval);
 
     JS_ASSERT(slot >= SLOT_lengthComputable && slot < SLOT_COUNT);
 
     const char*& name = sProperties[slot - SLOT_FIRST].name;
--- a/dom/workers/Exceptions.cpp
+++ b/dom/workers/Exceptions.cpp
@@ -154,17 +154,17 @@ private:
       return false;
     }
 
     JS_SET_RVAL(aCx, aVp, STRING_TO_JSVAL(out));
     return true;
   }
 
   static JSBool
-  GetProperty(JSContext* aCx, JSObject* aObj, jsid aIdval, jsval* aVp)
+  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
   {
     JS_ASSERT(JSID_IS_INT(aIdval));
 
     int32 slot = JSID_TO_INT(aIdval);
 
     JSClass* classPtr = JS_GetClass(aObj);
 
     if (classPtr != &sClass || !GetJSPrivateSafeish<DOMException>(aObj)) {
@@ -174,17 +174,17 @@ private:
       return false;
     }
 
     *aVp = JS_GetReservedSlot(aObj, slot);
     return true;
   }
 
   static JSBool
-  GetConstant(JSContext* aCx, JSObject* aObj, jsid idval, jsval* aVp)
+  GetConstant(JSContext* aCx, JSHandleObject aObj, JSHandleId idval, jsval* aVp)
   {
     JS_ASSERT(JSID_IS_INT(idval));
     *aVp = INT_TO_JSVAL(JSID_TO_INT(idval));
     return true;
   }
 };
 
 JSClass DOMException::sClass = {
--- a/dom/workers/File.cpp
+++ b/dom/workers/File.cpp
@@ -143,17 +143,17 @@ private:
   {
     JS_ASSERT(JS_GetClass(aObj) == &sClass);
 
     nsIDOMBlob* blob = GetPrivate(aObj);
     NS_IF_RELEASE(blob);
   }
 
   static JSBool
-  GetSize(JSContext* aCx, JSObject* aObj, jsid aIdval, jsval* aVp)
+  GetSize(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
   {
     nsIDOMBlob* blob = GetInstancePrivate(aCx, aObj, "size");
     if (!blob) {
       return false;
     }
 
     PRUint64 size;
     if (NS_FAILED(blob->GetSize(&size))) {
@@ -164,17 +164,17 @@ private:
     if (!JS_NewNumberValue(aCx, double(size), aVp)) {
       return false;
     }
 
     return true;
   }
 
   static JSBool
-  GetType(JSContext* aCx, JSObject* aObj, jsid aIdval, jsval* aVp)
+  GetType(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
   {
     nsIDOMBlob* blob = GetInstancePrivate(aCx, aObj, "type");
     if (!blob) {
       return false;
     }
 
     nsString type;
     if (NS_FAILED(blob->GetType(type))) {
@@ -334,17 +334,17 @@ private:
   {
     JS_ASSERT(JS_GetClass(aObj) == &sClass);
 
     nsIDOMFile* file = GetPrivate(aObj);
     NS_IF_RELEASE(file);
   }
 
   static JSBool
-  GetMozFullPath(JSContext* aCx, JSObject* aObj, jsid aIdval, jsval* aVp)
+  GetMozFullPath(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
   {
     nsIDOMFile* file = GetInstancePrivate(aCx, aObj, "mozFullPath");
     if (!file) {
       return false;
     }
 
     nsString fullPath;
 
@@ -360,17 +360,17 @@ private:
       return false;
     }
 
     *aVp = STRING_TO_JSVAL(jsFullPath);
     return true;
   }
 
   static JSBool
-  GetName(JSContext* aCx, JSObject* aObj, jsid aIdval, jsval* aVp)
+  GetName(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
   {
     nsIDOMFile* file = GetInstancePrivate(aCx, aObj, "name");
     if (!file) {
       return false;
     }
 
     nsString name;
     if (NS_FAILED(file->GetName(name))) {
--- a/dom/workers/ImageData.cpp
+++ b/dom/workers/ImageData.cpp
@@ -109,17 +109,17 @@ private:
   static void
   Finalize(JSFreeOp* aFop, JSObject* aObj)
   {
     MOZ_ASSERT(JS_GetClass(aObj) == &sClass);
     delete static_cast<ImageData*>(JS_GetPrivate(aObj));
   }
 
   static JSBool
-  GetProperty(JSContext* aCx, JSObject* aObj, jsid aIdval, jsval* aVp)
+  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
   {
     JSClass* classPtr = JS_GetClass(aObj);
     if (classPtr != &sClass) {
       JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
                            JSMSG_INCOMPATIBLE_PROTO, sClass.name, "GetProperty",
                            classPtr->name);
       return false;
     }
--- a/dom/workers/Location.cpp
+++ b/dom/workers/Location.cpp
@@ -156,17 +156,17 @@ private:
 
     jsval href = JS_GetReservedSlot(obj, SLOT_href);
 
     JS_SET_RVAL(aCx, aVp, href);
     return true;
   }
 
   static JSBool
-  GetProperty(JSContext* aCx, JSObject* aObj, jsid aIdval, jsval* aVp)
+  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
   {
     JSClass* classPtr = JS_GetClass(aObj);
     if (classPtr != &sClass) {
       JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
                            JSMSG_INCOMPATIBLE_PROTO, sClass.name, "GetProperty",
                            classPtr->name);
       return false;
     }
--- a/dom/workers/Navigator.cpp
+++ b/dom/workers/Navigator.cpp
@@ -145,17 +145,17 @@ private:
   static void
   Finalize(JSFreeOp* aFop, JSObject* aObj)
   {
     JS_ASSERT(JS_GetClass(aObj) == &sClass);
     delete static_cast<Navigator*>(JS_GetPrivate(aObj));
   }
 
   static JSBool
-  GetProperty(JSContext* aCx, JSObject* aObj, jsid aIdval, jsval* aVp)
+  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
   {
     JSClass* classPtr = JS_GetClass(aObj);
     if (classPtr != &sClass) {
       JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
                            JSMSG_INCOMPATIBLE_PROTO, sClass.name, "GetProperty",
                            classPtr->name);
       return false;
     }
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -389,17 +389,17 @@ public:
 };
 
 } /* anonymous namespace */
 
 BEGIN_WORKERS_NAMESPACE
 
 // Entry point for the DOM.
 JSBool
-ResolveWorkerClasses(JSContext* aCx, JSObject* aObj, jsid aId, unsigned aFlags,
+ResolveWorkerClasses(JSContext* aCx, JSHandleObject aObj, JSHandleId aId, unsigned aFlags,
                      JSObject** aObjp)
 {
   AssertIsOnMainThread();
 
   // Don't care about assignments or declarations, bail now.
   if (aFlags & (JSRESOLVE_ASSIGNING | JSRESOLVE_DECLARING)) {
     *aObjp = nsnull;
     return true;
@@ -418,31 +418,31 @@ ResolveWorkerClasses(JSContext* aCx, JSO
       gStringIDs[i] = INTERNED_STRING_TO_JSID(aCx, str);
     }
   }
 
   bool isChrome = false;
   bool shouldResolve = false;
 
   for (PRUint32 i = 0; i < ID_COUNT; i++) {
-    if (aId == gStringIDs[i]) {
+    if (gStringIDs[i] == aId) {
       nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
       NS_ASSERTION(ssm, "This should never be null!");
 
       bool enabled;
       if (NS_FAILED(ssm->IsCapabilityEnabled("UniversalXPConnect", &enabled))) {
         NS_WARNING("IsCapabilityEnabled failed!");
         isChrome = false;
       }
 
       isChrome = !!enabled;
 
       // Don't resolve if this is ChromeWorker and we're not chrome. Otherwise
       // always resolve.
-      shouldResolve = aId == gStringIDs[ID_ChromeWorker] ? isChrome : true;
+      shouldResolve = gStringIDs[ID_ChromeWorker] == aId ? isChrome : true;
       break;
     }
   }
 
   if (shouldResolve) {
     // Don't do anything if workers are disabled.
     if (!isChrome && !Preferences::GetBool(PREF_WORKERS_ENABLED)) {
       *aObjp = nsnull;
--- a/dom/workers/Worker.cpp
+++ b/dom/workers/Worker.cpp
@@ -182,17 +182,17 @@ protected:
 private:
   // No instance of this class should ever be created so these are explicitly
   // left without an implementation to prevent linking in case someone tries to
   // make one.
   Worker();
   ~Worker();
 
   static JSBool
-  GetEventListener(JSContext* aCx, JSObject* aObj, jsid aIdval, jsval* aVp)
+  GetEventListener(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
   {
     JS_ASSERT(JSID_IS_INT(aIdval));
     JS_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < STRING_COUNT);
 
     const char* name = sEventStrings[JSID_TO_INT(aIdval)];
     WorkerPrivate* worker = GetInstancePrivate(aCx, aObj, name);
     if (!worker) {
       return !JS_IsExceptionPending(aCx);
@@ -206,17 +206,17 @@ private:
       JS_ReportError(aCx, "Failed to get listener!");
     }
 
     *aVp = listener ? OBJECT_TO_JSVAL(listener) : JSVAL_NULL;
     return true;
   }
 
   static JSBool
-  SetEventListener(JSContext* aCx, JSObject* aObj, jsid aIdval, JSBool aStrict,
+  SetEventListener(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSBool aStrict,
                    jsval* aVp)
   {
     JS_ASSERT(JSID_IS_INT(aIdval));
     JS_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < STRING_COUNT);
 
     const char* name = sEventStrings[JSID_TO_INT(aIdval)];
     WorkerPrivate* worker = GetInstancePrivate(aCx, aObj, name);
     if (!worker) {
--- a/dom/workers/WorkerScope.cpp
+++ b/dom/workers/WorkerScope.cpp
@@ -162,17 +162,17 @@ protected:
   virtual void
   _Finalize(JSFreeOp* aFop) MOZ_OVERRIDE
   {
     EventTarget::_Finalize(aFop);
   }
 
 private:
   static JSBool
-  _GetEventListener(JSContext* aCx, JSObject* aObj, jsid aIdval, jsval* aVp)
+  _GetEventListener(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
   {
     JS_ASSERT(JSID_IS_INT(aIdval));
     JS_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < STRING_COUNT);
 
     const char* name = sEventStrings[JSID_TO_INT(aIdval)];
     WorkerGlobalScope* scope = GetInstancePrivate(aCx, aObj, name);
     if (!scope) {
       return false;
@@ -188,17 +188,17 @@ private:
       return false;
     }
 
     *aVp = listener ? OBJECT_TO_JSVAL(listener) : JSVAL_NULL;
     return true;
   }
 
   static JSBool
-  _SetEventListener(JSContext* aCx, JSObject* aObj, jsid aIdval, JSBool aStrict,
+  _SetEventListener(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSBool aStrict,
                    jsval* aVp)
   {
     JS_ASSERT(JSID_IS_INT(aIdval));
     JS_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < STRING_COUNT);
 
     const char* name = sEventStrings[JSID_TO_INT(aIdval)];
     WorkerGlobalScope* scope = GetInstancePrivate(aCx, aObj, name);
     if (!scope) {
@@ -228,28 +228,28 @@ private:
   Construct(JSContext* aCx, unsigned aArgc, jsval* aVp)
   {
     JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL, JSMSG_WRONG_CONSTRUCTOR,
                          sClass.name);
     return false;
   }
 
   static JSBool
-  GetSelf(JSContext* aCx, JSObject* aObj, jsid aIdval, jsval* aVp)
+  GetSelf(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
   {
     if (!GetInstancePrivate(aCx, aObj, "self")) {
       return false;
     }
 
     *aVp = OBJECT_TO_JSVAL(aObj);
     return true;
   }
 
   static JSBool
-  GetLocation(JSContext* aCx, JSObject* aObj, jsid aIdval, jsval* aVp)
+  GetLocation(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
   {
     WorkerGlobalScope* scope =
       GetInstancePrivate(aCx, aObj, sProperties[SLOT_location].name);
     if (!scope) {
       return false;
     }
 
     if (JSVAL_IS_VOID(scope->mSlots[SLOT_location])) {
@@ -328,17 +328,17 @@ private:
         !JS_CallFunctionName(aCx, event, "preventDefault", 0, NULL, &rval)) {
       return false;
     }
 
     return true;
   }
 
   static JSBool
-  GetOnErrorListener(JSContext* aCx, JSObject* aObj, jsid aIdval, jsval* aVp)
+  GetOnErrorListener(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
   {
     const char* name = sEventStrings[STRING_onerror];
     WorkerGlobalScope* scope = GetInstancePrivate(aCx, aObj, name);
     if (!scope) {
       return false;
     }
 
     ErrorResult rv;
@@ -359,17 +359,17 @@ private:
     *aVp = js::GetFunctionNativeReserved(adaptor, SLOT_wrappedFunction);
 
     JS_ASSERT(!JSVAL_IS_PRIMITIVE(*aVp));
 
     return true;
   }
 
   static JSBool
-  SetOnErrorListener(JSContext* aCx, JSObject* aObj, jsid aIdval,
+  SetOnErrorListener(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval,
                      JSBool aStrict, jsval* aVp)
   {
     const char* name = sEventStrings[STRING_onerror];
     WorkerGlobalScope* scope = GetInstancePrivate(aCx, aObj, name);
     if (!scope) {
       return false;
     }
 
@@ -402,17 +402,17 @@ private:
       JS_ReportError(aCx, "Failed to set event listener!");
       return false;
     }
 
     return true;
   }
 
   static JSBool
-  GetNavigator(JSContext* aCx, JSObject* aObj, jsid aIdval, jsval* aVp)
+  GetNavigator(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
   {
     WorkerGlobalScope* scope =
       GetInstancePrivate(aCx, aObj, sProperties[SLOT_navigator].name);
     if (!scope) {
       return false;
     }
 
     if (JSVAL_IS_VOID(scope->mSlots[SLOT_navigator])) {
@@ -729,17 +729,17 @@ protected:
 
   ~DedicatedWorkerGlobalScope()
   {
     MOZ_COUNT_DTOR(mozilla::dom::workers::DedicatedWorkerGlobalScope);
   }
 
 private:
   static JSBool
-  _GetEventListener(JSContext* aCx, JSObject* aObj, jsid aIdval, jsval* aVp)
+  _GetEventListener(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, jsval* aVp)
   {
     JS_ASSERT(JSID_IS_INT(aIdval));
     JS_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < STRING_COUNT);
 
     const char* name = sEventStrings[JSID_TO_INT(aIdval)];
     DedicatedWorkerGlobalScope* scope = GetInstancePrivate(aCx, aObj, name);
     if (!scope) {
       return false;
@@ -755,17 +755,17 @@ private:
       return false;
     }
 
     *aVp = listener ? OBJECT_TO_JSVAL(listener) : JSVAL_NULL;
     return true;
   }
 
   static JSBool
-  _SetEventListener(JSContext* aCx, JSObject* aObj, jsid aIdval, JSBool aStrict,
+  _SetEventListener(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSBool aStrict,
                     jsval* aVp)
   {
     JS_ASSERT(JSID_IS_INT(aIdval));
     JS_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < STRING_COUNT);
 
     const char* name = sEventStrings[JSID_TO_INT(aIdval)];
     DedicatedWorkerGlobalScope* scope = GetInstancePrivate(aCx, aObj, name);
     if (!scope) {
@@ -808,25 +808,25 @@ private:
   Construct(JSContext* aCx, unsigned aArgc, jsval* aVp)
   {
     JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL, JSMSG_WRONG_CONSTRUCTOR,
                          Class()->name);
     return false;
   }
 
   static JSBool
-  Resolve(JSContext* aCx, JSObject* aObj, jsid aId, unsigned aFlags,
+  Resolve(JSContext* aCx, JSHandleObject aObj, JSHandleId aId, unsigned aFlags,
           JSObject** aObjp)
   {
     JSBool resolved;
     if (!JS_ResolveStandardClass(aCx, aObj, aId, &resolved)) {
       return false;
     }
 
-    *aObjp = resolved ? aObj : NULL;
+    *aObjp = resolved ? aObj.value() : NULL;
     return true;
   }
 
   static void
   Finalize(JSFreeOp* aFop, JSObject* aObj)
   {
     JS_ASSERT(JS_GetClass(aObj) == Class());
     DedicatedWorkerGlobalScope* scope =
--- a/dom/workers/Workers.h
+++ b/dom/workers/Workers.h
@@ -39,17 +39,17 @@ AssertIsOnMainThread();
 #else
 inline void
 AssertIsOnMainThread()
 { }
 #endif
 
 // All of these are implemented in RuntimeService.cpp
 JSBool
-ResolveWorkerClasses(JSContext* aCx, JSObject* aObj, jsid aId, unsigned aFlags,
+ResolveWorkerClasses(JSContext* aCx, JSHandleObject aObj, JSHandleId aId, unsigned aFlags,
                      JSObject** aObjp);
 
 void
 CancelWorkersForWindow(JSContext* aCx, nsPIDOMWindow* aWindow);
 
 void
 SuspendWorkersForWindow(JSContext* aCx, nsPIDOMWindow* aWindow);
 
--- a/gfx/skia/src/xml/SkJS.cpp
+++ b/gfx/skia/src/xml/SkJS.cpp
@@ -69,27 +69,27 @@ extern "C" {
         SkASSERT(0);
         return 0;
     }
 
 }
 #endif
 
 static JSBool
-global_enumerate(JSContext *cx, JSObject *obj)
+global_enumerate(JSContext *cx, JSHandleObject obj)
 {
 #ifdef LAZY_STANDARD_CLASSES
     return JS_EnumerateStandardClasses(cx, obj);
 #else
     return JS_TRUE;
 #endif
 }
 
 static JSBool
-global_resolve(JSContext *cx, JSObject *obj, jsval id, unsigned flags, JSObject **objp)
+global_resolve(JSContext *cx, JSHandleObject obj, JSHandleId id, unsigned flags, JSObject **objp)
 {
 #ifdef LAZY_STANDARD_CLASSES
     if ((flags & JSRESOLVE_ASSIGNING) == 0) {
         JSBool resolved;
 
         if (!JS_ResolveStandardClass(cx, obj, id, &resolved))
             return JS_FALSE;
         if (resolved) {
--- a/js/ipc/ObjectWrapperParent.cpp
+++ b/js/ipc/ObjectWrapperParent.cpp
@@ -381,17 +381,17 @@ jsval_to_nsString(JSContext* cx, jsid fr
         (chars = JS_GetStringCharsZ(cx, str))) {
         *to = chars;
         return true;
     }
     return false;
 }
 
 /*static*/ JSBool
-ObjectWrapperParent::CPOW_AddProperty(JSContext *cx, JSObject *obj, jsid id,
+ObjectWrapperParent::CPOW_AddProperty(JSContext *cx, JSHandleObject obj, JSHandleId id,
                                       jsval *vp)
 {
     CPOW_LOG(("Calling CPOW_AddProperty (%s)...",
               JSVAL_TO_CSTR(cx, id)));
 
     ObjectWrapperParent* self = Unwrap(obj);
     if (!self)
         return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_AddProperty");
@@ -408,17 +408,17 @@ ObjectWrapperParent::CPOW_AddProperty(JS
 
     return (self->Manager()->RequestRunToCompletion() &&
             self->CallAddProperty(in_id,
                                   aco.StatusPtr()) &&
             aco.Ok());
 }
 
 /*static*/ JSBool
-ObjectWrapperParent::CPOW_GetProperty(JSContext *cx, JSObject *obj, jsid id,
+ObjectWrapperParent::CPOW_GetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id,
                                       jsval *vp)
 {
     CPOW_LOG(("Calling CPOW_GetProperty (%s)...",
               JSVAL_TO_CSTR(cx, id)));
 
     ObjectWrapperParent* self = Unwrap(obj);
     if (!self)
         return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_GetProperty");
@@ -435,17 +435,17 @@ ObjectWrapperParent::CPOW_GetProperty(JS
     return (self->Manager()->RequestRunToCompletion() &&
             self->CallGetProperty(in_id,
                                   aco.StatusPtr(), &out_v) &&
             aco.Ok() &&
             self->jsval_from_JSVariant(cx, out_v, vp));
 }
 
 /*static*/ JSBool
-ObjectWrapperParent::CPOW_SetProperty(JSContext *cx, JSObject *obj, jsid id, 
+ObjectWrapperParent::CPOW_SetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, 
                                       JSBool strict, jsval *vp)
 {
     CPOW_LOG(("Calling CPOW_SetProperty (%s)...",
               JSVAL_TO_CSTR(cx, id)));
 
     ObjectWrapperParent* self = Unwrap(obj);
     if (!self)
         return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_SetProperty");
@@ -464,17 +464,17 @@ ObjectWrapperParent::CPOW_SetProperty(JS
     return (self->Manager()->RequestRunToCompletion() &&
             self->CallSetProperty(in_id, in_v,
                                   aco.StatusPtr(), &out_v) &&
             aco.Ok() &&
             self->jsval_from_JSVariant(cx, out_v, vp));
 }    
     
 /*static*/ JSBool
-ObjectWrapperParent::CPOW_DelProperty(JSContext *cx, JSObject *obj, jsid id,
+ObjectWrapperParent::CPOW_DelProperty(JSContext *cx, JSHandleObject obj, JSHandleId id,
                                       jsval *vp)
 {
     CPOW_LOG(("Calling CPOW_DelProperty (%s)...",
               JSVAL_TO_CSTR(cx, id)));
 
     ObjectWrapperParent* self = Unwrap(obj);
     if (!self)
         return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_DelProperty");
@@ -545,17 +545,17 @@ ObjectWrapperParent::NewEnumerateDestroy
 
     if (!jsval_to_JSVariant(cx, state, &in_state))
         return JS_FALSE;
 
     return SendNewEnumerateDestroy(in_state);
 }
 
 /*static*/ JSBool
-ObjectWrapperParent::CPOW_NewEnumerate(JSContext *cx, JSObject *obj,
+ObjectWrapperParent::CPOW_NewEnumerate(JSContext *cx, JSHandleObject obj,
                                        JSIterateOp enum_op, jsval *statep,
                                        jsid *idp)
 {
     CPOW_LOG(("Calling CPOW_NewEnumerate..."));
 
     ObjectWrapperParent* self = Unwrap(obj);
     if (!self)
         return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_NewEnumerate");
@@ -571,17 +571,17 @@ ObjectWrapperParent::CPOW_NewEnumerate(J
         return self->NewEnumerateDestroy(cx, *statep);
     }
 
     NS_NOTREACHED("Unknown enum_op value in CPOW_NewEnumerate");
     return JS_FALSE;
 }
 
 /*static*/ JSBool
-ObjectWrapperParent::CPOW_NewResolve(JSContext *cx, JSObject *obj, jsid id,
+ObjectWrapperParent::CPOW_NewResolve(JSContext *cx, JSHandleObject obj, JSHandleId id,
                                      unsigned flags, JSObject **objp)
 {
     CPOW_LOG(("Calling CPOW_NewResolve (%s)...",
               JSVAL_TO_CSTR(cx, id)));
 
     ObjectWrapperParent* self = Unwrap(obj);
     if (!self)
         return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_NewResolve");
@@ -606,17 +606,17 @@ ObjectWrapperParent::CPOW_NewResolve(JSC
         AutoResolveFlag arf(*objp);
         JS_DefinePropertyById(cx, *objp, id, JSVAL_VOID, NULL, NULL,
                               JSPROP_ENUMERATE);
     }
     return JS_TRUE;
 }
 
 /*static*/ JSBool
-ObjectWrapperParent::CPOW_Convert(JSContext *cx, JSObject *obj, JSType type,
+ObjectWrapperParent::CPOW_Convert(JSContext *cx, JSHandleObject obj, JSType type,
                                   jsval *vp)
 {
     CPOW_LOG(("Calling CPOW_Convert (to %s)...",
               JS_GetTypeName(cx, type)));
 
     ObjectWrapperParent* self = Unwrap(obj);
     if (!self)
         return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_Convert");
@@ -699,17 +699,17 @@ ObjectWrapperParent::CPOW_Construct(JSCo
 
     return (constructor->Manager()->RequestRunToCompletion() &&
             constructor->CallConstruct(in_argv, aco.StatusPtr(), &out_powp) &&
             aco.Ok() &&
             jsval_from_PObjectWrapperParent(cx, out_powp, vp));
 }
 
 /*static*/ JSBool
-ObjectWrapperParent::CPOW_HasInstance(JSContext *cx, JSObject *obj, const jsval *v,
+ObjectWrapperParent::CPOW_HasInstance(JSContext *cx, JSHandleObject obj, const jsval *v,
                                       JSBool *bp)
 {
     CPOW_LOG(("Calling CPOW_HasInstance..."));
 
     *bp = JS_FALSE;
 
     ObjectWrapperParent* self = Unwrap(obj);
     if (!self)
@@ -724,17 +724,17 @@ ObjectWrapperParent::CPOW_HasInstance(JS
 
     return (self->Manager()->RequestRunToCompletion() &&
             self->CallHasInstance(in_v,
                                   aco.StatusPtr(), bp) &&
             aco.Ok());
 }
 
 /*static*/ JSBool
-ObjectWrapperParent::CPOW_Equality(JSContext *cx, JSObject *obj, const jsval *v,
+ObjectWrapperParent::CPOW_Equality(JSContext *cx, JSHandleObject obj, const jsval *v,
                                    JSBool *bp)
 {
     CPOW_LOG(("Calling CPOW_Equality..."));
 
     *bp = JS_FALSE;
     
     ObjectWrapperParent* self = Unwrap(obj);
     if (!self)
--- a/js/ipc/ObjectWrapperParent.h
+++ b/js/ipc/ObjectWrapperParent.h
@@ -88,55 +88,55 @@ protected:
 
     ContextWrapperParent* Manager();
 
 private:
 
     mutable JSObject* mObj;
 
     static JSBool
-    CPOW_AddProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
+    CPOW_AddProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, jsval *vp);
 
     static JSBool
-    CPOW_DelProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
+    CPOW_DelProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, jsval *vp);
 
     static JSBool
-    CPOW_GetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
+    CPOW_GetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, jsval *vp);
     
     static JSBool
-    CPOW_SetProperty(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp);
+    CPOW_SetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, jsval *vp);
 
     JSBool NewEnumerateInit(JSContext* cx, jsval* statep, jsid* idp);
     JSBool NewEnumerateNext(JSContext* cx, jsval* statep, jsid* idp);
     JSBool NewEnumerateDestroy(JSContext* cx, jsval state);
     static JSBool
-    CPOW_NewEnumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
+    CPOW_NewEnumerate(JSContext *cx, JSHandleObject obj, JSIterateOp enum_op,
                       jsval *statep, jsid *idp);
 
     static JSBool
-    CPOW_NewResolve(JSContext *cx, JSObject *obj, jsid id, unsigned flags,
+    CPOW_NewResolve(JSContext *cx, JSHandleObject obj, JSHandleId id, unsigned flags,
                     JSObject **objp);
 
     static JSBool
-    CPOW_Convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp);
+    CPOW_Convert(JSContext *cx, JSHandleObject obj, JSType type, jsval *vp);
 
     static void
     CPOW_Finalize(js::FreeOp* fop, JSObject* obj);
 
     static JSBool
     CPOW_Call(JSContext* cx, unsigned argc, jsval* vp);
 
     static JSBool
     CPOW_Construct(JSContext *cx, unsigned argc, jsval *vp);
     
     static JSBool
-    CPOW_HasInstance(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp);
+    CPOW_HasInstance(JSContext *cx, JSHandleObject obj, const jsval *v, JSBool *bp);
 
     static JSBool
-    CPOW_Equality(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp);
+    CPOW_Equality(JSContext *cx, JSHandleObject obj, const jsval *v, JSBool *bp);
 
     static bool jsval_to_JSVariant(JSContext* cx, jsval from, JSVariant* to);
     static bool jsval_from_JSVariant(JSContext* cx, const JSVariant& from,
                                      jsval* to);
     static bool
     JSObject_to_PObjectWrapperParent(JSObject* from, PObjectWrapperParent** to);
     static bool
     JSObject_from_PObjectWrapperParent(JSContext* cx,
--- a/js/src/builtin/RegExp.cpp
+++ b/js/src/builtin/RegExp.cpp
@@ -52,27 +52,27 @@ using namespace js;
 using namespace js::types;
 
 class RegExpMatchBuilder
 {
     JSContext   * const cx;
     RootedVarObject array;
 
     bool setProperty(JSAtom *name, Value v) {
-        return !!js_DefineProperty(cx, array, AtomToId(name), &v,
-                                   JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE);
+        return !!baseops::DefineProperty(cx, array, RootedVarId(cx, AtomToId(name)), &v,
+                                         JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE);
     }
 
   public:
     RegExpMatchBuilder(JSContext *cx, JSObject *array) : cx(cx), array(cx, array) {}
 
     bool append(uint32_t index, Value v) {
         JS_ASSERT(!array->getOps()->getElement);
-        return !!js_DefineElement(cx, array, index, &v, JS_PropertyStub, JS_StrictPropertyStub,
-                                  JSPROP_ENUMERATE);
+        return !!baseops::DefineElement(cx, array, index, &v, JS_PropertyStub, JS_StrictPropertyStub,
+                                        JSPROP_ENUMERATE);
     }
 
     bool setIndex(int index) {
         return setProperty(cx->runtime->atomState.indexAtom, Int32Value(index));
     }
 
     bool setInput(JSString *str) {
         JS_ASSERT(str);
@@ -400,17 +400,17 @@ static JSFunctionSpec regexp_methods[] =
  *  RegExp.lastMatch            $&
  *  RegExp.lastParen            $+
  *  RegExp.leftContext          $`
  *  RegExp.rightContext         $'
  */
 
 #define DEFINE_STATIC_GETTER(name, code)                                        \
     static JSBool                                                               \
-    name(JSContext *cx, JSObject *obj, jsid id, jsval *vp)                      \
+    name(JSContext *cx, HandleObject obj, HandleId id, jsval *vp)               \
     {                                                                           \
         RegExpStatics *res = cx->regExpStatics();                               \
         code;                                                                   \
     }
 
 DEFINE_STATIC_GETTER(static_input_getter,        return res->createPendingInput(cx, vp))
 DEFINE_STATIC_GETTER(static_multiline_getter,    *vp = BOOLEAN_TO_JSVAL(res->multiline());
                                                  return true)
@@ -426,17 +426,17 @@ DEFINE_STATIC_GETTER(static_paren4_gette
 DEFINE_STATIC_GETTER(static_paren5_getter,       return res->createParen(cx, 5, vp))
 DEFINE_STATIC_GETTER(static_paren6_getter,       return res->createParen(cx, 6, vp))
 DEFINE_STATIC_GETTER(static_paren7_getter,       return res->createParen(cx, 7, vp))
 DEFINE_STATIC_GETTER(static_paren8_getter,       return res->createParen(cx, 8, vp))
 DEFINE_STATIC_GETTER(static_paren9_getter,       return res->createParen(cx, 9, vp))
 
 #define DEFINE_STATIC_SETTER(name, code)                                        \
     static JSBool                                                               \
-    name(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp)       \
+    name(JSContext *cx, HandleObject obj, HandleId id, JSBool strict, jsval *vp)\
     {                                                                           \
         RegExpStatics *res = cx->regExpStatics();                               \
         code;                                                                   \
         return true;                                                            \
     }
 
 DEFINE_STATIC_SETTER(static_input_setter,
                      if (!JSVAL_IS_STRING(*vp) && !JS_ConvertValue(cx, *vp, JSTYPE_STRING, vp))
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -82,27 +82,27 @@ static JSBool ConstructAbstract(JSContex
 namespace CType {
   static JSBool ConstructData(JSContext* cx, unsigned argc, jsval* vp);
   static JSBool ConstructBasic(JSContext* cx, JSObject* 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, JSObject* obj, jsid idval,
+  static JSBool PrototypeGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
     jsval* vp);
-  static JSBool NameGetter(JSContext* cx, JSObject* obj, jsid idval,
+  static JSBool NameGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
     jsval* vp);
-  static JSBool SizeGetter(JSContext* cx, JSObject* obj, jsid idval,
+  static JSBool SizeGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
     jsval* vp);
-  static JSBool PtrGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp);
+  static JSBool PtrGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, jsval* vp);
   static JSBool CreateArray(JSContext* cx, unsigned argc, jsval* vp);
   static JSBool ToString(JSContext* cx, unsigned argc, jsval* vp);
   static JSBool ToSource(JSContext* cx, unsigned argc, jsval* vp);
-  static JSBool HasInstance(JSContext* cx, JSObject* obj, const jsval* v, JSBool* bp);
+  static JSBool HasInstance(JSContext* cx, JSHandleObject obj, const jsval* v, JSBool* bp);
 
 
   /*
    * Get the global "ctypes" object.
    *
    * |obj| must be a CType object.
    *
    * This function never returns NULL.
@@ -115,99 +115,99 @@ 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 TargetTypeGetter(JSContext* cx, JSObject* obj, jsid idval,
+  static JSBool TargetTypeGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
     jsval* vp);
-  static JSBool ContentsGetter(JSContext* cx, JSObject* obj, jsid idval,
+  static JSBool ContentsGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
     jsval* vp);
-  static JSBool ContentsSetter(JSContext* cx, JSObject* obj, jsid idval, JSBool strict,
+  static JSBool ContentsSetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, JSBool strict,
     jsval* vp);
   static JSBool IsNull(JSContext* cx, unsigned argc, jsval* vp);
   static JSBool Increment(JSContext* cx, unsigned argc, jsval* vp);
   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 ElementTypeGetter(JSContext* cx, JSObject* obj, jsid idval,
+  static JSBool ElementTypeGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
     jsval* vp);
-  static JSBool LengthGetter(JSContext* cx, JSObject* obj, jsid idval,
+  static JSBool LengthGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
     jsval* vp);
-  static JSBool Getter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp);
-  static JSBool Setter(JSContext* cx, JSObject* obj, jsid idval, JSBool strict, 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 FieldsArrayGetter(JSContext* cx, JSObject* obj, jsid idval,
+  static JSBool FieldsArrayGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
     jsval* vp);
-  static JSBool FieldGetter(JSContext* cx, JSObject* obj, jsid idval,
+  static JSBool FieldGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
     jsval* vp);
-  static JSBool FieldSetter(JSContext* cx, JSObject* obj, jsid idval, JSBool strict,
+  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 Call(JSContext* cx, unsigned argc, jsval* vp);
 
-  static JSBool ArgTypesGetter(JSContext* cx, JSObject* obj, jsid idval,
+  static JSBool ArgTypesGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
     jsval* vp);
-  static JSBool ReturnTypeGetter(JSContext* cx, JSObject* obj, jsid idval,
+  static JSBool ReturnTypeGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
     jsval* vp);
-  static JSBool ABIGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp);
-  static JSBool IsVariadicGetter(JSContext* cx, JSObject* obj, jsid idval,
+  static JSBool ABIGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, jsval* vp);
+  static JSBool IsVariadicGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
     jsval* vp);
 }
 
 namespace CClosure {
   static void Trace(JSTracer* trc, JSObject* obj);
   static void Finalize(JSFreeOp *fop, JSObject* obj);
 
   // libffi callback
   static void ClosureStub(ffi_cif* cif, void* result, void** args,
     void* userData);
 }
 
 namespace CData {
   static void Finalize(JSFreeOp *fop, JSObject* obj);
 
-  static JSBool ValueGetter(JSContext* cx, JSObject* obj, jsid idval,
+  static JSBool ValueGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
                             jsval* vp);
-  static JSBool ValueSetter(JSContext* cx, JSObject* obj, jsid idval,
+  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,
                                    void *data);
-  static JSBool ErrnoGetter(JSContext* cx, JSObject *obj, jsid idval,
+  static JSBool ErrnoGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
                             jsval* vp);
 
 #if defined(XP_WIN)
-  static JSBool LastErrorGetter(JSContext* cx, JSObject *obj, jsid idval,
+  static JSBool LastErrorGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
                                 jsval* vp);
 #endif // defined(XP_WIN)
 }
 
 namespace CDataFinalizer {
   /*
    * Attach a C function as a finalizer to a JS object.
    *
@@ -3373,61 +3373,61 @@ CType::GetProtoFromType(JSObject* obj, C
   JS_ASSERT(CType::IsCTypeProto(proto));
 
   // Get the requested ctypes.{Pointer,Array,Struct,Function}Type.prototype.
   jsval result = JS_GetReservedSlot(proto, slot);
   return JSVAL_TO_OBJECT(result);
 }
 
 JSBool
-CType::PrototypeGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
+CType::PrototypeGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, jsval* vp)
 {
   if (!(CType::IsCType(obj) || CType::IsCTypeProto(obj))) {
     JS_ReportError(cx, "not a CType or CTypeProto");
     return JS_FALSE;
   }
 
   unsigned slot = CType::IsCTypeProto(obj) ? (unsigned) SLOT_OURDATAPROTO
                                            : (unsigned) SLOT_PROTO;
   *vp = JS_GetReservedSlot(obj, slot);
   JS_ASSERT(!JSVAL_IS_PRIMITIVE(*vp) || JSVAL_IS_VOID(*vp));
   return JS_TRUE;
 }
 
 JSBool
-CType::NameGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
+CType::NameGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, jsval* vp)
 {
   if (!CType::IsCType(obj)) {
     JS_ReportError(cx, "not a CType");
     return JS_FALSE;
   }
 
   JSString* name = CType::GetName(cx, obj);
   if (!name)
     return JS_FALSE;
 
   *vp = STRING_TO_JSVAL(name);
   return JS_TRUE;
 }
 
 JSBool
-CType::SizeGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
+CType::SizeGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, jsval* vp)
 {
   if (!CType::IsCType(obj)) {
     JS_ReportError(cx, "not a CType");
     return JS_FALSE;
   }
 
   *vp = JS_GetReservedSlot(obj, SLOT_SIZE);
   JS_ASSERT(JSVAL_IS_NUMBER(*vp) || JSVAL_IS_VOID(*vp));
   return JS_TRUE;
 }
 
 JSBool
-CType::PtrGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
+CType::PtrGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, jsval* vp)
 {
   if (!CType::IsCType(obj)) {
     JS_ReportError(cx, "not a CType");
     return JS_FALSE;
   }
 
   JSObject* pointerType = PointerType::CreateInternal(cx, obj);
   if (!pointerType)
@@ -3525,17 +3525,17 @@ CType::ToSource(JSContext* cx, unsigned 
   if (!result)
     return JS_FALSE;
 
   JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(result));
   return JS_TRUE;
 }
 
 JSBool
-CType::HasInstance(JSContext* cx, JSObject* obj, const jsval* v, JSBool* bp)
+CType::HasInstance(JSContext* cx, JSHandleObject obj, const jsval* v, JSBool* bp)
 {
   JS_ASSERT(CType::IsCType(obj));
 
   jsval slot = JS_GetReservedSlot(obj, SLOT_PROTO);
   JSObject* prototype = JSVAL_TO_OBJECT(slot);
   JS_ASSERT(prototype);
   JS_ASSERT(CData::IsCDataProto(prototype));
 
@@ -3769,18 +3769,18 @@ PointerType::GetBaseType(JSObject* obj)
 
   jsval type = JS_GetReservedSlot(obj, SLOT_TARGET_T);
   JS_ASSERT(!JSVAL_IS_NULL(type));
   return JSVAL_TO_OBJECT(type);
 }
 
 JSBool
 PointerType::TargetTypeGetter(JSContext* cx,
-                              JSObject* obj,
-                              jsid idval,
+                              JSHandleObject obj,
+                              JSHandleId idval,
                               jsval* vp)
 {
   if (!CType::IsCType(obj) || CType::GetTypeCode(obj) != TYPE_pointer) {
     JS_ReportError(cx, "not a PointerType");
     return JS_FALSE;
   }
 
   *vp = JS_GetReservedSlot(obj, SLOT_TARGET_T);
@@ -3857,18 +3857,18 @@ PointerType::Increment(JSContext* cx, un
 JSBool
 PointerType::Decrement(JSContext* cx, unsigned argc, jsval* vp)
 {
   return OffsetBy(cx, -1, vp);
 }
 
 JSBool
 PointerType::ContentsGetter(JSContext* cx,
-                            JSObject* obj,
-                            jsid idval,
+                            JSHandleObject obj,
+                            JSHandleId idval,
                             jsval* vp)
 {
   if (!CData::IsCData(obj)) {
     JS_ReportError(cx, "not a CData");
     return JS_FALSE;
   }
 
   // Get pointer type and base type.
@@ -3895,18 +3895,18 @@ PointerType::ContentsGetter(JSContext* c
     return JS_FALSE;
 
   JS_SET_RVAL(cx, vp, result);
   return JS_TRUE;
 }
 
 JSBool
 PointerType::ContentsSetter(JSContext* cx,
-                            JSObject* obj,
-                            jsid idval,
+                            JSHandleObject obj,
+                            JSHandleId idval,
                             JSBool strict,
                             jsval* vp)
 {
   if (!CData::IsCData(obj)) {
     JS_ReportError(cx, "not a CData");
     return JS_FALSE;
   }
 
@@ -4214,48 +4214,50 @@ ArrayType::BuildFFIType(JSContext* cx, J
   for (size_t i = 0; i < length; ++i)
     ffiType->elements[i] = ffiBaseType;
   ffiType->elements[length] = NULL;
 
   return ffiType.forget();
 }
 
 JSBool
-ArrayType::ElementTypeGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
+ArrayType::ElementTypeGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, jsval* vp)
 {
   if (!CType::IsCType(obj) || CType::GetTypeCode(obj) != TYPE_array) {
     JS_ReportError(cx, "not an ArrayType");
     return JS_FALSE;
   }
 
   *vp = JS_GetReservedSlot(obj, SLOT_ELEMENT_T);
   JS_ASSERT(!JSVAL_IS_PRIMITIVE(*vp));
   return JS_TRUE;
 }
 
 JSBool
-ArrayType::LengthGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
-{
+ArrayType::LengthGetter(JSContext* cx, JSHandleObject obj_, JSHandleId idval, jsval* vp)
+{
+  JSObject *obj = obj_;
+
   // This getter exists for both CTypes and CDatas of the ArrayType persuasion.
   // If we're dealing with a CData, get the CType from it.
   if (CData::IsCData(obj))
     obj = CData::GetCType(obj);
 
   if (!CType::IsCType(obj) || CType::GetTypeCode(obj) != TYPE_array) {
     JS_ReportError(cx, "not an ArrayType");
     return JS_FALSE;
   }
 
   *vp = JS_GetReservedSlot(obj, SLOT_LENGTH);
   JS_ASSERT(JSVAL_IS_NUMBER(*vp) || JSVAL_IS_VOID(*vp));
   return JS_TRUE;
 }
 
 JSBool
-ArrayType::Getter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
+ArrayType::Getter(JSContext* cx, JSHandleObject obj, JSHandleId idval, jsval* vp)
 {
   // This should never happen, but we'll check to be safe.
   if (!CData::IsCData(obj)) {
     JS_ReportError(cx, "not a CData");
     return JS_FALSE;
   }
 
   // Bail early if we're not an ArrayType. (This setter is present for all
@@ -4281,17 +4283,17 @@ ArrayType::Getter(JSContext* cx, JSObjec
 
   JSObject* baseType = GetBaseType(typeObj);
   size_t elementSize = CType::GetSize(baseType);
   char* data = static_cast<char*>(CData::GetData(obj)) + elementSize * index;
   return ConvertToJS(cx, baseType, obj, data, false, false, vp);
 }
 
 JSBool
-ArrayType::Setter(JSContext* cx, JSObject* obj, jsid idval, JSBool strict, jsval* vp)
+ArrayType::Setter(JSContext* cx, JSHandleObject obj, JSHandleId idval, JSBool strict, jsval* vp)
 {
   // This should never happen, but we'll check to be safe.
   if (!CData::IsCData(obj)) {
     JS_ReportError(cx, "not a CData");
     return JS_FALSE;
   }
 
   // Bail early if we're not an ArrayType. (This setter is present for all
@@ -4869,17 +4871,17 @@ StructType::BuildFieldsArray(JSContext* 
   // Seal the fields array.
   if (!JS_FreezeObject(cx, fieldsProp))
     return NULL;
 
   return fieldsProp;
 }
 
 JSBool
-StructType::FieldsArrayGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
+StructType::FieldsArrayGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, jsval* vp)
 {
   if (!CType::IsCType(obj) || CType::GetTypeCode(obj) != TYPE_struct) {
     JS_ReportError(cx, "not a StructType");
     return JS_FALSE;
   }
 
   *vp = JS_GetReservedSlot(obj, SLOT_FIELDS);
 
@@ -4899,17 +4901,17 @@ StructType::FieldsArrayGetter(JSContext*
   }
 
   JS_ASSERT(!JSVAL_IS_PRIMITIVE(*vp) &&
             JS_IsArrayObject(cx, JSVAL_TO_OBJECT(*vp)));
   return JS_TRUE;
 }
 
 JSBool
-StructType::FieldGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
+StructType::FieldGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, jsval* vp)
 {
   if (!CData::IsCData(obj)) {
     JS_ReportError(cx, "not a CData");
     return JS_FALSE;
   }
 
   JSObject* typeObj = CData::GetCType(obj);
   if (CType::GetTypeCode(typeObj) != TYPE_struct) {
@@ -4921,17 +4923,17 @@ StructType::FieldGetter(JSContext* cx, J
   if (!field)
     return JS_FALSE;
 
   char* data = static_cast<char*>(CData::GetData(obj)) + field->mOffset;
   return ConvertToJS(cx, field->mType, obj, data, false, false, vp);
 }
 
 JSBool
-StructType::FieldSetter(JSContext* cx, JSObject* obj, jsid idval, JSBool strict, jsval* vp)
+StructType::FieldSetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, JSBool strict, jsval* vp)
 {
   if (!CData::IsCData(obj)) {
     JS_ReportError(cx, "not a CData");
     return JS_FALSE;
   }
 
   JSObject* typeObj = CData::GetCType(obj);
   if (CType::GetTypeCode(typeObj) != TYPE_struct) {
@@ -5637,17 +5639,17 @@ CheckFunctionType(JSContext* cx, JSObjec
   if (!CType::IsCType(obj) || CType::GetTypeCode(obj) != TYPE_function) {
     JS_ReportError(cx, "not a FunctionType");
     return JS_FALSE;
   }
   return JS_TRUE;
 }
 
 JSBool
-FunctionType::ArgTypesGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
+FunctionType::ArgTypesGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, jsval* vp)
 {
   if (!CheckFunctionType(cx, obj))
     return JS_FALSE;
 
   // Check if we have a cached argTypes array.
   *vp = JS_GetReservedSlot(obj, SLOT_ARGS_T);
   if (!JSVAL_IS_VOID(*vp))
     return JS_TRUE;
@@ -5672,39 +5674,39 @@ FunctionType::ArgTypesGetter(JSContext* 
     return JS_FALSE;
   JS_SetReservedSlot(obj, SLOT_ARGS_T, OBJECT_TO_JSVAL(argTypes));
 
   *vp = OBJECT_TO_JSVAL(argTypes);
   return JS_TRUE;
 }
 
 JSBool
-FunctionType::ReturnTypeGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
+FunctionType::ReturnTypeGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, jsval* vp)
 {
   if (!CheckFunctionType(cx, obj))
     return JS_FALSE;
 
   // Get the returnType object from the FunctionInfo.
   *vp = OBJECT_TO_JSVAL(GetFunctionInfo(obj)->mReturnType);
   return JS_TRUE;
 }
 
 JSBool
-FunctionType::ABIGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
+FunctionType::ABIGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, jsval* vp)
 {
   if (!CheckFunctionType(cx, obj))
     return JS_FALSE;
 
   // Get the abi object from the FunctionInfo.
   *vp = OBJECT_TO_JSVAL(GetFunctionInfo(obj)->mABI);
   return JS_TRUE;
 }
 
 JSBool
-FunctionType::IsVariadicGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
+FunctionType::IsVariadicGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, jsval* vp)
 {
   if (!CheckFunctionType(cx, obj))
     return JS_FALSE;
 
   *vp = BOOLEAN_TO_JSVAL(GetFunctionInfo(obj)->mIsVariadic);
   return JS_TRUE;
 }
 
@@ -6140,32 +6142,32 @@ CData::IsCData(JSObject* obj)
 
 bool
 CData::IsCDataProto(JSObject* obj)
 {
   return JS_GetClass(obj) == &sCDataProtoClass;
 }
 
 JSBool
-CData::ValueGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp)
+CData::ValueGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, jsval* vp)
 {
   if (!IsCData(obj)) {
     JS_ReportError(cx, "not a CData");
     return JS_FALSE;
   }
 
   // Convert the value to a primitive; do not create a new CData object.
   if (!ConvertToJS(cx, GetCType(obj), NULL, GetData(obj), true, false, vp))
     return JS_FALSE;
 
   return JS_TRUE;
 }
 
 JSBool
-CData::ValueSetter(JSContext* cx, JSObject* obj, jsid idval, JSBool strict, jsval* vp)
+CData::ValueSetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, JSBool strict, jsval* vp)
 {
   if (!IsCData(obj)) {
     JS_ReportError(cx, "not a CData");
     return JS_FALSE;
   }
 
   return ImplicitConvert(cx, *vp, GetCType(obj), GetData(obj), false, NULL);
 }
@@ -6422,30 +6424,30 @@ CData::ToSource(JSContext* cx, unsigned 
   if (!result)
     return JS_FALSE;
 
   JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(result));
   return JS_TRUE;
 }
 
 JSBool
-CData::ErrnoGetter(JSContext* cx, JSObject* obj, jsid, jsval* vp)
+CData::ErrnoGetter(JSContext* cx, JSHandleObject obj, JSHandleId, jsval* vp)
 {
   if (!IsCTypesGlobal(obj)) {
     JS_ReportError(cx, "this is not not global object ctypes");
     return JS_FALSE;
   }
 
   *vp = JS_GetReservedSlot(obj, SLOT_ERRNO);
   return JS_TRUE;
 }
 
 #if defined(XP_WIN)
 JSBool
-CData::LastErrorGetter(JSContext* cx, JSObject* obj, jsid, jsval* vp)
+CData::LastErrorGetter(JSContext* cx, JSHandleObject obj, JSHandleId, jsval* vp)
 {
   if (!IsCTypesGlobal(obj)) {
     JS_ReportError(cx, "not global object ctypes");
     return JS_FALSE;
   }
 
 
   *vp = JS_GetReservedSlot(obj, SLOT_LASTERROR);
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -3717,21 +3717,23 @@ ParseNode::getConstantValue(JSContext *c
       case PNK_RB: {
         JS_ASSERT(isOp(JSOP_NEWINIT) && !(pn_xflags & PNX_NONCONST));
 
         RootedVarObject obj(cx, NewDenseAllocatedArray(cx, pn_count));
         if (!obj)
             return false;
 
         unsigned idx = 0;
+        RootedVarId id(cx);
         for (ParseNode *pn = pn_head; pn; idx++, pn = pn->pn_next) {
             Value value;
             if (!pn->getConstantValue(cx, strictChecks, &value))
                 return false;
-            if (!obj->defineGeneric(cx, INT_TO_JSID(idx), value, NULL, NULL, JSPROP_ENUMERATE))
+            id = INT_TO_JSID(idx);
+            if (!obj->defineGeneric(cx, id, value, NULL, NULL, JSPROP_ENUMERATE))
                 return false;
         }
         JS_ASSERT(idx == pn_count);
 
         types::FixArrayType(cx, obj);
         vp->setObject(*obj);
         return true;
       }
@@ -3746,27 +3748,27 @@ ParseNode::getConstantValue(JSContext *c
         for (ParseNode *pn = pn_head; pn; pn = pn->pn_next) {
             Value value;
             if (!pn->pn_right->getConstantValue(cx, strictChecks, &value))
                 return false;
 
             ParseNode *pnid = pn->pn_left;
             if (pnid->isKind(PNK_NUMBER)) {
                 Value idvalue = NumberValue(pnid->pn_dval);
-                jsid id;
+                RootedVarId id(cx);
                 if (idvalue.isInt32() && INT_FITS_IN_JSID(idvalue.toInt32()))
                     id = INT_TO_JSID(idvalue.toInt32());
-                else if (!InternNonIntElementId(cx, obj, idvalue, &id))
+                else if (!InternNonIntElementId(cx, obj, idvalue, id.address()))
                     return false;
                 if (!obj->defineGeneric(cx, id, value, NULL, NULL, JSPROP_ENUMERATE))
                     return false;
             } else {
                 JS_ASSERT(pnid->isKind(PNK_NAME) || pnid->isKind(PNK_STRING));
                 JS_ASSERT(pnid->pn_atom != cx->runtime->atomState.protoAtom);
-                jsid id = AtomToId(pnid->pn_atom);
+                RootedVarId id(cx, AtomToId(pnid->pn_atom));
                 if (!DefineNativeProperty(cx, obj, id, value, NULL, NULL,
                                           JSPROP_ENUMERATE, 0, 0)) {
                     return false;
                 }
             }
         }
 
         types::FixObjectType(cx, obj);
@@ -5759,17 +5761,17 @@ EmitObject(JSContext *cx, BytecodeEmitte
              * a non-standard setter on objects.
              */
             if (pn3->pn_atom == cx->runtime->atomState.protoAtom)
                 obj = NULL;
             op = JSOP_INITPROP;
 
             if (obj) {
                 JS_ASSERT(!obj->inDictionaryMode());
-                if (!DefineNativeProperty(cx, obj, AtomToId(pn3->pn_atom),
+                if (!DefineNativeProperty(cx, obj, RootedVarId(cx, AtomToId(pn3->pn_atom)),
                                           UndefinedValue(), NULL, NULL,
                                           JSPROP_ENUMERATE, 0, 0))
                 {
                     return false;
                 }
                 if (obj->inDictionaryMode())
                     obj = NULL;
             }
--- a/js/src/gc/Root.h
+++ b/js/src/gc/Root.h
@@ -131,21 +131,21 @@ class Handle
 
     /*
      * Construct a handle from an explicitly rooted location. This is the
      * normal way to create a handle.
      */
     template <typename S> inline Handle(const Root<S> &root);
     template <typename S> inline Handle(const RootedVar<S> &root);
 
-    const T *address() { return ptr; }
-    T value() { return *ptr; }
+    const T *address() const { return ptr; }
+    T value() const { return *ptr; }
 
-    operator T () { return value(); }
-    T operator ->() { return value(); }
+    operator T () const { return value(); }
+    T operator ->() const { return value(); }
 
   private:
     Handle() {}
 
     const T *ptr;
 
     template <typename S>
     void testAssign() {
--- a/js/src/jsapi-tests/testAddPropertyPropcache.cpp
+++ b/js/src/jsapi-tests/testAddPropertyPropcache.cpp
@@ -5,17 +5,17 @@
 #include "tests.h"
 
 /* Do the test a bunch of times, because sometimes we seem to randomly
    miss the propcache */
 static const int expectedCount = 100;
 static int callCount = 0;
 
 static JSBool
-addProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+addProperty(JSContext *cx, JS::HandleObject obj, JS::HandleId id, jsval *vp)
 {
   callCount++;
   return true;
 }
 
 JSClass addPropertyClass = {
     "AddPropertyTester",
     0,
--- a/js/src/jsapi-tests/testClassGetter.cpp
+++ b/js/src/jsapi-tests/testClassGetter.cpp
@@ -4,17 +4,17 @@
  * Tests the JSClass::getProperty hook
  */
 
 #include "tests.h"
 
 int called_test_fn;
 int called_test_prop_get;
 
-static JSBool test_prop_get( JSContext *cx, JSObject *obj, jsid id, jsval *vp )
+static JSBool test_prop_get( JSContext *cx, JS::HandleObject obj, JS::HandleId id, jsval *vp )
 {
     called_test_prop_get++;
     return JS_TRUE;
 }
 
 static JSBool
 PTest(JSContext* cx, unsigned argc, jsval *vp);
 
--- a/js/src/jsapi-tests/testCustomIterator.cpp
+++ b/js/src/jsapi-tests/testCustomIterator.cpp
@@ -9,17 +9,17 @@ IterNext(JSContext *cx, unsigned argc, j
 {
     if (count++ == 100)
         return JS_ThrowStopIteration(cx);
     JS_SET_RVAL(cx, vp, INT_TO_JSVAL(count));
     return true;
 }
 
 static JSObject *
-IterHook(JSContext *cx, JSObject *obj, JSBool keysonly)
+IterHook(JSContext *cx, JS::HandleObject obj, JSBool keysonly)
 {
     JSObject *iterObj = JS_NewObject(cx, NULL, NULL, NULL);
     if (!iterObj)
         return NULL;
     if (!JS_DefineFunction(cx, iterObj, "next", IterNext, 0, 0))
         return NULL;
     return iterObj;
 }
--- a/js/src/jsapi-tests/testExtendedEq.cpp
+++ b/js/src/jsapi-tests/testExtendedEq.cpp
@@ -4,17 +4,17 @@
  * This tests user-specified (via JSExtendedClass) equality operations on
  * trace.
  */
 
 #include "tests.h"
 #include "jsobj.h"
 
 static JSBool
-my_Equality(JSContext *cx, JSObject *obj, const jsval *, JSBool *bp)
+my_Equality(JSContext *cx, JS::HandleObject obj, const jsval *, JSBool *bp)
 {
     *bp = JS_TRUE;
     return JS_TRUE;
 }
 
 js::Class TestExtendedEq_JSClass = {
     "TestExtendedEq",
     0,
--- a/js/src/jsapi-tests/testLookup.cpp
+++ b/js/src/jsapi-tests/testLookup.cpp
@@ -29,30 +29,30 @@ BEGIN_TEST(testLookup_bug522590)
     CHECK(funobj->isFunction());
     CHECK(!js::IsInternalFunctionObject(funobj));
 
     return true;
 }
 END_TEST(testLookup_bug522590)
 
 JSBool
-document_resolve(JSContext *cx, JSObject *obj, jsid id, unsigned flags, JSObject **objp)
+document_resolve(JSContext *cx, JSHandleObject obj, JSHandleId id, unsigned flags, JSObject **objp)
 {
     // If id is "all", and we're not detecting, resolve document.all=true.
     jsvalRoot v(cx);
     if (!JS_IdToValue(cx, id, v.addr()))
         return false;
     if (JSVAL_IS_STRING(v.value())) {
         JSString *str = JSVAL_TO_STRING(v.value());
         JSFlatString *flatStr = JS_FlattenString(cx, str);
         if (!flatStr)
             return false;
         if (JS_FlatStringEqualsAscii(flatStr, "all") && !(flags & JSRESOLVE_DETECTING)) {
             JSBool ok = JS_DefinePropertyById(cx, obj, id, JSVAL_TRUE, NULL, NULL, 0);
-            *objp = ok ? obj : NULL;
+            *objp = ok ? obj.value() : NULL;
             return ok;
         }
     }
     *objp = NULL;
     return true;
 }
 
 static JSClass document_class = {
--- a/js/src/jsapi-tests/testOps.cpp
+++ b/js/src/jsapi-tests/testOps.cpp
@@ -2,17 +2,17 @@
  * vim: set ts=8 sw=4 et tw=99:
  *
  * Tests for operators and implicit type conversion.
  */
 
 #include "tests.h"
 
 static JSBool
-my_convert(JSContext* context, JSObject* obj, JSType type, jsval* rval)
+my_convert(JSContext* context, JS::HandleObject obj, JSType type, jsval* rval)
 {
     if (type == JSTYPE_VOID || type == JSTYPE_STRING || type == JSTYPE_NUMBER || type == JSTYPE_BOOLEAN)
         return JS_NewNumberValue(context, 123, rval);
     return JS_FALSE;
 }
 
 static JSClass myClass = {
     "MyClass",
--- a/js/src/jsapi-tests/testPropCache.cpp
+++ b/js/src/jsapi-tests/testPropCache.cpp
@@ -2,17 +2,17 @@
  * vim: set ts=8 sw=4 et tw=99:
  */
 
 #include "tests.h"
 
 static int g_counter;
 
 static JSBool
-CounterAdd(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+CounterAdd(JSContext *cx, JS::HandleObject obj, JS::HandleId id, jsval *vp)
 {
     g_counter++;
     return JS_TRUE;
 }
 
 static JSClass CounterClass = {
     "Counter",  /* name */
     0,  /* flags */
--- a/js/src/jsapi-tests/testResolveRecursion.cpp
+++ b/js/src/jsapi-tests/testResolveRecursion.cpp
@@ -118,15 +118,15 @@ doResolve(JSObject *obj, jsid id, unsign
             return true;
         }
     }
     CHECK(false);
     return false;
 }
 
 static JSBool
-my_resolve(JSContext *cx, JSObject *obj, jsid id, unsigned flags, JSObject **objp)
+my_resolve(JSContext *cx, JSHandleObject obj, JSHandleId id, unsigned flags, JSObject **objp)
 {
     return static_cast<cls_testResolveRecursion *>(JS_GetPrivate(obj))->
            doResolve(obj, id, flags, objp);
 }
 
 END_TEST(testResolveRecursion)
--- a/js/src/jsapi-tests/testSetProperty.cpp
+++ b/js/src/jsapi-tests/testSetProperty.cpp
@@ -1,16 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sw=4 et tw=99:
  */
 
 #include "tests.h"
 
 static JSBool
-nativeGet(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+nativeGet(JSContext *cx, JS::HandleObject obj, JS::HandleId id, jsval *vp)
 {
     *vp = INT_TO_JSVAL(17);
     return JS_TRUE;
 }
 
 BEGIN_TEST(testSetProperty_NativeGetterStubSetter)
 {
     jsvalRoot vobj(cx);
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1783,17 +1783,17 @@ JS_InitStandardClasses(JSContext *cx, JS
 
 #define CLASP(name)                 (&name##Class)
 #define TYPED_ARRAY_CLASP(type)     (&TypedArray::classes[TypedArray::type])
 #define EAGER_ATOM(name)            NAME_OFFSET(name)
 #define EAGER_CLASS_ATOM(name)      CLASS_NAME_OFFSET(name)
 #define EAGER_ATOM_AND_CLASP(name)  EAGER_CLASS_ATOM(name), CLASP(name)
 
 typedef struct JSStdName {
-    JSObjectOp  init;
+    JSClassInitializerOp init;
     size_t      atomOffset;     /* offset of atom pointer in JSAtomState */
     Class       *clasp;
 } JSStdName;
 
 static PropertyName *
 StdNameToPropertyName(JSContext *cx, JSStdName *stdn)
 {
     return OFFSET_TO_NAME(cx->runtime, stdn->atomOffset);
@@ -2111,17 +2111,17 @@ EnumerateIfResolved(JSContext *cx, JSObj
 
 JS_PUBLIC_API(JSIdArray *)
 JS_EnumerateResolvedStandardClasses(JSContext *cx, JSObject *obj, JSIdArray *ida)
 {
     JSRuntime *rt;
     int i, j, k;
     PropertyName *name;
     JSBool found;
-    JSObjectOp init;
+    JSClassInitializerOp init;
 
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, ida);
     rt = cx->runtime;
     if (ida) {
         i = ida->length;
     } else {
@@ -3093,41 +3093,41 @@ JS_DefaultValue(JSContext *cx, JSObject 
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     JS_ASSERT(obj != NULL);
     JS_ASSERT(hint == JSTYPE_VOID || hint == JSTYPE_STRING || hint == JSTYPE_NUMBER);
     return obj->defaultValue(cx, hint, vp);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_PropertyStub(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+JS_PropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, jsval *vp)
 {
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_StrictPropertyStub(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
+JS_StrictPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, jsval *vp)
 {
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_EnumerateStub(JSContext *cx, JSObject *obj)
+JS_EnumerateStub(JSContext *cx, JSHandleObject obj)
 {
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_ResolveStub(JSContext *cx, JSObject *obj, jsid id)
+JS_ResolveStub(JSContext *cx, JSHandleObject obj, JSHandleId id)
 {
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_ConvertStub(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
+JS_ConvertStub(JSContext *cx, JSHandleObject obj, JSType type, jsval *vp)
 {
     JS_ASSERT(type != JSTYPE_OBJECT && type != JSTYPE_FUNCTION);
     JS_ASSERT(obj);
     return DefaultValue(cx, RootedVarObject(cx, obj), type, vp);
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
@@ -3170,18 +3170,20 @@ JS_InstanceOf(JSContext *cx, JSObject *o
         if (argv)
             ReportIncompatibleMethod(cx, CallReceiverFromArgv(argv), Valueify(clasp));
         return false;
     }
     return true;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
-{
+JS_HasInstance(JSContext *cx, JSObject *obj_, jsval v, JSBool *bp)
+{
+    RootedVarObject obj(cx, obj_);
+
     AssertNoGC(cx);
     assertSameCompartment(cx, obj, v);
     return HasInstance(cx, obj, &v, bp);
 }
 
 JS_PUBLIC_API(void *)
 JS_GetPrivate(JSObject *obj)
 {
@@ -3467,17 +3469,17 @@ JS_ConstructObjectWithArguments(JSContex
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                              JSMSG_WRONG_CONSTRUCTOR, clasp->name);
         return NULL;
     }
     return &rval.toObject();
 }
 
 static JSBool
-LookupPropertyById(JSContext *cx, JSObject *obj, jsid id, unsigned flags,
+LookupPropertyById(JSContext *cx, JSObject *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);
@@ -3518,18 +3520,20 @@ 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)
+{
+    RootedVarId id(cx, id_);
+
     JSObject *obj2;
     JSProperty *prop;
     return LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &prop) &&
            LookupResult(cx, obj, obj2, id, prop, vp);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_LookupElement(JSContext *cx, JSObject *obj, uint32_t index, jsval *vp)
@@ -3551,19 +3555,22 @@ JS_LookupProperty(JSContext *cx, JSObjec
 JS_PUBLIC_API(JSBool)
 JS_LookupUCProperty(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen, jsval *vp)
 {
     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,
+JS_LookupPropertyWithFlagsById(JSContext *cx, JSObject *obj_, jsid id_, unsigned flags,
                                JSObject **objp, jsval *vp)
 {
+    RootedVarObject obj(cx, obj_);
+    RootedVarId id(cx, id_);
+
     JSBool ok;
     JSProperty *prop;
 
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, id);
     ok = obj->isNative()
          ? LookupPropertyWithFlags(cx, obj, id, flags, objp, &prop)
@@ -3575,18 +3582,20 @@ 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)
+{
+    RootedVarId id(cx, id_);
+
     JSObject *obj2;
     JSProperty *prop;
     JSBool ok = LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING,
                                    &obj2, &prop);
     *foundp = (prop != NULL);
     return ok;
 }
 
@@ -3611,18 +3620,20 @@ JS_HasProperty(JSContext *cx, JSObject *
 JS_PUBLIC_API(JSBool)
 JS_HasUCProperty(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen, JSBool *foundp)
 {
     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)
+{
+    RootedVarId id(cx, id_);
+
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, id);
 
     if (!obj->isNative()) {
         JSObject *obj2;
         JSProperty *prop;
 
@@ -3883,17 +3894,17 @@ JS_DefineProperties(JSContext *cx, JSObj
                             ps->flags, Shape::HAS_SHORTID, ps->tinyid);
         if (!ok)
             break;
     }
     return ok;
 }
 
 static JSBool
-GetPropertyDescriptorById(JSContext *cx, JSObject *obj, jsid id, unsigned flags,
+GetPropertyDescriptorById(JSContext *cx, JSObject *obj, HandleId id, unsigned flags,
                           JSBool own, PropertyDescriptor *desc)
 {
     JSObject *obj2;
     JSProperty *prop;
 
     if (!LookupPropertyById(cx, obj, id, flags, &obj2, &prop))
         return JS_FALSE;
 
@@ -3928,27 +3939,29 @@ 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)
 {
+    RootedVarId id(cx, id_);
     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)
 {
+    RootedVarId 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)
         *getterp = desc.getter;
@@ -4000,17 +4013,17 @@ JS_PUBLIC_API(JSBool)
 JS_GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
 {
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     return GetOwnPropertyDescriptor(cx, RootedVarObject(cx, obj), RootedVarId(cx, id), vp);
 }
 
 static JSBool
-SetPropertyAttributesById(JSContext *cx, JSObject *obj, jsid id, unsigned attrs, JSBool *foundp)
+SetPropertyAttributesById(JSContext *cx, JSObject *obj, HandleId id, unsigned attrs, JSBool *foundp)
 {
     JSObject *obj2;
     JSProperty *prop;
 
     if (!LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &prop))
         return false;
     if (!prop || obj != obj2) {
         *foundp = false;
@@ -4025,69 +4038,76 @@ SetPropertyAttributesById(JSContext *cx,
     return ok;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_SetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
                          unsigned attrs, JSBool *foundp)
 {
     JSAtom *atom = js_Atomize(cx, name, strlen(name));
-    return atom && SetPropertyAttributesById(cx, obj, AtomToId(atom), attrs, foundp);
+    return atom && SetPropertyAttributesById(cx, obj, RootedVarId(cx, AtomToId(atom)), attrs, foundp);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_SetUCPropertyAttributes(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen,
                            unsigned attrs, JSBool *foundp)
 {
     JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
-    return atom && SetPropertyAttributesById(cx, obj, AtomToId(atom), attrs, foundp);
+    return atom && SetPropertyAttributesById(cx, obj, RootedVarId(cx, AtomToId(atom)), attrs, foundp);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_GetPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
 {
     return JS_ForwardGetPropertyTo(cx, obj, id, obj, vp);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_ForwardGetPropertyTo(JSContext *cx, JSObject *obj, jsid id, JSObject *onBehalfOf, jsval *vp)
-{
+JS_ForwardGetPropertyTo(JSContext *cx, JSObject *obj, jsid id_, JSObject *onBehalfOf_, jsval *vp)
+{
+    RootedVarId id(cx, id_);
+    RootedVarObject onBehalfOf(cx, onBehalfOf_);
+
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, id);
     assertSameCompartment(cx, onBehalfOf);
     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
     return obj->getGeneric(cx, onBehalfOf, id, vp);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_GetPropertyByIdDefault(JSContext *cx, JSObject *obj, jsid id, jsval def, jsval *vp)
 {
-    return GetPropertyDefault(cx, RootedVarObject(cx, obj), RootedVarId(cx, id), def, vp);
+    return baseops::GetPropertyDefault(cx, RootedVarObject(cx, obj), RootedVarId(cx, id), def, vp);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_GetElement(JSContext *cx, JSObject *obj, uint32_t index, jsval *vp)
 {
     return JS_ForwardGetElementTo(cx, obj, index, obj, vp);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_ForwardGetElementTo(JSContext *cx, JSObject *obj, uint32_t index, JSObject *onBehalfOf, jsval *vp)
-{
+JS_ForwardGetElementTo(JSContext *cx, JSObject *obj, uint32_t index, JSObject *onBehalfOf_, jsval *vp)
+{
+    RootedVarObject onBehalfOf(cx, onBehalfOf_);
+
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
     return obj->getElement(cx, onBehalfOf, index, vp);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_GetElementIfPresent(JSContext *cx, JSObject *obj, uint32_t index, JSObject *onBehalfOf, jsval *vp, JSBool* present)
-{
+JS_GetElementIfPresent(JSContext *cx, JSObject *obj, uint32_t index, JSObject *onBehalfOf_, jsval *vp, JSBool* present)
+{
+    RootedVarObject onBehalfOf(cx, onBehalfOf_);
+
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
     bool isPresent;
     if (!obj->getElementIfPresent(cx, onBehalfOf, index, vp, &isPresent))
         return false;
     *present = isPresent;
@@ -4114,62 +4134,67 @@ JS_PUBLIC_API(JSBool)
 JS_GetUCProperty(JSContext *cx, JSObject *obj_, const jschar *name, size_t namelen, jsval *vp)
 {
     RootedVarObject obj(cx, obj_);
     JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
     return atom && JS_GetPropertyById(cx, obj, AtomToId(atom), vp);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_GetMethodById(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, jsval *vp)
-{
+JS_GetMethodById(JSContext *cx, JSObject *obj_, jsid id_, JSObject **objp, jsval *vp)
+{
+    RootedVarObject obj(cx, obj_);
+    RootedVarId id(cx, id_);
+
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, id);
-    if (!js_GetMethod(cx, RootedVarObject(cx, obj), id, 0, vp))
+    if (!GetMethod(cx, obj, id, 0, vp))
         return JS_FALSE;
     if (objp)
         *objp = obj;
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_GetMethod(JSContext *cx, JSObject *obj, const char *name, JSObject **objp, jsval *vp)
 {
     JSAtom *atom = js_Atomize(cx, name, strlen(name));
     return atom && JS_GetMethodById(cx, obj, AtomToId(atom), objp, vp);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_SetPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
-{
+JS_SetPropertyById(JSContext *cx, JSObject *obj, jsid id_, jsval *vp)
+{
+    RootedVarId id(cx, id_);
+
     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)
 {
-    AssertNoGC(cx);
-    CHECK_REQUEST(cx);
-    assertSameCompartment(cx, obj_, *vp);
     RootedVarObject obj(cx, obj_);
-    RootValue vpRoot(cx, 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)
 {
     RootedVarObject obj(cx, obj_);
-    RootValue vpRoot(cx, vp);
+
     JSAtom *atom = js_Atomize(cx, name, strlen(name));
     return atom && JS_SetPropertyById(cx, obj, AtomToId(atom), vp);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_SetUCProperty(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen, jsval *vp)
 {
     JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
@@ -4180,17 +4205,17 @@ JS_PUBLIC_API(JSBool)
 JS_DeletePropertyById2(JSContext *cx, JSObject *obj, jsid id, jsval *rval)
 {
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, id);
     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
 
     if (JSID_IS_SPECIAL(id))
-        return obj->deleteSpecial(cx, JSID_TO_SPECIALID(id), rval, false);
+        return obj->deleteSpecial(cx, RootedVar<SpecialId>(cx, JSID_TO_SPECIALID(id)), rval, false);
 
     return obj->deleteByValue(cx, IdToValue(id), rval, false);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_DeleteElement2(JSContext *cx, JSObject *obj, uint32_t index, jsval *rval)
 {
     AssertNoGC(cx);
@@ -4245,18 +4270,20 @@ JS_DeleteElement(JSContext *cx, JSObject
 JS_PUBLIC_API(JSBool)
 JS_DeleteProperty(JSContext *cx, JSObject *obj, const char *name)
 {
     jsval junk;
     return JS_DeleteProperty2(cx, obj, name, &junk);
 }
 
 JS_PUBLIC_API(void)
-JS_ClearScope(JSContext *cx, JSObject *obj)
-{
+JS_ClearScope(JSContext *cx, JSObject *obj_)
+{
+    RootedVarObject obj(cx, obj_);
+
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
 
     ClearOp clearOp = obj->getOps()->clear;
     if (clearOp)
         clearOp(cx, obj);
 
@@ -4433,17 +4460,17 @@ JS_NewElementIterator(JSContext *cx, JSO
 {
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     return ElementIteratorObject::create(cx, RootedVarObject(cx, obj));
 }
 
 JS_PUBLIC_API(JSObject *)
-JS_ElementIteratorStub(JSContext *cx, JSObject *obj, JSBool keysonly)
+JS_ElementIteratorStub(JSContext *cx, JSHandleObject obj, JSBool keysonly)
 {
     JS_ASSERT(!keysonly);
     return JS_NewElementIterator(cx, obj);
 }
 
 JS_PUBLIC_API(jsval)
 JS_GetReservedSlot(JSObject *obj, uint32_t index)
 {
@@ -4488,19 +4515,21 @@ JS_SetArrayLength(JSContext *cx, JSObjec
 {
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     return js_SetLengthProperty(cx, obj, length);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
+JS_CheckAccess(JSContext *cx, JSObject *obj, jsid id_, JSAccessMode mode,
                jsval *vp, unsigned *attrsp)
 {
+    RootedVarId id(cx, id_);
+
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, id);
     return CheckAccess(cx, obj, id, mode, vp, attrsp);
 }
 
 JS_PUBLIC_API(void)
 JS_HoldPrincipals(JSPrincipals *principals)
@@ -4731,33 +4760,33 @@ JS_DefineFunctions(JSContext *cx, JSObje
 
             if (!ctor) {
                 ctor = JS_GetConstructor(cx, obj);
                 if (!ctor)
                     return JS_FALSE;
             }
 
             flags &= ~JSFUN_GENERIC_NATIVE;
-            fun = js_DefineFunction(cx, ctor, AtomToId(atom),
+            fun = js_DefineFunction(cx, ctor, RootedVarId(cx, AtomToId(atom)),
                                     js_generic_native_method_dispatcher,
                                     fs->nargs + 1,
                                     flags,
                                     JSFunction::ExtendedFinalizeKind);
             if (!fun)
                 return JS_FALSE;
 
             /*
              * As jsapi.h notes, fs must point to storage that lives as long
              * as fun->object lives.
              */
             fun->setExtendedSlot(0, PrivateValue(fs));
         }
 
         fun = js_DefineFunction(cx, objRoot,
-                                AtomToId(atom), fs->call, fs->nargs, flags);
+                                RootedVarId(cx, AtomToId(atom)), fs->call, fs->nargs, flags);
         if (!fun)
             return JS_FALSE;
     }
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSFunction *)
 JS_DefineFunction(JSContext *cx, JSObject *obj, const char *name, JSNative call,
@@ -4767,47 +4796,48 @@ JS_DefineFunction(JSContext *cx, JSObjec
 
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     JSAtom *atom = js_Atomize(cx, name, strlen(name));
     if (!atom)
         return NULL;
-    return js_DefineFunction(cx, objRoot, AtomToId(atom), call, nargs, attrs);
+    return js_DefineFunction(cx, objRoot, RootedVarId(cx, AtomToId(atom)), call, nargs, attrs);
 }
 
 JS_PUBLIC_API(JSFunction *)
 JS_DefineUCFunction(JSContext *cx, JSObject *obj,
                     const jschar *name, size_t namelen, JSNative call,
                     unsigned nargs, unsigned attrs)
 {
     RootObject objRoot(cx, &obj);
 
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
     if (!atom)
         return NULL;
-    return js_DefineFunction(cx, objRoot, AtomToId(atom), call, nargs, attrs);
+    return js_DefineFunction(cx, objRoot, RootedVarId(cx, AtomToId(atom)), call, nargs, attrs);
 }
 
 extern JS_PUBLIC_API(JSFunction *)
-JS_DefineFunctionById(JSContext *cx, JSObject *obj, jsid id, JSNative call,
+JS_DefineFunctionById(JSContext *cx, JSObject *obj_, jsid id_, JSNative call,
                     unsigned nargs, unsigned attrs)
 {
-    RootObject objRoot(cx, &obj);
+    RootedVarObject obj(cx, obj_);
+    RootedVarId id(cx, id_);
 
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
-    return js_DefineFunction(cx, objRoot, id, call, nargs, attrs);
+    return js_DefineFunction(cx, obj, id, call, nargs, attrs);
 }
 
 struct AutoLastFrameCheck {
     AutoLastFrameCheck(JSContext *cx JS_GUARD_OBJECT_NOTIFIER_PARAM)
       : cx(cx) {
         JS_ASSERT(cx);
         JS_GUARD_OBJECT_NOTIFIER_INIT;
     }
@@ -5149,17 +5179,17 @@ CompileUCFunctionForPrincipalsCommon(JSC
 
     if (!frontend::CompileFunctionBody(cx, fun, principals, NULL, &bindings,
                                        chars, length, filename, lineno, version))
     {
         return NULL;
     }
 
     if (obj && funAtom &&
-        !obj->defineGeneric(cx, AtomToId(funAtom), ObjectValue(*fun), NULL, NULL,
+        !obj->defineGeneric(cx, RootedVarId(cx, AtomToId(funAtom)), ObjectValue(*fun), NULL, NULL,
                             JSPROP_ENUMERATE))
     {
         return NULL;
     }
 
     return fun;
 }
 
@@ -5451,17 +5481,17 @@ JS_CallFunctionName(JSContext *cx, JSObj
     assertSameCompartment(cx, obj_, JSValueArray(argv, argc));
     AutoLastFrameCheck lfc(cx);
 
     RootedVarObject obj(cx, obj_);
 
     Value v;
     JSAtom *atom = js_Atomize(cx, name, strlen(name));
     return atom &&
-           js_GetMethod(cx, obj, AtomToId(atom), 0, &v) &&
+           GetMethod(cx, obj, RootedVarId(cx, AtomToId(atom)), 0, &v) &&
            Invoke(cx, ObjectOrNullValue(obj), v, argc, argv, rval);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_CallFunctionValue(JSContext *cx, JSObject *obj, jsval fval, unsigned argc, jsval *argv,
                      jsval *rval)
 {
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1299,37 +1299,60 @@ IMPL_TO_JSVAL(jsval_layout l)
 typedef struct { char c; jsval_layout l; } JSLayoutAlignmentTester;
 JS_STATIC_ASSERT(sizeof(JSLayoutAlignmentTester) == 16);
 #endif /* DEBUG */
 
 JS_STATIC_ASSERT(sizeof(jsval_layout) == sizeof(jsval));
 
 /************************************************************************/
 
+#ifdef __cplusplus
+
+typedef JS::Handle<JSObject*> JSHandleObject;
+typedef JS::Handle<jsid> JSHandleId;
+
+#else
+
+/*
+ * Handle support for C API users. Handles must be destroyed in the reverse
+ * order that they were created (as in a stack).
+ */
+
+typedef struct { JSObject **_; } JSHandleObject;
+typedef struct { jsid *_; } JSHandleId;
+
+JSBool JS_CreateHandleObject(JSContext *cx, JSObject *obj, JSHandleObject *phandle);
+void JS_DestroyHandleObject(JSContext *cx, JSHandleObject handle);
+
+JSBool JS_CreateHandleId(JSContext *cx, jsid id, JSHandleId *phandle);
+void JS_DestroyHandleId(JSContext *cx, JSHandleId handle);
+
+#endif
+
 /* JSClass operation signatures. */
 
 /*
  * Add, delete, or get a property named by id in obj.  Note the jsid id
  * type -- id may be a string (Unicode property identifier) or an int (element
  * index).  The *vp out parameter, on success, is the new property value after
  * an add or get.  After a successful delete, *vp is JSVAL_FALSE iff
  * obj[id] can't be deleted (because it's permanent).
  */
 typedef JSBool
-(* JSPropertyOp)(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
+(* JSPropertyOp)(JSContext *cx, JSHandleObject obj, JSHandleId id, jsval *vp);
 
 /*
  * Set a property named by id in obj, treating the assignment as strict
  * mode code if strict is true. Note the jsid id type -- id may be a string
  * (Unicode property identifier) or an int (element index). The *vp out
  * parameter, on success, is the new property value after the
  * set.
  */
 typedef JSBool
-(* JSStrictPropertyOp)(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp);
+(* JSStrictPropertyOp)(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, jsval *vp);
 
 /*
  * This function type is used for callbacks that enumerate the properties of
  * a JSObject.  The behavior depends on the value of enum_op:
  *
  *  JSENUMERATE_INIT
  *    A new, opaque iterator state should be allocated and stored in *statep.
  *    (You can use PRIVATE_TO_JSVAL() to tag the pointer to be stored).
@@ -1354,40 +1377,40 @@ typedef JSBool
  *    Destroy the opaque iterator state previously allocated in *statep by a
  *    call to this function when enum_op was JSENUMERATE_INIT or
  *    JSENUMERATE_INIT_ALL.
  *
  * The return value is used to indicate success, with a value of JS_FALSE
  * indicating failure.
  */
 typedef JSBool
-(* JSNewEnumerateOp)(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
+(* JSNewEnumerateOp)(JSContext *cx, JSHandleObject obj, JSIterateOp enum_op,
                      jsval *statep, jsid *idp);
 
 /*
  * The old-style JSClass.enumerate op should define all lazy properties not
  * yet reflected in obj.
  */
 typedef JSBool
-(* JSEnumerateOp)(JSContext *cx, JSObject *obj);
+(* JSEnumerateOp)(JSContext *cx, JSHandleObject obj);
 
 /*
  * Resolve a lazy property named by id in obj by defining it directly in obj.
  * Lazy properties are those reflected from some peer native property space
  * (e.g., the DOM attributes for a given node reflected as obj) on demand.
  *
  * JS looks for a property in an object, and if not found, tries to resolve
  * the given id.  If resolve succeeds, the engine looks again in case resolve
  * defined obj[id].  If no such property exists directly in obj, the process
  * is repeated with obj's prototype, etc.
  *
  * NB: JSNewResolveOp provides a cheaper way to resolve lazy properties.
  */
 typedef JSBool
-(* JSResolveOp)(JSContext *cx, JSObject *obj, jsid id);
+(* JSResolveOp)(JSContext *cx, JSHandleObject obj, JSHandleId id);
 
 /*
  * Like JSResolveOp, but flags provide contextual information as follows:
  *
  *  JSRESOLVE_QUALIFIED   a qualified property id: obj.id or obj[id], not id
  *  JSRESOLVE_ASSIGNING   obj[id] is on the left-hand side of an assignment
  *  JSRESOLVE_DETECTING   'if (o.p)...' or similar detection opcode sequence
  *  JSRESOLVE_DECLARING   var, const, or function prolog declaration opcode
@@ -1409,25 +1432,25 @@ typedef JSBool
  * When using JSCLASS_NEW_RESOLVE_GETS_START, the resolve hook must therefore
  * null *objp to signify "not resolved".  With only JSCLASS_NEW_RESOLVE and no
  * JSCLASS_NEW_RESOLVE_GETS_START, the hook can assume *objp is null on entry.
  * This is not good practice, but enough existing hook implementations count
  * on it that we can't break compatibility by passing the starting object in
  * *objp without a new JSClass flag.
  */
 typedef JSBool
-(* JSNewResolveOp)(JSContext *cx, JSObject *obj, jsid id, unsigned flags,
+(* JSNewResolveOp)(JSContext *cx, JSHandleObject obj, JSHandleId id, unsigned flags,
                    JSObject **objp);
 
 /*
  * Convert obj to the given type, returning true with the resulting value in
  * *vp on success, and returning false on error or exception.
  */
 typedef JSBool
-(* JSConvertOp)(JSContext *cx, JSObject *obj, JSType type, jsval *vp);
+(* JSConvertOp)(JSContext *cx, JSHandleObject obj, JSType type, jsval *vp);
 
 /*
  * Delegate typeof to an object so it can cloak a primitive or another object.
  */
 typedef JSType
 (* JSTypeOfOp)(JSContext *cx, JSObject *obj);
 
 typedef struct JSFreeOp JSFreeOp;
@@ -1469,26 +1492,26 @@ struct JSStringFinalizer {
 
 /*
  * JSClass.checkAccess type: check whether obj[id] may be accessed per mode,
  * returning false on error/exception, true on success with obj[id]'s last-got
  * value in *vp, and its attributes in *attrsp.  As for JSPropertyOp above, id
  * is either a string or an int jsval.
  */
 typedef JSBool
-(* JSCheckAccessOp)(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
+(* JSCheckAccessOp)(JSContext *cx, JSHandleObject obj, JSHandleId id, JSAccessMode mode,
                     jsval *vp);
 
 /*
  * Check whether v is an instance of obj.  Return false on error or exception,
  * true on success with JS_TRUE in *bp if v is an instance of obj, JS_FALSE in
  * *bp otherwise.
  */
 typedef JSBool
-(* JSHasInstanceOp)(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp);
+(* JSHasInstanceOp)(JSContext *cx, JSHandleObject obj, const jsval *v, JSBool *bp);
 
 /*
  * Function type for trace operation of the class called to enumerate all
  * traceable things reachable from obj's private data structure. For each such
  * thing, a trace implementation must call
  *
  *    JS_CallTracer(trc, thing, kind);
  *
@@ -1508,17 +1531,17 @@ typedef void
 /*
  * DEBUG only callback that JSTraceOp implementation can provide to return
  * a string describing the reference traced with JS_CallTracer.
  */
 typedef void
 (* JSTraceNamePrinter)(JSTracer *trc, char *buf, size_t bufsize);
 
 typedef JSBool
-(* JSEqualityOp)(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp);
+(* JSEqualityOp)(JSContext *cx, JSHandleObject obj, const jsval *v, JSBool *bp);
 
 /*
  * Typedef for native functions called by the JS VM.
  *
  * See jsapi.h, the JS_CALLEE, JS_THIS, etc. macros.
  */
 
 typedef JSBool
@@ -3813,29 +3836,29 @@ JS_IdToValue(JSContext *cx, jsid id, jsv
  * the specified object, computing a primitive default value for the object.
  * The hint must be JSTYPE_STRING, JSTYPE_NUMBER, or JSTYPE_VOID (no hint).  On
  * success the resulting value is stored in *vp.
  */
 extern JS_PUBLIC_API(JSBool)
 JS_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp);
 
 extern JS_PUBLIC_API(JSBool)
-JS_PropertyStub(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
+JS_PropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, jsval *vp);
 
 extern JS_PUBLIC_API(JSBool)
-JS_StrictPropertyStub(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp);
+JS_StrictPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, jsval *vp);
 
 extern JS_PUBLIC_API(JSBool)
-JS_EnumerateStub(JSContext *cx, JSObject *obj);
+JS_EnumerateStub(JSContext *cx, JSHandleObject obj);
 
 extern JS_PUBLIC_API(JSBool)
-JS_ResolveStub(JSContext *cx, JSObject *obj, jsid id);
+JS_ResolveStub(JSContext *cx, JSHandleObject obj, JSHandleId id);
 
 extern JS_PUBLIC_API(JSBool)
-JS_ConvertStub(JSContext *cx, JSObject *obj, JSType type, jsval *vp);
+JS_ConvertStub(JSContext *cx, JSHandleObject obj, JSType type, jsval *vp);
 
 struct JSConstDoubleSpec {
     double          dval;
     const char      *name;
     uint8_t         flags;
     uint8_t         spare[3];
 };
 
@@ -4295,17 +4318,17 @@ extern JS_PUBLIC_API(JSObject *)
 JS_NewElementIterator(JSContext *cx, JSObject *obj);
 
 /*
  * To make your array-like class iterable using the for-of loop, set the
  * JSCLASS_FOR_OF_ITERATION bit in the class's flags field and set its
  * .ext.iteratorObject hook to this function.
  */
 extern JS_PUBLIC_API(JSObject *)
-JS_ElementIteratorStub(JSContext *cx, JSObject *obj, JSBool keysonly);
+JS_ElementIteratorStub(JSContext *cx, JSHandleObject obj, JSBool keysonly);
 
 extern JS_PUBLIC_API(JSBool)
 JS_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
                jsval *vp, unsigned *attrsp);
 
 extern JS_PUBLIC_API(jsval)
 JS_GetReservedSlot(JSObject *obj, uint32_t index);
 
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -390,17 +390,17 @@ DoGetElement(JSContext *cx, JSObject *ob
         if (!obj->getGeneric(cx, id, vp))
             return JS_FALSE;
         *hole = JS_FALSE;
     }
     return JS_TRUE;
 }
 
 static inline JSBool
-DoGetElement(JSContext *cx, JSObject *obj, uint32_t index, JSBool *hole, Value *vp)
+DoGetElement(JSContext *cx, HandleObject obj, uint32_t index, JSBool *hole, Value *vp)
 {
     bool present;
     if (!obj->getElementIfPresent(cx, obj, index, vp, &present))
         return false;
 
     *hole = !present;
     if (*hole)
         vp->setUndefined();
@@ -507,24 +507,24 @@ SetArrayElement(JSContext *cx, HandleObj
 
         if (result == JSObject::ED_FAILED)
             return false;
         JS_ASSERT(result == JSObject::ED_SPARSE);
         if (!JSObject::makeDenseArraySlow(cx, obj))
             return JS_FALSE;
     }
 
-    AutoIdRooter idr(cx);
-
-    if (!IndexToId(cx, obj, index, NULL, idr.addr(), JS_TRUE))
+    RootedVarId id(cx);
+
+    if (!IndexToId(cx, obj, index, NULL, id.address(), JS_TRUE))
         return JS_FALSE;
-    JS_ASSERT(!JSID_IS_VOID(idr.id()));
+    JS_ASSERT(!JSID_IS_VOID(id));
 
     RootedVarValue tmp(cx, v);
-    return obj->setGeneric(cx, idr.id(), tmp.address(), true);
+    return obj->setGeneric(cx, id, tmp.address(), true);
 }
 
 /*
  * Delete the element |index| from |obj|. If |strict|, do a strict
  * deletion: throw if the property is not configurable.
  *
  * - Return 1 if the deletion succeeds (that is, ES5's [[Delete]] would
  *   return true)
@@ -593,32 +593,31 @@ js_SetLengthProperty(JSContext *cx, JSOb
 /*
  * Since SpiderMonkey supports cross-class prototype-based delegation, we have
  * to be careful about the length getter and setter being called on an object
  * not of Array class. For the getter, we search obj's prototype chain for the
  * array that caused this getter to be invoked. In the setter case to overcome
  * the JSPROP_SHARED attribute, we must define a shadowing length property.
  */
 static JSBool
-array_length_getter(JSContext *cx, JSObject *obj, jsid id, Value *vp)
+array_length_getter(JSContext *cx, HandleObject obj_, HandleId id, Value *vp)
 {
+    JSObject *obj = obj_;
     do {
         if (obj->isArray()) {
             vp->setNumber(obj->getArrayLength());
             return JS_TRUE;
         }
     } while ((obj = obj->getProto()) != NULL);
     return JS_TRUE;
 }
 
 static JSBool
-array_length_setter(JSContext *cx, JSObject *obj_, jsid id, JSBool strict, Value *vp)
+array_length_setter(JSContext *cx, HandleObject obj, HandleId id, JSBool strict, Value *vp)
 {
-    RootedVarObject obj(cx, obj_);
-
     if (!obj->isArray()) {
         return obj->defineProperty(cx, cx->runtime->atomState.lengthAtom, *vp,
                                    NULL, NULL, JSPROP_ENUMERATE);
     }
 
     uint32_t newlen;
     if (!ToUint32(cx, *vp, &newlen))
         return false;
@@ -677,23 +676,24 @@ array_length_setter(JSContext *cx, JSObj
          * bug 322135.
          */
         JSObject *iter = JS_NewPropertyIterator(cx, obj);
         if (!iter)
             return false;
 
         uint32_t gap = oldlen - newlen;
         for (;;) {
-            if (!JS_CHECK_OPERATION_LIMIT(cx) || !JS_NextProperty(cx, iter, &id))
+            jsid nid;
+            if (!JS_CHECK_OPERATION_LIMIT(cx) || !JS_NextProperty(cx, iter, &nid))
                 return false;
-            if (JSID_IS_VOID(id))
+            if (JSID_IS_VOID(nid))
                 break;
             uint32_t index;
             Value junk;
-            if (js_IdIsIndex(id, &index) && index - newlen < gap &&
+            if (js_IdIsIndex(nid, &index) && index - newlen < gap &&
                 !obj->deleteElement(cx, index, &junk, false)) {
                 return false;
             }
         }
     }
 
     obj->setArrayLength(cx, newlen);
     return true;
@@ -719,21 +719,21 @@ IsDenseArrayId(JSContext *cx, JSObject *
     JS_ASSERT(obj->isDenseArray());
 
     uint32_t i;
     return JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom) ||
            (js_IdIsIndex(id, &i) && IsDenseArrayIndex(obj, i));
 }
 
 static JSBool
-array_lookupGeneric(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
+array_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, JSObject **objp,
                     JSProperty **propp)
 {
     if (!obj->isDenseArray())
-        return js_LookupProperty(cx, obj, id, objp, propp);
+        return baseops::LookupProperty(cx, obj, id, objp, propp);
 
     if (IsDenseArrayId(cx, obj, id)) {
         *propp = (JSProperty *) 1;  /* non-null to indicate found */
         *objp = obj;
         return JS_TRUE;
     }
 
     JSObject *proto = obj->getProto();
@@ -741,48 +741,48 @@ array_lookupGeneric(JSContext *cx, JSObj
         *objp = NULL;
         *propp = NULL;
         return JS_TRUE;
     }
     return proto->lookupGeneric(cx, id, objp, propp);
 }
 
 static JSBool
-array_lookupProperty(JSContext *cx, JSObject *obj, PropertyName *name, JSObject **objp,
+array_lookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, JSObject **objp,
                      JSProperty **propp)
 {
-    return array_lookupGeneric(cx, obj, NameToId(name), objp, propp);
+    return array_lookupGeneric(cx, obj, RootedVarId(cx, NameToId(name)), objp, propp);
 }
 
 static JSBool
-array_lookupElement(JSContext *cx, JSObject *obj, uint32_t index, JSObject **objp,
+array_lookupElement(JSContext *cx, HandleObject obj, uint32_t index, JSObject **objp,
                     JSProperty **propp)
 {
     if (!obj->isDenseArray())
-        return js_LookupElement(cx, obj, index, objp, propp);
+        return baseops::LookupElement(cx, obj, index, objp, propp);
 
     if (IsDenseArrayIndex(obj, index)) {
         *propp = (JSProperty *) 1;  /* non-null to indicate found */
         *objp = obj;
         return true;
     }
 
     if (JSObject *proto = obj->getProto())
         return proto->lookupElement(cx, index, objp, propp);
 
     *objp = NULL;
     *propp = NULL;
     return true;
 }
 
 static JSBool
-array_lookupSpecial(JSContext *cx, JSObject *obj, SpecialId sid, JSObject **objp,
+array_lookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, JSObject **objp,
                     JSProperty **propp)
 {
-    return array_lookupGeneric(cx, obj, SPECIALID_TO_JSID(sid), objp, propp);
+    return array_lookupGeneric(cx, obj, RootedVarId(cx, SPECIALID_TO_JSID(sid)), objp, propp);
 }
 
 JSBool
 js_GetDenseArrayElementValue(JSContext *cx, JSObject *obj, jsid id, Value *vp)
 {
     JS_ASSERT(obj->isDenseArray());
 
     uint32_t i;
@@ -791,57 +791,45 @@ js_GetDenseArrayElementValue(JSContext *
         vp->setNumber(obj->getArrayLength());
         return JS_TRUE;
     }
     *vp = obj->getDenseArrayElement(i);
     return JS_TRUE;
 }
 
 static JSBool
-array_getProperty(JSContext *cx, JSObject *obj, JSObject *receiver, PropertyName *name, Value *vp)
+array_getProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandlePropertyName name, Value *vp)
 {
     if (name == cx->runtime->atomState.lengthAtom) {
         vp->setNumber(obj->getArrayLength());
         return true;
     }
 
     if (name == cx->runtime->atomState.protoAtom) {
         vp->setObjectOrNull(obj->getProto());
         return true;
     }
 
     if (!obj->isDenseArray())
-    {
-        return js_GetProperty(cx,
-                              RootedVarObject(cx, obj),
-                              RootedVarObject(cx, receiver),
-                              NameToId(name),
-                              vp);
-    }
+        return baseops::GetProperty(cx, obj, receiver, RootedVarId(cx, NameToId(name)), vp);
 
     JSObject *proto = obj->getProto();
     if (!proto) {
         vp->setUndefined();
         return true;
     }
 
     return proto->getProperty(cx, receiver, name, vp);
 }
 
 static JSBool
-array_getElement(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t index, Value *vp)
+array_getElement(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index, Value *vp)
 {
     if (!obj->isDenseArray())
-    {
-        return js_GetElement(cx,
-                             RootedVarObject(cx, obj),
-                             RootedVarObject(cx, receiver),
-                             index,
-                             vp);
-    }
+        return baseops::GetElement(cx, obj, receiver, index, vp);
 
     if (index < obj->getDenseArrayInitializedLength()) {
         *vp = obj->getDenseArrayElement(index);
         if (!vp->isMagic(JS_ARRAY_HOLE)) {
             /* Type information for dense array elements must be correct. */
             JS_ASSERT_IF(!obj->hasSingletonType(),
                          js::types::TypeHasProperty(cx, obj->type(), JSID_VOID, *vp));
 
@@ -854,83 +842,76 @@ array_getElement(JSContext *cx, JSObject
         vp->setUndefined();
         return true;
     }
 
     return proto->getElement(cx, receiver, index, vp);
 }
 
 static JSBool
-array_getSpecial(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid, Value *vp)
+array_getSpecial(JSContext *cx, HandleObject obj, HandleObject receiver, HandleSpecialId sid, Value *vp)
 {
     if (obj->isDenseArray() && !obj->getProto()) {
         vp->setUndefined();
         return true;
     }
 
-    return js_GetProperty(cx,
-                          RootedVarObject(cx, obj),
-                          RootedVarObject(cx, receiver),
-                          SPECIALID_TO_JSID(sid),
-                          vp);
+    return baseops::GetProperty(cx, obj, receiver, RootedVarId(cx, SPECIALID_TO_JSID(sid)), vp);
 }
 
 static JSBool
-array_getGeneric(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp)
+array_getGeneric(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id, Value *vp)
 {
     Value idval = IdToValue(id);
 
     uint32_t index;
     if (IsDefinitelyIndex(idval, &index))
         return array_getElement(cx, obj, receiver, index, vp);
 
     SpecialId sid;
     if (ValueIsSpecial(obj, &idval, &sid, cx))
-        return array_getSpecial(cx, obj, receiver, sid, vp);
+        return array_getSpecial(cx, obj, receiver, RootedVar<SpecialId>(cx, sid), vp);
 
     JSAtom *atom;
     if (!js_ValueToAtom(cx, idval, &atom))
         return false;
 
     if (atom->isIndex(&index))
         return array_getElement(cx, obj, receiver, index, vp);
 
-    return array_getProperty(cx, obj, receiver, atom->asPropertyName(), vp);
+    return array_getProperty(cx, obj, receiver, RootedVarPropertyName(cx, atom->asPropertyName()), vp);
 }
 
 static JSBool
-slowarray_addProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp)
+slowarray_addProperty(JSContext *cx, HandleObject obj, HandleId id, Value *vp)
 {
     uint32_t index, length;
 
     if (!js_IdIsIndex(id, &index))
         return JS_TRUE;
     length = obj->getArrayLength();
     if (index >= length)
         obj->setArrayLength(cx, index + 1);
     return JS_TRUE;
 }
 
 static JSType
-array_typeOf(JSContext *cx, JSObject *obj)
+array_typeOf(JSContext *cx, HandleObject obj)
 {
     return JSTYPE_OBJECT;
 }
 
 static JSBool
-array_setGeneric(JSContext *cx, JSObject *obj_, jsid id_, Value *vp, JSBool strict)
+array_setGeneric(JSContext *cx, HandleObject obj, HandleId id, Value *vp, JSBool strict)
 {
-    RootedVarObject obj(cx, obj_);
-    RootedVarId id(cx, id_);
-
     if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom))
         return array_length_setter(cx, obj, id, strict, vp);
 
     if (!obj->isDenseArray())
-        return js_SetPropertyHelper(cx, obj, id, 0, vp, strict);
+        return baseops::SetPropertyHelper(cx, obj, id, 0, vp, strict);
 
     do {
         uint32_t i;
         if (!js_IdIsIndex(id, &i))
             break;
         if (js_PrototypeHasIndexedProperties(cx, obj))
             break;
 
@@ -945,36 +926,34 @@ array_setGeneric(JSContext *cx, JSObject
         if (i >= obj->getArrayLength())
             obj->setDenseArrayLength(i + 1);
         obj->setDenseArrayElementWithType(cx, i, *vp);
         return true;
     } while (false);
 
     if (!JSObject::makeDenseArraySlow(cx, obj))
         return false;
-    return js_SetPropertyHelper(cx, obj, id, 0, vp, strict);
-}
-
-static JSBool
-array_setProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict)
-{
-    return array_setGeneric(cx, obj, NameToId(name), vp, strict);
+    return baseops::SetPropertyHelper(cx, obj, id, 0, vp, strict);
 }
 
 static JSBool
-array_setElement(JSContext *cx, JSObject *obj_, uint32_t index, Value *vp, JSBool strict)
+array_setProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, Value *vp, JSBool strict)
 {
-    RootedVarObject obj(cx, obj_);
-
-    jsid id;
-    if (!IndexToId(cx, index, &id))
+    return array_setGeneric(cx, obj, RootedVarId(cx, NameToId(name)), vp, strict);
+}
+
+static JSBool
+array_setElement(JSContext *cx, HandleObject obj, uint32_t index, Value *vp, JSBool strict)
+{
+    RootedVarId id(cx);
+    if (!IndexToId(cx, index, id.address()))
         return false;
 
     if (!obj->isDenseArray())
-        return js_SetPropertyHelper(cx, obj, id, 0, vp, strict);
+        return baseops::SetPropertyHelper(cx, obj, id, 0, vp, strict);
 
     do {
         /*
          * UINT32_MAX is not an array index and must not affect the length
          * property, so specifically reject it.
          */
         if (index == UINT32_MAX)
             break;
@@ -992,23 +971,23 @@ array_setElement(JSContext *cx, JSObject
         if (index >= obj->getArrayLength())
             obj->setDenseArrayLength(index + 1);
         obj->setDenseArrayElementWithType(cx, index, *vp);
         return true;
     } while (false);
 
     if (!JSObject::makeDenseArraySlow(cx, obj))
         return false;
-    return js_SetPropertyHelper(cx, obj, id, 0, vp, strict);
+    return baseops::SetPropertyHelper(cx, obj, id, 0, vp, strict);
 }
 
 static JSBool
-array_setSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict)
+array_setSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, Value *vp, JSBool strict)
 {
-    return array_setGeneric(cx, obj, SPECIALID_TO_JSID(sid), vp, strict);
+    return array_setGeneric(cx, obj, RootedVarId(cx, SPECIALID_TO_JSID(sid)), vp, strict);
 }
 
 JSBool
 js_PrototypeHasIndexedProperties(JSContext *cx, JSObject *obj)
 {
     /*
      * Walk up the prototype chain and see if this indexed element already
      * exists. If we hit the end of the prototype chain, it's safe to set the
@@ -1024,26 +1003,24 @@ js_PrototypeHasIndexedProperties(JSConte
             return JS_TRUE;
         if (obj->isIndexed())
             return JS_TRUE;
     }
     return JS_FALSE;
 }
 
 static JSBool
-array_defineGeneric(JSContext *cx, JSObject *obj_, jsid id, const Value *value,
+array_defineGeneric(JSContext *cx, HandleObject obj, HandleId id, const Value *value,
                     JSPropertyOp getter, StrictPropertyOp setter, unsigned attrs)
 {
-    RootedVarObject obj(cx, obj_);
-
     if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom))
         return JS_TRUE;
 
     if (!obj->isDenseArray())
-        return js_DefineProperty(cx, obj, id, value, getter, setter, attrs);
+        return baseops::DefineProperty(cx, obj, id, value, getter, setter, attrs);
 
     do {
         uint32_t i = 0;       // init to shut GCC up
         bool isIndex = js_IdIsIndex(id, &i);
         if (!isIndex || attrs != JSPROP_ENUMERATE)
             break;
 
         JSObject::EnsureDenseResult result = obj->ensureDenseArrayElements(cx, i, 1);
@@ -1055,37 +1032,39 @@ array_defineGeneric(JSContext *cx, JSObj
         }
 
         if (i >= obj->getArrayLength())
             obj->setDenseArrayLength(i + 1);
         obj->setDenseArrayElementWithType(cx, i, *value);
         return true;
     } while (false);
 
+    RootGetterSetter gsRoot(cx, attrs, &getter, &setter);
+
     if (!JSObject::makeDenseArraySlow(cx, obj))
         return false;
-    return js_DefineProperty(cx, obj, id, value, getter, setter, attrs);
+    return baseops::DefineProperty(cx, obj, id, value, getter, setter, attrs);
 }
 
 static JSBool
-array_defineProperty(JSContext *cx, JSObject *obj, PropertyName *name, const Value *value,
+array_defineProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, const Value *value,
                      JSPropertyOp getter, StrictPropertyOp setter, unsigned attrs)
 {
-    return array_defineGeneric(cx, obj, NameToId(name), value, getter, setter, attrs);
+    return array_defineGeneric(cx, obj, RootedVarId(cx, NameToId(name)), value, getter, setter, attrs);
 }
 
 namespace js {
 
 /* non-static for direct definition of array elements within the engine */
 JSBool
-array_defineElement(JSContext *cx, JSObject *obj, uint32_t index, const Value *value,
+array_defineElement(JSContext *cx, HandleObject obj, uint32_t index, const Value *value,
                     PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
 {
     if (!obj->isDenseArray())
-        return js_DefineElement(cx, obj, index, value, getter, setter, attrs);
+        return baseops::DefineElement(cx, obj, index, value, getter, setter, attrs);
 
     do {
         /*
          * UINT32_MAX is not an array index and must not affect the length
          * property, so specifically reject it.
          */
         if (attrs != JSPROP_ENUMERATE || index == UINT32_MAX)
             break;
@@ -1099,136 +1078,136 @@ array_defineElement(JSContext *cx, JSObj
         }
 
         if (index >= obj->getArrayLength())
             obj->setDenseArrayLength(index + 1);
         obj->setDenseArrayElementWithType(cx, index, *value);
         return true;
     } while (false);
 
-    RootObject objRoot(cx, &obj);
     RootValue valueRoot(cx, value);
     RootGetterSetter gsRoot(cx, attrs, &getter, &setter);
 
-    if (!JSObject::makeDenseArraySlow(cx, objRoot))
+    if (!JSObject::makeDenseArraySlow(cx, obj))
         return false;
-    return js_DefineElement(cx, obj, index, value, getter, setter, attrs);
+    return baseops::DefineElement(cx, obj, index, value, getter, setter, attrs);
 }
 
 } // namespace js
 
 static JSBool
-array_defineSpecial(JSContext *cx, JSObject *obj, SpecialId sid, const Value *value,
+array_defineSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, const Value *value,
                     PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
 {
-    return array_defineGeneric(cx, obj, SPECIALID_TO_JSID(sid), value, getter, setter, attrs);
+    return array_defineGeneric(cx, obj, RootedVarId(cx, SPECIALID_TO_JSID(sid)),
+                               value, getter, setter, attrs);
 }
 
 static JSBool
-array_getGenericAttributes(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp)
+array_getGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp)
 {
     *attrsp = JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)
         ? JSPROP_PERMANENT : JSPROP_ENUMERATE;
     return true;
 }
 
 static JSBool
-array_getPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, unsigned *attrsp)
+array_getPropertyAttributes(JSContext *cx, HandleObject obj, HandlePropertyName name, unsigned *attrsp)
 {
     *attrsp = (name == cx->runtime->atomState.lengthAtom)
               ? JSPROP_PERMANENT
               : JSPROP_ENUMERATE;
     return true;
 }
 
 static JSBool
-array_getElementAttributes(JSContext *cx, JSObject *obj, uint32_t index, unsigned *attrsp)
+array_getElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp)
 {
     *attrsp = JSPROP_ENUMERATE;
     return true;
 }
 
 static JSBool
-array_getSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, unsigned *attrsp)
+array_getSpecialAttributes(JSContext *cx, HandleObject obj, HandleSpecialId sid, unsigned *attrsp)
 {
     *attrsp = JSPROP_ENUMERATE;
     return true;
 }
 
 static JSBool
-array_setGenericAttributes(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp)
+array_setGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp)
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_SET_ARRAY_ATTRS);
     return false;
 }
 
 static JSBool
-array_setPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, unsigned *attrsp)
+array_setPropertyAttributes(JSContext *cx, HandleObject obj, HandlePropertyName name, unsigned *attrsp)
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_SET_ARRAY_ATTRS);
     return false;
 }
 
 static JSBool
-array_setElementAttributes(JSContext *cx, JSObject *obj, uint32_t index, unsigned *attrsp)
+array_setElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp)
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_SET_ARRAY_ATTRS);
     return false;
 }
 
 static JSBool
-array_setSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, unsigned *attrsp)
+array_setSpecialAttributes(JSContext *cx, HandleObject obj, HandleSpecialId sid, unsigned *attrsp)
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_SET_ARRAY_ATTRS);
     return false;
 }
 
 static JSBool
-array_deleteProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *rval, JSBool strict)
+array_deleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, Value *rval, JSBool strict)
 {
     if (!obj->isDenseArray())
-        return js_DeleteProperty(cx, obj, name, rval, strict);
+        return baseops::DeleteProperty(cx, obj, name, rval, strict);
 
     if (name == cx->runtime->atomState.lengthAtom) {
         rval->setBoolean(false);
         return true;
     }
 
     rval->setBoolean(true);
     return true;
 }
 
 namespace js {
 
 /* non-static for direct deletion of array elements within the engine */
 JSBool
-array_deleteElement(JSContext *cx, JSObject *obj, uint32_t index, Value *rval, JSBool strict)
+array_deleteElement(JSContext *cx, HandleObject obj, uint32_t index, Value *rval, JSBool strict)
 {
     if (!obj->isDenseArray())
-        return js_DeleteElement(cx, obj, index, rval, strict);
+        return baseops::DeleteElement(cx, obj, index, rval, strict);
 
     if (index < obj->getDenseArrayInitializedLength()) {
         obj->markDenseArrayNotPacked(cx);
         obj->setDenseArrayElement(index, MagicValue(JS_ARRAY_HOLE));
     }
 
     if (!js_SuppressDeletedElement(cx, RootedVarObject(cx, obj), index))
         return false;
 
     rval->setBoolean(true);
     return true;
 }
 
 } // namespace js
 
 static JSBool
-array_deleteSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *rval, JSBool strict)
+array_deleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, Value *rval, JSBool strict)
 {
     if (!obj->isDenseArray())
-        return js_DeleteSpecial(cx, obj, sid, rval, strict);
+        return baseops::DeleteSpecial(cx, obj, sid, rval, strict);
 
     rval->setBoolean(true);
     return true;
 }
 
 static void
 array_trace(JSTracer *trc, JSObject *obj)
 {
@@ -1344,17 +1323,17 @@ AddLengthProperty(JSContext *cx, JSObjec
 {
     /*
      * 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.
      */
 
-    const jsid lengthId = NameToId(cx->runtime->atomState.lengthAtom);
+    RootedVarId lengthId(cx, NameToId(cx->runtime->atomState.lengthAtom));
     JS_ASSERT(!obj->nativeLookup(cx, lengthId));
 
     if (!obj->allocateSlowArrayElements(cx))
         return false;
 
     return obj->addProperty(cx, lengthId, array_length_getter, array_length_setter,
                             SHAPE_INVALID_SLOT, JSPROP_PERMANENT | JSPROP_SHARED, 0, 0);
 }
@@ -1680,17 +1659,17 @@ array_toString_sub(JSContext *cx, Handle
             if (!GetElement(cx, obj, index, &hole, &elt))
                 return false;
 
             if (!hole && !elt.isNullOrUndefined()) {
                 if (locale) {
                     JSObject *robj = ToObject(cx, &elt);
                     if (!robj)
                         return false;
-                    jsid id = NameToId(cx->runtime->atomState.toLocaleStringAtom);
+                    RootedVarId id(cx, NameToId(cx->runtime->atomState.toLocaleStringAtom));
                     if (!robj->callMethod(cx, id, 0, NULL, &elt))
                         return false;
                 }
                 if (!ValueToStringBuffer(cx, elt, sb))
                     return false;
             }
 
             if (index + 1 != length) {
@@ -2425,42 +2404,42 @@ array_push1_dense(JSContext* cx, HandleO
 
     obj->setDenseArrayLength(length + 1);
     obj->setDenseArrayElementWithType(cx, length, args[0]);
     args.rval().setNumber(obj->getArrayLength());
     return true;
 }
 
 JS_ALWAYS_INLINE JSBool
-NewbornArrayPushImpl(JSContext *cx, JSObject *obj, const Value &v)
+NewbornArrayPushImpl(JSContext *cx, HandleObject obj, const Value &v)
 {
     JS_ASSERT(!v.isMagic());
 
     uint32_t length = obj->getArrayLength();
     if (obj->isSlowArray()) {
         /* This can happen in one evil case. See bug 630377. */
-        jsid id;
-        return IndexToId(cx, length, &id) &&
-               js_DefineProperty(cx, obj, id, &v, NULL, NULL, JSPROP_ENUMERATE);
+        RootedVarId id(cx);
+        return IndexToId(cx, length, id.address()) &&
+               baseops::DefineProperty(cx, obj, id, &v, NULL, NULL, JSPROP_ENUMERATE);
     }
 
     JS_ASSERT(obj->isDenseArray());
     JS_ASSERT(length <= obj->getDenseArrayCapacity());
 
     if (!obj->ensureElements(cx, length + 1))
         return false;
 
     obj->setDenseArrayInitializedLength(length + 1);
     obj->setDenseArrayLength(length + 1);
     obj->initDenseArrayElementWithType(cx, length, v);
     return true;
 }
 
 JSBool
-js_NewbornArrayPush(JSContext *cx, JSObject *obj, const Value &vp)
+js_NewbornArrayPush(JSContext *cx, HandleObject obj, const Value &vp)
 {
     return NewbornArrayPushImpl(cx, obj, vp);
 }
 
 JSBool
 js::array_push(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
--- a/js/src/jsarray.h
+++ b/js/src/jsarray.h
@@ -118,21 +118,21 @@ extern JSBool
 js_GetLengthProperty(JSContext *cx, JSObject *obj, uint32_t *lengthp);
 
 extern JSBool
 js_SetLengthProperty(JSContext *cx, JSObject *obj, double length);
 
 namespace js {
 
 extern JSBool
-array_defineElement(JSContext *cx, JSObject *obj, uint32_t index, const Value *value,
+array_defineElement(JSContext *cx, HandleObject obj, uint32_t index, const Value *value,
                     PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
 
 extern JSBool
-array_deleteElement(JSContext *cx, JSObject *obj, uint32_t index, Value *rval, JSBool strict);
+array_deleteElement(JSContext *cx, HandleObject obj, uint32_t index, Value *rval, JSBool strict);
 
 /*
  * Copy 'length' elements from aobj to vp.
  *
  * This function assumes 'length' is effectively the result of calling
  * js_GetLengthProperty on aobj.
  */
 extern bool
@@ -165,17 +165,17 @@ js_ArrayInfo(JSContext *cx, unsigned arg
 /*
  * Append the given (non-hole) value to the end of an array.  The array must be
  * a newborn array -- that is, one which has not been exposed to script for
  * arbitrary manipulation.  (This method optimizes on the assumption that
  * extending the array to accommodate the element will never make the array
  * sparse, which requires that the array be completely filled.)
  */
 extern JSBool
-js_NewbornArrayPush(JSContext *cx, JSObject *obj, const js::Value &v);
+js_NewbornArrayPush(JSContext *cx, js::HandleObject obj, const js::Value &v);
 
 JSBool
 js_PrototypeHasIndexedProperties(JSContext *cx, JSObject *obj);
 
 /*
  * Utility to access the value from the id returned by array_lookupProperty.
  */
 JSBool
--- a/js/src/jsclass.h
+++ b/js/src/jsclass.h
@@ -169,83 +169,85 @@ JSID_TO_SPECIALID(jsid id)
     if (JSID_IS_EMPTY(id))
         return SpecialId::empty();
     if (JSID_IS_VOID(id))
         return SpecialId::voidId();
     JS_ASSERT(JSID_IS_DEFAULT_XML_NAMESPACE(id));
     return SpecialId::defaultXMLNamespace();
 }
 
+typedef JS::Handle<SpecialId> HandleSpecialId;
+
 /* js::Class operation signatures. */
 
 typedef JSBool
-(* LookupGenericOp)(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
+(* LookupGenericOp)(JSContext *cx, HandleObject obj, HandleId id, JSObject **objp,
                     JSProperty **propp);
 typedef JSBool
-(* LookupPropOp)(JSContext *cx, JSObject *obj, PropertyName *name, JSObject **objp,
+(* LookupPropOp)(JSContext *cx, HandleObject obj, HandlePropertyName name, JSObject **objp,
                  JSProperty **propp);
 typedef JSBool
-(* LookupElementOp)(JSContext *cx, JSObject *obj, uint32_t index, JSObject **objp,
+(* LookupElementOp)(JSContext *cx, HandleObject obj, uint32_t index, JSObject **objp,
                     JSProperty **propp);
 typedef JSBool
-(* LookupSpecialOp)(JSContext *cx, JSObject *obj, SpecialId sid, JSObject **objp,
+(* LookupSpecialOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, JSObject **objp,
                     JSProperty **propp);
 typedef JSBool
-(* DefineGenericOp)(JSContext *cx, JSObject *obj, jsid id, const Value *value,
+(* DefineGenericOp)(JSContext *cx, HandleObject obj, HandleId id, const Value *value,
                     PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
 typedef JSBool
-(* DefinePropOp)(JSContext *cx, JSObject *obj, PropertyName *name, const Value *value,
+(* DefinePropOp)(JSContext *cx, HandleObject obj, HandlePropertyName name, const Value *value,
                  PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
 typedef JSBool
-(* DefineElementOp)(JSContext *cx, JSObject *obj, uint32_t index, const Value *value,
+(* DefineElementOp)(JSContext *cx, HandleObject obj, uint32_t index, const Value *value,
                     PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
 typedef JSBool
-(* DefineSpecialOp)(JSContext *cx, JSObject *obj, SpecialId sid, const Value *value,
+(* DefineSpecialOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, const Value *value,
                     PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
 typedef JSBool
-(* GenericIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp);
+(* GenericIdOp)(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id, Value *vp);
 typedef JSBool
-(* PropertyIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, PropertyName *name, Value *vp);
+(* PropertyIdOp)(JSContext *cx, HandleObject obj, HandleObject receiver, HandlePropertyName name, Value *vp);
 typedef JSBool
-(* ElementIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t index, Value *vp);
+(* ElementIdOp)(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index, Value *vp);
 typedef JSBool
-(* ElementIfPresentOp)(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t index, Value *vp, bool* present);
+(* ElementIfPresentOp)(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index, Value *vp, bool* present);
 typedef JSBool
-(* SpecialIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid, Value *vp);
+(* SpecialIdOp)(JSContext *cx, HandleObject obj, HandleObject receiver, HandleSpecialId sid, Value *vp);
 typedef JSBool
-(* StrictGenericIdOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict);
+(* StrictGenericIdOp)(JSContext *cx, HandleObject obj, HandleId id, Value *vp, JSBool strict);
 typedef JSBool
-(* StrictPropertyIdOp)(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict);
+(* StrictPropertyIdOp)(JSContext *cx, HandleObject obj, HandlePropertyName name, Value *vp, JSBool strict);
 typedef JSBool
-(* StrictElementIdOp)(JSContext *cx, JSObject *obj, uint32_t index, Value *vp, JSBool strict);
+(* StrictElementIdOp)(JSContext *cx, HandleObject obj, uint32_t index, Value *vp, JSBool strict);
 typedef JSBool
-(* StrictSpecialIdOp)(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict);
+(* StrictSpecialIdOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, Value *vp, JSBool strict);
 typedef JSBool
-(* GenericAttributesOp)(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp);
+(* GenericAttributesOp)(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp);
 typedef JSBool
-(* PropertyAttributesOp)(JSContext *cx, JSObject *obj, PropertyName *name, unsigned *attrsp);
+(* PropertyAttributesOp)(JSContext *cx, HandleObject obj, HandlePropertyName name, unsigned *attrsp);
 typedef JSBool
-(* ElementAttributesOp)(JSContext *cx, JSObject *obj, uint32_t index, unsigned *attrsp);
+(* ElementAttributesOp)(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp);
 typedef JSBool
-(* SpecialAttributesOp)(JSContext *cx, JSObject *obj, SpecialId sid, unsigned *attrsp);
+(* SpecialAttributesOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, unsigned *attrsp);
 typedef JSBool
-(* DeletePropertyOp)(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict);
+(* DeletePropertyOp)(JSContext *cx, HandleObject obj, HandlePropertyName name, Value *vp, JSBool strict);
 typedef JSBool
-(* DeleteElementOp)(JSContext *cx, JSObject *obj, uint32_t index, Value *vp, JSBool strict);
+(* DeleteElementOp)(JSContext *cx, HandleObject obj, uint32_t index, Value *vp, JSBool strict);
 typedef JSBool
-(* DeleteSpecialOp)(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict);
+(* DeleteSpecialOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, Value *vp, JSBool strict);
 typedef JSType
-(* TypeOfOp)(JSContext *cx, JSObject *obj);
+(* TypeOfOp)(JSContext *cx, HandleObject obj);
 
 typedef JSObject *
-(* ObjectOp)(JSContext *cx, JSObject *obj);
+(* ObjectOp)(JSContext *cx, HandleObject obj);
+typedef void
+(* ClearOp)(JSContext *cx, HandleObject obj);
 typedef void
 (* FinalizeOp)(FreeOp *fop, JSObject *obj);
-typedef void
-(* ClearOp)(JSContext *cx, JSObject *obj);
 
 #define JS_CLASS_MEMBERS                                                      \
     const char          *name;                                                \
     uint32_t            flags;                                                \
                                                                               \
     /* Mandatory non-null function pointer members. */                        \
     JSPropertyOp        addProperty;                                          \
     JSPropertyOp        delProperty;                                          \
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -1060,29 +1060,29 @@ JSContext::~JSContext()
     }
 
     JS_ASSERT(!resolvingList);
 }
 
 void
 JSContext::resetCompartment()
 {
-    JSObject *scopeobj;
+    RootedVarObject scopeobj(this);
     if (stack.hasfp()) {
         scopeobj = fp()->scopeChain();
     } else {
         scopeobj = globalObject;
         if (!scopeobj)
             goto error;
 
         /*
          * Innerize. Assert, but check anyway, that this succeeds. (It
          * can only fail due to bugs in the engine or embedding.)
          */
-        OBJ_TO_INNER_OBJECT(this, scopeobj);
+        scopeobj = GetInnerObject(this, scopeobj);
         if (!scopeobj)
             goto error;
     }
 
     compartment = scopeobj->compartment();
     inferenceEnabled = compartment->types.inferenceEnabled;
 
     if (isExceptionPending())
--- a/js/src/jscntxtinlines.h
+++ b/js/src/jscntxtinlines.h
@@ -358,59 +358,59 @@ class CompartmentChecker
  * depends on other objects not having been swept yet.
  */
 #define START_ASSERT_SAME_COMPARTMENT()                                       \
     if (cx->runtime->gcRunning)                                               \
         return;                                                               \
     CompartmentChecker c(cx)
 
 template <class T1> inline void
-assertSameCompartment(JSContext *cx, T1 t1)
+assertSameCompartment(JSContext *cx, const T1 &t1)
 {
 #ifdef DEBUG
     START_ASSERT_SAME_COMPARTMENT();
     c.check(t1);
 #endif
 }
 
 template <class T1, class T2> inline void
-assertSameCompartment(JSContext *cx, T1 t1, T2 t2)
+assertSameCompartment(JSContext *cx, const T1 &t1, const T2 &t2)
 {
 #ifdef DEBUG
     START_ASSERT_SAME_COMPARTMENT();
     c.check(t1);
     c.check(t2);
 #endif
 }
 
 template <class T1, class T2, class T3> inline void
-assertSameCompartment(JSContext *cx, T1 t1, T2 t2, T3 t3)
+assertSameCompartment(JSContext *cx, const T1 &t1, const T2 &t2, const T3 &t3)
 {
 #ifdef DEBUG
     START_ASSERT_SAME_COMPARTMENT();
     c.check(t1);
     c.check(t2);
     c.check(t3);
 #endif
 }
 
 template <class T1, class T2, class T3, class T4> inline void
-assertSameCompartment(JSContext *cx, T1 t1, T2 t2, T3 t3, T4 t4)
+assertSameCompartment(JSContext *cx, const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4)
 {
 #ifdef DEBUG
     START_ASSERT_SAME_COMPARTMENT();
     c.check(t1);
     c.check(t2);
     c.check(t3);
     c.check(t4);
 #endif
 }
 
 template <class T1, class T2, class T3, class T4, class T5> inline void
-assertSameCompartment(JSContext *cx, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
+assertSameCompartment(JSContext *cx, const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4, const T5 &t5)
 {
 #ifdef DEBUG
     START_ASSERT_SAME_COMPARTMENT();
     c.check(t1);
     c.check(t2);
     c.check(t3);
     c.check(t4);
     c.check(t5);
@@ -468,46 +468,49 @@ CallJSNativeConstructor(JSContext *cx, N
                  native != js::CallOrConstructBoundFunction &&
                  (!callee->isFunction() || callee->toFunction()->native() != js_Object),
                  !args.rval().isPrimitive() && callee != &args.rval().toObject());
 
     return true;
 }
 
 JS_ALWAYS_INLINE bool
-CallJSPropertyOp(JSContext *cx, PropertyOp op, JSObject *receiver, jsid id, Value *vp)
+CallJSPropertyOp(JSContext *cx, PropertyOp op, HandleObject receiver, HandleId id, Value *vp)
 {
     assertSameCompartment(cx, receiver, id, *vp);
     JSBool ok = op(cx, receiver, id, vp);
     if (ok)
         assertSameCompartment(cx, *vp);
     return ok;
 }
 
 JS_ALWAYS_INLINE bool
-CallJSPropertyOpSetter(JSContext *cx, StrictPropertyOp op, JSObject *obj, jsid id,
+CallJSPropertyOpSetter(JSContext *cx, StrictPropertyOp op, HandleObject obj, HandleId id,
                        JSBool strict, Value *vp)
 {
     assertSameCompartment(cx, obj, id, *vp);
     return op(cx, obj, id, strict, vp);
 }
 
 inline bool
-CallSetter(JSContext *cx, JSObject *obj, jsid id, StrictPropertyOp op, unsigned attrs,
+CallSetter(JSContext *cx, HandleObject obj, HandleId id, StrictPropertyOp op, unsigned attrs,
            unsigned shortid, JSBool strict, Value *vp)
 {
     if (attrs & JSPROP_SETTER)
         return InvokeGetterOrSetter(cx, obj, CastAsObjectJsval(op), 1, vp, vp);
 
     if (attrs & JSPROP_GETTER)
         return js_ReportGetterOnlyAssignment(cx);
 
-    if (attrs & JSPROP_SHORTID)
-        id = INT_TO_JSID(shortid);
-    return CallJSPropertyOpSetter(cx, op, obj, id, strict, vp);
+    if (!(attrs & JSPROP_SHORTID))
+        return CallJSPropertyOpSetter(cx, op, obj, id, strict, vp);
+
+    RootedVarId nid(cx, INT_TO_JSID(shortid));
+
+    return CallJSPropertyOpSetter(cx, op, obj, nid, strict, vp);
 }
 
 static inline HeapPtrAtom *
 FrameAtomBase(JSContext *cx, js::StackFrame *fp)
 {
     return fp->script()->atoms;
 }
 
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -212,18 +212,17 @@ JSCompartment::wrap(JSContext *cx, Value
         }
 
         if (obj->compartment() == this)
             return WrapForSameCompartment(cx, obj, vp);
         vp->setObject(*obj);
 
 #ifdef DEBUG
         {
-            JSObject *outer = obj;
-            OBJ_TO_OUTER_OBJECT(cx, outer);
+            JSObject *outer = GetOuterObject(cx, RootedVarObject(cx, obj));
             JS_ASSERT(outer && outer == obj);
         }
 #endif
     }
 
     /* If we already have a wrapper for this value, use it. */
     if (WrapperMap::Ptr p = crossCompartmentWrappers.lookup(*vp)) {
         *vp = p->value;
--- a/js/src/jsdate.cpp
+++ b/js/src/jsdate.cpp
@@ -494,23 +494,22 @@ msFromTime(double t)
     return result;
 }
 
 /**
  * end of ECMA 'support' functions
  */
 
 static JSBool
-date_convert(JSContext *cx, JSObject *obj, JSType hint, Value *vp)
+date_convert(JSContext *cx, HandleObject obj, JSType hint, Value *vp)
 {
     JS_ASSERT(hint == JSTYPE_NUMBER || hint == JSTYPE_STRING || hint == JSTYPE_VOID);
     JS_ASSERT(obj->isDate());
 
-    return DefaultValue(cx, RootedVarObject(cx, obj),
-                        (hint == JSTYPE_VOID) ? JSTYPE_STRING : hint, vp);
+    return DefaultValue(cx, obj, (hint == JSTYPE_VOID) ? JSTYPE_STRING : hint, vp);
 }
 
 /*
  * Other Support routines and definitions
  */
 
 Class js::DateClass = {
     js_Date_str,
@@ -2688,21 +2687,21 @@ js_InitDateClass(JSContext *cx, JSObject
     /*
      * Define all Date.prototype.* functions, then brand for trace-jitted code.
      * Date.prototype.toGMTString has the same initial value as
      * Date.prototype.toUTCString.
      */
     if (!JS_DefineFunctions(cx, dateProto, date_methods))
         return NULL;
     Value toUTCStringFun;
-    jsid toUTCStringId = NameToId(cx->runtime->atomState.toUTCStringAtom);
-    jsid toGMTStringId = NameToId(cx->runtime->atomState.toGMTStringAtom);
-    if (!js_GetProperty(cx, dateProto, toUTCStringId, &toUTCStringFun) ||
-        !js_DefineProperty(cx, dateProto, toGMTStringId, &toUTCStringFun,
-                           JS_PropertyStub, JS_StrictPropertyStub, 0))
+    RootedVarId toUTCStringId(cx, NameToId(cx->runtime->atomState.toUTCStringAtom));
+    RootedVarId toGMTStringId(cx, NameToId(cx->runtime->atomState.toGMTStringAtom));
+    if (!baseops::GetProperty(cx, dateProto, toUTCStringId, &toUTCStringFun) ||
+        !baseops::DefineProperty(cx, dateProto, toGMTStringId, &toUTCStringFun,
+                                 JS_PropertyStub, JS_StrictPropertyStub, 0))
     {
         return NULL;
     }
 
     if (!DefineConstructorAndPrototype(cx, global, JSProto_Date, ctor, dateProto))
         return NULL;
 
     return dateProto;
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -277,25 +277,24 @@ JS_ClearInterrupt(JSRuntime *rt, JSInter
 JS_PUBLIC_API(JSBool)
 JS_SetWatchPoint(JSContext *cx, JSObject *obj_, jsid id,
                  JSWatchPointHandler handler, JSObject *closure_)
 {
     assertSameCompartment(cx, obj_);
 
     RootedVarObject obj(cx, obj_), closure(cx, closure_);
 
-    JSObject *origobj;
+    JSObject *origobj = obj;
+    obj = GetInnerObject(cx, obj);
+    if (!obj)
+        return false;
+
     Value v;
     unsigned attrs;
 
-    origobj = obj;
-    OBJ_TO_INNER_OBJECT(cx, obj.reference());
-    if (!obj)
-        return false;
-
     RootedVarId propid(cx);
 
     if (JSID_IS_INT(id)) {
         propid = id;
     } else if (JSID_IS_OBJECT(id)) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_WATCH_PROP);
         return false;
     } else {
@@ -816,17 +815,17 @@ GetPropertyDesc(JSContext *cx, JSObject 
     RootedVarObject obj(cx, obj_);
 
     JSBool wasThrowing = cx->isExceptionPending();
     Value lastException = UndefinedValue();
     if (wasThrowing)
         lastException = cx->getPendingException();
     cx->clearPendingException();
 
-    if (!js_GetProperty(cx, obj, shape->propid(), &pd->value)) {
+    if (!baseops::GetProperty(cx, obj, RootedVarId(cx, shape->propid()), &pd->value)) {
         if (!cx->isExceptionPending()) {
             pd->flags = JSPD_ERROR;
             pd->value = JSVAL_VOID;
         } else {
             pd->flags = JSPD_EXCEPTION;
             pd->value = cx->getPendingException();
         }
     } else {
@@ -850,18 +849,20 @@ GetPropertyDesc(JSContext *cx, JSObject 
         pd->slot = 0;
     }
     pd->alias = JSVAL_VOID;
 
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda)
+JS_GetPropertyDescArray(JSContext *cx, JSObject *obj_, JSPropertyDescArray *pda)
 {
+    RootedVarObject obj(cx, obj_);
+
     assertSameCompartment(cx, obj);
     uint32_t i = 0;
     JSPropertyDesc *pd = NULL;
 
     if (obj->isDebugScope()) {
         AutoIdVector props(cx);
         if (!Proxy::enumerate(cx, obj, props))
             return false;
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -84,17 +84,17 @@ Exception(JSContext *cx, unsigned argc, 
 
 static void
 exn_trace(JSTracer *trc, JSObject *obj);
 
 static void
 exn_finalize(FreeOp *fop, JSObject *obj);
 
 static JSBool
-exn_resolve(JSContext *cx, JSObject *obj, jsid id, unsigned flags,
+exn_resolve(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
             JSObject **objp);
 
 Class js::ErrorClass = {
     js_Error_str,
     JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_NEW_RESOLVE |
     JSCLASS_HAS_CACHED_PROTO(JSProto_Error),
     JS_PropertyStub,         /* addProperty */
     JS_PropertyStub,         /* delProperty */
@@ -296,18 +296,18 @@ InitExnPrivate(JSContext *cx, HandleObje
             StackFrame *fp = i.fp();
 
             /*
              * Ask the crystal CAPS ball whether we can see across compartments.
              * NB: this means 'fp' may point to cross-compartment frames.
              */
             if (checkAccess && i.isNonEvalFunctionFrame()) {
                 Value v = NullValue();
-                jsid callerid = NameToId(cx->runtime->atomState.callerAtom);
-                if (!checkAccess(cx, i.callee(), callerid, JSACC_READ, &v))
+                RootedVarId callerid(cx, NameToId(cx->runtime->atomState.callerAtom));
+                if (!checkAccess(cx, RootedVarObject(cx, i.callee()), callerid, JSACC_READ, &v))
                     break;
             }
 
             if (!frames.growBy(1))
                 return false;
             JSStackTraceStackElem &frame = frames.back();
             if (i.isNonEvalFunctionFrame())
                 frame.funName = fp->fun()->atom ? fp->fun()->atom : cx->runtime->emptyString;
@@ -413,29 +413,27 @@ exn_finalize(FreeOp *fop, JSObject *obj)
                 JS_DropPrincipals(fop->runtime(), prin);
             fop->free_(report);
         }
         fop->free_(priv);
     }
 }
 
 static JSBool
-exn_resolve(JSContext *cx, JSObject *obj_, jsid id, unsigned flags,
+exn_resolve(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
             JSObject **objp)
 {
     JSExnPrivate *priv;
     JSString *str;
     JSAtom *atom;
     JSString *stack;
     const char *prop;
     jsval v;
     unsigned attrs;
 
-    RootedVarObject obj(cx, obj_);
-
     *objp = NULL;
     priv = GetExnPrivate(obj);
     if (priv && JSID_IS_ATOM(id)) {
         str = JSID_TO_STRING(id);
 
         atom = cx->runtime->atomState.messageAtom;
         if (str == atom) {
             prop = js_message_str;
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -64,18 +64,20 @@ JS_SetGrayGCRootsTracer(JSRuntime *rt, J
 JS_FRIEND_API(JSString *)
 JS_GetAnonymousString(JSRuntime *rt)
 {
     JS_ASSERT(rt->hasContexts());
     return rt->atomState.anonymousAtom;
 }
 
 JS_FRIEND_API(JSObject *)
-JS_FindCompilationScope(JSContext *cx, JSObject *obj)
+JS_FindCompilationScope(JSContext *cx, JSObject *obj_)
 {
+    RootedVarObject obj(cx, obj_);
+
     /*
      * We unwrap wrappers here. This is a little weird, but it's what's being
      * asked of us.
      */
     if (obj->isWrapper())
         obj = UnwrapObject(obj);
 
     /*
@@ -225,17 +227,17 @@ JS_DefineFunctionsWithHelp(JSContext *cx
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     for (; fs->name; fs++) {
         JSAtom *atom = js_Atomize(cx, fs->name, strlen(fs->name));
         if (!atom)
             return false;
 
         RootedVarFunction fun(cx);
-        fun = js_DefineFunction(cx, objRoot, AtomToId(atom),
+        fun = js_DefineFunction(cx, objRoot, RootedVarId(cx, AtomToId(atom)),
                                 fs->call, fs->nargs, fs->flags);
         if (!fun)
             return false;
 
         if (fs->usage) {
             if (!DefineHelpProperty(cx, fun, "usage", fs->usage))
                 return false;
         }
@@ -332,17 +334,17 @@ js::DefineFunctionWithReserved(JSContext
     RootObject objRoot(cx, &obj);
 
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     JSAtom *atom = js_Atomize(cx, name, strlen(name));
     if (!atom)
         return NULL;
-    return js_DefineFunction(cx, objRoot, AtomToId(atom),
+    return js_DefineFunction(cx, objRoot, RootedVarId(cx, AtomToId(atom)),
                              call, nargs, attrs,
                              JSFunction::ExtendedFinalizeKind);
 }
 
 JS_FRIEND_API(JSFunction *)
 js::NewFunctionWithReserved(JSContext *cx, JSNative native, unsigned nargs, unsigned flags,
                             JSObject *parent, const char *name)
 {
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -124,17 +124,17 @@ JS_ObjectToInnerObject(JSContext *cx, JS
 /* Requires obj != NULL. */
 extern JS_FRIEND_API(JSObject *)
 JS_ObjectToOuterObject(JSContext *cx, JSObject *obj);
 
 extern JS_FRIEND_API(JSObject *)
 JS_CloneObject(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent);
 
 extern JS_FRIEND_API(JSBool)
-js_GetterOnlyPropertyStub(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp);
+js_GetterOnlyPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, jsval *vp);
 
 JS_FRIEND_API(void)
 js_ReportOverRecursed(JSContext *maybecx);
 
 #ifdef DEBUG
 
 /*
  * Routines to print out values during debugging.  These are FRIEND_API to help
@@ -159,17 +159,17 @@ js_DumpChars(const jschar *s, size_t n);
 
 extern JS_FRIEND_API(bool)
 JS_CopyPropertiesFrom(JSContext *cx, JSObject *target, JSObject *obj);
 
 extern JS_FRIEND_API(JSBool)
 JS_WrapPropertyDescriptor(JSContext *cx, js::PropertyDescriptor *desc);
 
 extern JS_FRIEND_API(JSBool)
-JS_EnumerateState(JSContext *cx, JSObject *obj, JSIterateOp enum_op, js::Value *statep, jsid *idp);
+JS_EnumerateState(JSContext *cx, JSHandleObject obj, JSIterateOp enum_op, js::Value *statep, jsid *idp);
 
 struct JSFunctionSpecWithHelp {
     const char      *name;
     JSNative        call;
     uint16_t        nargs;
     uint16_t        flags;
     const char      *usage;
     const char      *help;
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -92,18 +92,19 @@
 #include "vm/Stack-inl.h"
 
 using namespace mozilla;
 using namespace js;
 using namespace js::gc;
 using namespace js::types;
 
 static JSBool
-fun_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp)
+fun_getProperty(JSContext *cx, HandleObject obj_, HandleId id, Value *vp)
 {
+    JSObject *obj = obj_;
     while (!obj->isFunction()) {
         obj = obj->getProto();
         if (!obj)
             return true;
     }
     JSFunction *fun = obj->toFunction();
 
     /*
@@ -203,23 +204,21 @@ fun_getProperty(JSContext *cx, JSObject 
 /* NB: no sentinels at ends -- use ArrayLength to bound loops.
  * Properties censored into [[ThrowTypeError]] in strict mode. */
 static const uint16_t poisonPillProps[] = {
     NAME_OFFSET(arguments),
     NAME_OFFSET(caller),
 };
 
 static JSBool
-fun_enumerate(JSContext *cx, JSObject *obj)
+fun_enumerate(JSContext *cx, HandleObject obj)
 {
     JS_ASSERT(obj->isFunction());
 
-    RootObject root(cx, &obj);
-
-    jsid id;
+    RootedVarId id(cx);
     bool found;
 
     if (!obj->isBoundFunction()) {
         id = NameToId(cx->runtime->atomState.classPrototypeAtom);
         if (!obj->hasProperty(cx, id, &found, JSRESOLVE_QUALIFIED))
             return false;
     }
 
@@ -283,17 +282,17 @@ ResolveInterpretedFunctionPrototype(JSCo
     {
        return NULL;
     }
 
     return proto;
 }
 
 static JSBool
-fun_resolve(JSContext *cx, JSObject *obj, jsid id, unsigned flags,
+fun_resolve(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
             JSObject **objp)
 {
     if (!JSID_IS_ATOM(id))
         return true;
 
     RootedVarFunction fun(cx);
     fun = obj->toFunction();
 
@@ -472,18 +471,20 @@ js::CloneInterpretedFunction(JSContext *
 }
 
 /*
  * [[HasInstance]] internal method for Function objects: fetch the .prototype
  * property of its 'this' parameter, and walks the prototype chain of v (only
  * if v is an object) returning true if .prototype is found.
  */
 static JSBool
-fun_hasInstance(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp)
+fun_hasInstance(JSContext *cx, HandleObject obj_, const Value *v, JSBool *bp)
 {
+    RootedVarObject obj(cx, obj_);
+
     while (obj->isFunction()) {
         if (!obj->isBoundFunction())
             break;
         obj = obj->toFunction()->getBoundFunctionTarget();
     }
 
     Value pval;
     if (!obj->getProperty(cx, cx->runtime->atomState.classPrototypeAtom, &pval))
@@ -1310,21 +1311,19 @@ js_CloneFunctionObject(JSContext *cx, Ha
             js_CallNewScriptHook(cx, clone->script(), clone);
             Debugger::onNewScript(cx, clone->script(), NULL);
         }
     }
     return clone;
 }
 
 JSFunction *
-js_DefineFunction(JSContext *cx, HandleObject obj, jsid id, Native native,
+js_DefineFunction(JSContext *cx, HandleObject obj, HandleId id, Native native,
                   unsigned nargs, unsigned attrs, AllocKind kind)
 {
-    RootId idRoot(cx, &id);
-
     PropertyOp gop;
     StrictPropertyOp sop;
 
     RootedVarFunction fun(cx);
 
     if (attrs & JSFUN_STUB_GSOPS) {
         /*
          * JSFUN_STUB_GSOPS is a request flag only, not stored in fun->flags or
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -241,17 +241,17 @@ js_NewFunction(JSContext *cx, JSObject *
                js::gc::AllocKind kind = JSFunction::FinalizeKind);
 
 extern JSFunction * JS_FASTCALL
 js_CloneFunctionObject(JSContext *cx, js::HandleFunction fun,
                        js::HandleObject parent, js::HandleObject proto,
                        js::gc::AllocKind kind = JSFunction::FinalizeKind);
 
 extern JSFunction *
-js_DefineFunction(JSContext *cx, js::HandleObject obj, jsid id, JSNative native,
+js_DefineFunction(JSContext *cx, js::HandleObject obj, js::HandleId id, JSNative native,
                   unsigned nargs, unsigned flags,
                   js::gc::AllocKind kind = JSFunction::FinalizeKind);
 
 /*
  * Flags for js_ValueToFunction and js_ReportIsNotFunction.
  */
 #define JSV2F_CONSTRUCT         INITIAL_CONSTRUCT
 #define JSV2F_SEARCH_STACK      0x10000
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -4388,20 +4388,20 @@ AnalyzeNewScriptProperties(JSContext *cx
         RootedVarObject obj(cx, *pbaseobj);
 
         if (op == JSOP_SETPROP && uses->u.which == 1) {
             /*
              * Don't use GetAtomId here, we need to watch for SETPROP on
              * integer properties and bail out. We can't mark the aggregate
              * JSID_VOID type property as being in a definite slot.
              */
-            jsid id = NameToId(script->getName(GET_UINT32_INDEX(pc)));
+            RootedVarId id(cx, NameToId(script->getName(GET_UINT32_INDEX(pc))));
             if (MakeTypeId(cx, id) != id)
                 return false;
-            if (id == id_prototype(cx) || id == id___proto__(cx) || id == id_constructor(cx))
+            if (id_prototype(cx) == id || id___proto__(cx) == id || id_constructor(cx) == id)
                 return false;
 
             /*
              * Ensure that if the properties named here could have a setter or
              * a permanent property in any transitive prototype, the definite
              * properties get cleared from the shape.
              */
             JSObject *parent = type->proto;
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -189,30 +189,30 @@ Class js_NoSuchMethodClass = {
  * call by name, and args is an Array containing this invocation's actual
  * parameters.
  */
 bool
 js::OnUnknownMethod(JSContext *cx, HandleObject obj, Value idval_, Value *vp)
 {
     RootedVarValue idval(cx, idval_);
 
-    jsid id = NameToId(cx->runtime->atomState.noSuchMethodAtom);
+    RootedVarId id(cx, NameToId(cx->runtime->atomState.noSuchMethodAtom));
     RootedVarValue value(cx);
-    if (!js_GetMethod(cx, obj, id, 0, value.address()))
+    if (!GetMethod(cx, obj, id, 0, value.address()))
         return false;
     TypeScript::MonitorUnknown(cx, cx->fp()->script(), cx->regs().pc);
 
     if (value.reference().isPrimitive()) {
         *vp = value;
     } else {
 #if JS_HAS_XML_SUPPORT
         /* Extract the function name from function::name qname. */
         if (idval.reference().isObject()) {
             JSObject *obj = &idval.reference().toObject();
-            if (js_GetLocalNameFromFunctionQName(obj, &id, cx))
+            if (js_GetLocalNameFromFunctionQName(obj, id.address(), cx))
                 idval = IdToValue(id);
         }
 #endif
 
         JSObject *obj = NewObjectWithClassProto(cx, &js_NoSuchMethodClass, NULL, NULL);
         if (!obj)
             return false;
 
@@ -508,18 +508,18 @@ js::ExecuteKernel(JSContext *cx, JSScrip
         *result = fp->returnValue();
     return ok;
 }
 
 bool
 js::Execute(JSContext *cx, JSScript *script, JSObject &scopeChainArg, Value *rval)
 {
     /* The scope chain could be anything, so innerize just in case. */
-    JSObject *scopeChain = &scopeChainArg;
-    OBJ_TO_INNER_OBJECT(cx, scopeChain);
+    RootedVarObject scopeChain(cx, &scopeChainArg);
+    scopeChain = GetInnerObject(cx, scopeChain);
     if (!scopeChain)
         return false;
 
     /* If we were handed a non-native object, complain bitterly. */
     if (!scopeChain->isNative()) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NON_NATIVE_SCOPE);
         return false;
     }
@@ -537,17 +537,17 @@ js::Execute(JSContext *cx, JSScript *scr
         return false;
     Value thisv = ObjectValue(*thisObj);
 
     return ExecuteKernel(cx, script, *scopeChain, thisv, EXECUTE_GLOBAL,
                          NULL /* evalInFrame */, rval);
 }
 
 JSBool
-js::HasInstance(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp)
+js::HasInstance(JSContext *cx, HandleObject obj, const Value *v, JSBool *bp)
 {
     Class *clasp = obj->getClass();
     if (clasp->hasInstance)
         return clasp->hasInstance(cx, obj, v, bp);
     js_ReportValueError(cx, JSMSG_BAD_INSTANCEOF_RHS,
                         JSDVG_SEARCH_STACK, ObjectValue(*obj), NULL);
     return JS_FALSE;
 }
@@ -580,17 +580,17 @@ js::LooselyEqual(JSContext *cx, const Va
         }
 
         if (lval.isObject()) {
             JSObject *l = &lval.toObject();
             JSObject *r = &rval.toObject();
 
             if (JSEqualityOp eq = l->getClass()->ext.equality) {
                 JSBool res;
-                if (!eq(cx, l, &rval, &res))
+                if (!eq(cx, RootedVarObject(cx, l), &rval, &res))
                     return false;
                 *result = !!res;
                 return true;
             }
 
             *result = l == r;
             return true;
         }
@@ -1025,17 +1025,17 @@ js::AssertValidPropertyCacheHit(JSContex
 
     JSObject *obj, *pobj;
     JSProperty *prop;
     JSBool ok;
 
     if (JOF_OPMODE(*pc) == JOF_NAME)
         ok = FindProperty(cx, name, start, &obj, &pobj, &prop);
     else
-        ok = LookupProperty(cx, start, name, &pobj, &prop);
+        ok = baseops::LookupProperty(cx, start, name.reference(), &pobj, &prop);
     JS_ASSERT(ok);
 
     if (cx->runtime->gcNumber != sample)
         JS_PROPERTY_CACHE(cx).restore(&savedEntry);
     JS_ASSERT(prop);
     JS_ASSERT(pobj == found);
 
     const Shape *shape = (Shape *) prop;
@@ -1344,16 +1344,17 @@ js::Interpret(JSContext *cx, StackFrame 
      * around computed gotos.
      */
     RootedVarValue rootValue0(cx), rootValue1(cx);
     RootedVarString rootString0(cx), rootString1(cx);
     RootedVarObject rootObject0(cx), rootObject1(cx);
     RootedVarFunction rootFunction0(cx);
     RootedVarTypeObject rootType0(cx);
     RootedVarPropertyName rootName0(cx);
+    RootedVarId rootId0(cx);
 
     if (rt->profilingScripts)
         ENABLE_INTERRUPTS();
 
     if (!entryFrame)
         entryFrame = regs.fp();
 
     /*
@@ -1795,17 +1796,17 @@ END_CASE(JSOP_AND)
  * If the index value at sp[n] is not an int that fits in a jsval, it could
  * be an object (an XML QName, AttributeName, or AnyName), but only if we are
  * compiling with JS_HAS_XML_SUPPORT.  Otherwise convert the index value to a
  * string atom id.
  */
 #define FETCH_ELEMENT_ID(obj, n, id)                                          \
     JS_BEGIN_MACRO                                                            \
         const Value &idval_ = regs.sp[n];                                     \
-        if (!ValueToId(cx, obj, idval_, &id))                                 \
+        if (!ValueToId(cx, obj, idval_, id.address()))                        \
             goto error;                                                       \
     JS_END_MACRO
 
 #define TRY_BRANCH_AFTER_COND(cond,spdec)                                     \
     JS_BEGIN_MACRO                                                            \
         JS_ASSERT(js_CodeSpec[op].length == 1);                               \
         unsigned diff_ = (unsigned) GET_UINT8(regs.pc) - (unsigned) JSOP_IFEQ;         \
         if (diff_ <= 1) {                                                     \
@@ -1824,17 +1825,17 @@ BEGIN_CASE(JSOP_IN)
 {
     const Value &rref = regs.sp[-1];
     if (!rref.isObject()) {
         js_ReportValueError(cx, JSMSG_IN_NOT_OBJECT, -1, rref, NULL);
         goto error;
     }
     RootedVarObject &obj = rootObject0;
     obj = &rref.toObject();
-    jsid id;
+    RootedVarId &id = rootId0;
     FETCH_ELEMENT_ID(obj, -2, id);
     JSObject *obj2;
     JSProperty *prop;
     if (!obj->lookupGeneric(cx, id, &obj2, &prop))
         goto error;
     bool cond = prop != NULL;
     TRY_BRANCH_AFTER_COND(cond, 2);
     regs.sp--;
@@ -1939,17 +1940,17 @@ BEGIN_CASE(JSOP_SETCONST)
 END_CASE(JSOP_SETCONST);
 
 #if JS_HAS_DESTRUCTURING
 BEGIN_CASE(JSOP_ENUMCONSTELEM)
 {
     const Value &ref = regs.sp[-3];
     JSObject *obj;
     FETCH_OBJECT(cx, -2, obj);
-    jsid id;
+    RootedVarId &id = rootId0;
     FETCH_ELEMENT_ID(obj, -1, id);
     if (!obj->defineGeneric(cx, id, ref,
                             JS_PropertyStub, JS_StrictPropertyStub,
                             JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY)) {
         goto error;
     }
     regs.sp -= 3;
 }
@@ -2324,17 +2325,18 @@ BEGIN_CASE(JSOP_DELPROP)
 END_CASE(JSOP_DELPROP)
 
 BEGIN_CASE(JSOP_DELELEM)
 {
     /* Fetch the left part and resolve it to a non-null object. */
     JSObject *obj;
     FETCH_OBJECT(cx, -2, obj);
 
-    const Value &propval = regs.sp[-1];
+    RootedVarValue &propval = rootValue0;
+    propval = regs.sp[-1];
     Value &rval = regs.sp[-2];
 
     if (!obj->deleteByValue(cx, propval, &rval, script->strictModeCode))
         goto error;
 
     regs.sp--;
 }
 END_CASE(JSOP_DELELEM)
@@ -2472,34 +2474,34 @@ BEGIN_CASE(JSOP_CALLELEM)
     regs.sp--;
 }
 END_CASE(JSOP_GETELEM)
 
 BEGIN_CASE(JSOP_SETELEM)
 {
     RootedVarObject &obj = rootObject0;
     FETCH_OBJECT(cx, -3, obj);
-    jsid id;
+    RootedVarId &id = rootId0;
     FETCH_ELEMENT_ID(obj, -2, id);
     Value &value = regs.sp[-1];
     if (!SetObjectElementOperation(cx, obj, id, value, script->strictModeCode))
         goto error;
     regs.sp[-3] = value;
     regs.sp -= 2;
 }
 END_CASE(JSOP_SETELEM)
 
 BEGIN_CASE(JSOP_ENUMELEM)
 {
     RootedVarObject &obj = rootObject0;
     RootedVarValue &rval = rootValue0;
 
     /* Funky: the value to set is under the [obj, id] pair. */
     FETCH_OBJECT(cx, -2, obj);
-    jsid id;
+    RootedVarId &id = rootId0;
     FETCH_ELEMENT_ID(obj, -1, id);
     rval = regs.sp[-3];
     if (!obj->setGeneric(cx, id, rval.address(), script->strictModeCode))
         goto error;
     regs.sp -= 3;
 }
 END_CASE(JSOP_ENUMELEM)
 
@@ -3060,17 +3062,17 @@ BEGIN_CASE(JSOP_CALLEE)
     JS_ASSERT(regs.fp()->isNonEvalFunctionFrame());
     PUSH_COPY(argv[-2]);
 END_CASE(JSOP_CALLEE)
 
 BEGIN_CASE(JSOP_GETTER)
 BEGIN_CASE(JSOP_SETTER)
 {
     JSOp op2 = JSOp(*++regs.pc);
-    jsid id;
+    RootedVarId &id = rootId0;
     Value rval;
     int i;
     JSObject *obj;
     switch (op2) {
       case JSOP_SETNAME:
       case JSOP_SETPROP:
       {
         PropertyName *name;
@@ -3224,22 +3226,24 @@ BEGIN_CASE(JSOP_INITPROP)
     JS_ASSERT(regs.sp - regs.fp()->base() >= 2);
     Value rval = regs.sp[-1];
 
     /* Load the object being initialized into lval/obj. */
     RootedVarObject &obj = rootObject0;
     obj = &regs.sp[-2].toObject();
     JS_ASSERT(obj->isObject());
 
+    RootedVarId &id = rootId0;
+
     PropertyName *name;
     LOAD_NAME(0, name);
-    jsid id = NameToId(name);
+    id = NameToId(name);
 
     if (JS_UNLIKELY(name == cx->runtime->atomState.protoAtom)
-        ? !js_SetPropertyHelper(cx, obj, id, 0, &rval, script->strictModeCode)
+        ? !baseops::SetPropertyHelper(cx, obj, id, 0, &rval, script->strictModeCode)
         : !DefineNativeProperty(cx, obj, id, rval, NULL, NULL,
                                 JSPROP_ENUMERATE, 0, 0, 0)) {
         goto error;
     }
 
     regs.sp--;
 }
 END_CASE(JSOP_INITPROP);
@@ -3253,17 +3257,17 @@ BEGIN_CASE(JSOP_INITELEM)
     RootedVarObject &obj = rootObject0;
 
     /* Find the object being initialized at top of stack. */
     const Value &lref = regs.sp[-3];
     JS_ASSERT(lref.isObject());
     obj = &lref.toObject();
 
     /* Fetch id now that we have obj. */
-    jsid id;
+    RootedVarId &id = rootId0;
     FETCH_ELEMENT_ID(obj, -2, id);
 
     /*
      * If rref is a hole, do not call JSObject::defineProperty. In this case,
      * obj must be an array, so if the current op is the last element
      * initialiser, set the array length to one greater than id.
      */
     if (rref.isMagic(JS_ARRAY_HOLE)) {
@@ -3346,17 +3350,18 @@ BEGIN_CASE(JSOP_THROW)
 
 BEGIN_CASE(JSOP_INSTANCEOF)
 {
     const Value &rref = regs.sp[-1];
     if (rref.isPrimitive()) {
         js_ReportValueError(cx, JSMSG_BAD_INSTANCEOF_RHS, -1, rref, NULL);
         goto error;
     }
-    JSObject *obj = &rref.toObject();
+    RootedVarObject &obj = rootObject0;
+    obj = &rref.toObject();
     const Value &lref = regs.sp[-2];
     JSBool cond = JS_FALSE;
     if (!HasInstance(cx, obj, &lref, &cond))
         goto error;
     regs.sp--;
     regs.sp[-1].setBoolean(cond);
 }
 END_CASE(JSOP_INSTANCEOF)
@@ -3515,35 +3520,35 @@ BEGIN_CASE(JSOP_BINDXMLNAME)
 END_CASE(JSOP_BINDXMLNAME)
 
 BEGIN_CASE(JSOP_SETXMLNAME)
 {
     JS_ASSERT(!script->strictModeCode);
 
     JSObject *obj = &regs.sp[-3].toObject();
     Value rval = regs.sp[-1];
-    jsid id;
+    RootedVarId &id = rootId0;
     FETCH_ELEMENT_ID(obj, -2, id);
     if (!obj->setGeneric(cx, id, &rval, script->strictModeCode))
         goto error;
     rval = regs.sp[-1];
     regs.sp -= 2;
     regs.sp[-1] = rval;
 }
 END_CASE(JSOP_SETXMLNAME)
 
 BEGIN_CASE(JSOP_CALLXMLNAME)
 BEGIN_CASE(JSOP_XMLNAME)
 {
     JS_ASSERT(!script->strictModeCode);
 
     Value lval = regs.sp[-1];
     JSObject *obj;
-    jsid id;
-    if (!js_FindXMLProperty(cx, lval, &obj, &id))
+    RootedVarId &id = rootId0;
+    if (!js_FindXMLProperty(cx, lval, &obj, id.address()))
         goto error;
     Value rval;
     if (!obj->getGeneric(cx, id, &rval))
         goto error;
     regs.sp[-1] = rval;
     if (op == JSOP_CALLXMLNAME) {
         Value v;
         if (!ComputeImplicitThis(cx, obj, &v))
@@ -3809,17 +3814,18 @@ BEGIN_CASE(JSOP_YIELD)
     goto exit;
 
 BEGIN_CASE(JSOP_ARRAYPUSH)
 {
     uint32_t slot = GET_UINT16(regs.pc);
     JS_ASSERT(script->nfixed <= slot);
     JS_ASSERT(slot < script->nslots);
     CheckLocalAccess(regs.fp(), slot);
-    JSObject *obj = &regs.fp()->slots()[slot].toObject();
+    RootedVarObject &obj = rootObject0;
+    obj = &regs.fp()->slots()[slot].toObject();
     if (!js_NewbornArrayPush(cx, obj, regs.sp[-1]))
         goto error;
     regs.sp--;
 }
 END_CASE(JSOP_ARRAYPUSH)
 #endif /* JS_HAS_GENERATORS */
 
 #if JS_THREADED_INTERP
--- a/js/src/jsinterp.h
+++ b/js/src/jsinterp.h
@@ -239,17 +239,17 @@ LooselyEqual(JSContext *cx, const Value 
 /* === except that NaN is the same as NaN and -0 is not the same as +0. */
 extern bool
 SameValue(JSContext *cx, const Value &v1, const Value &v2, bool *same);
 
 extern JSType
 TypeOfValue(JSContext *cx, const Value &v);
 
 extern JSBool
-HasInstance(JSContext *cx, JSObject *obj, const js::Value *v, JSBool *bp);
+HasInstance(JSContext *cx, HandleObject obj, const js::Value *v, JSBool *bp);
 
 /*
  * A linked list of the |FrameRegs regs;| variables belonging to all
  * js::Interpret C++ frames on this thread's stack.
  *
  * Note that this is *not* a list of all JS frames running under the
  * interpreter; that would include inlined frames, whose FrameRegs are
  * saved in various pieces in various places. Rather, this lists each
--- a/js/src/jsinterpinlines.h
+++ b/js/src/jsinterpinlines.h
@@ -178,17 +178,17 @@ AssertValidPropertyCacheHit(JSContext *c
 #else
 inline void
 AssertValidPropertyCacheHit(JSContext *cx, JSObject *start, JSObject *found,
                             PropertyCacheEntry *entry)
 {}
 #endif
 
 inline bool
-GetPropertyGenericMaybeCallXML(JSContext *cx, JSOp op, HandleObject obj, jsid id, Value *vp)
+GetPropertyGenericMaybeCallXML(JSContext *cx, JSOp op, HandleObject obj, HandleId id, Value *vp)
 {
     /*
      * Various XML properties behave differently when accessed in a
      * call vs. normal context, and getGeneric will not work right.
      */
 #if JS_HAS_XML_SUPPORT
     if (op == JSOP_CALLPROP && obj->isXML())
         return js_GetXMLMethod(cx, obj, id, vp);
@@ -334,22 +334,22 @@ SetPropertyOperation(JSContext *cx, jsby
 
     bool strict = cx->stack.currentScript()->strictModeCode;
     RootedVarValue rref(cx, rval);
 
     JSOp op = JSOp(*pc);
 
     RootObject objRoot(cx, &obj);
 
-    jsid id = NameToId(name);
+    RootedVarId id(cx, NameToId(name));
     if (JS_LIKELY(!obj->getOps()->setProperty)) {
         unsigned defineHow = (op == JSOP_SETNAME)
                              ? DNP_CACHE_RESULT | DNP_UNQUALIFIED
                              : DNP_CACHE_RESULT;
-        if (!js_SetPropertyHelper(cx, objRoot, id, defineHow, rref.address(), strict))
+        if (!baseops::SetPropertyHelper(cx, objRoot, id, defineHow, rref.address(), strict))
             return false;
     } else {
         if (!obj->setGeneric(cx, id, rref.address(), strict))
             return false;
     }
 
     return true;
 }
@@ -400,17 +400,17 @@ NameOperation(JSContext *cx, jsbytecode 
         JSAutoByteString printable;
         if (js_AtomToPrintableString(cx, name, &printable))
             js_ReportIsNotDefined(cx, printable.ptr());
         return false;
     }
 
     /* Take the slow path if prop was not found in a native object. */
     if (!obj->isNative() || !obj2->isNative()) {
-        if (!obj->getGeneric(cx, id, vp))
+        if (!obj->getGeneric(cx, RootedVarId(cx, id), vp))
             return false;
     } else {
         Shape *shape = (Shape *)prop;
         JSObject *normalized = obj;
         if (normalized->getClass() == &WithClass && !shape->hasDefaultGetter())
             normalized = &normalized->asWith().object();
         if (!NativeGet(cx, normalized, obj2, shape, 0, vp))
             return false;
@@ -705,24 +705,24 @@ ModOperation(JSContext *cx, HandleValue 
         res->setDouble(js_NaN);
     else
         res->setDouble(js_fmod(d1, d2));
     types::TypeScript::MonitorOverflow(cx);
     return true;
 }
 
 static inline bool
-FetchElementId(JSContext *cx, JSObject *obj, const Value &idval, jsid &id, Value *vp)
+FetchElementId(JSContext *cx, JSObject *obj, const Value &idval, jsid *idp, Value *vp)
 {
     int32_t i_;
     if (ValueFitsInInt32(idval, &i_) && INT_FITS_IN_JSID(i_)) {
-        id = INT_TO_JSID(i_);
+        *idp = INT_TO_JSID(i_);
         return true;
     }
-    return !!InternNonIntElementId(cx, obj, idval, &id, vp);
+    return !!InternNonIntElementId(cx, obj, idval, idp, vp);
 }
 
 static JS_ALWAYS_INLINE bool
 ToIdOperation(JSContext *cx, const Value &objval, const Value &idval, Value *res)
 {
     if (idval.isInt32()) {
         *res = idval;
         return true;
@@ -742,17 +742,17 @@ ToIdOperation(JSContext *cx, const Value
 }
 
 static JS_ALWAYS_INLINE bool
 GetObjectElementOperation(JSContext *cx, JSOp op, HandleObject obj, const Value &rref, Value *res)
 {
 #if JS_HAS_XML_SUPPORT
     if (op == JSOP_CALLELEM && JS_UNLIKELY(obj->isXML())) {
         jsid id;
-        if (!FetchElementId(cx, obj, rref, id, res))
+        if (!FetchElementId(cx, obj, rref, &id, res))
             return false;
         return js_GetXMLMethod(cx, obj, id, res);
     }
 #endif
 
     uint32_t index;
     if (IsDefinitelyIndex(rref, &index)) {
         do {
@@ -833,17 +833,17 @@ GetElementOperation(JSContext *cx, JSOp 
         if (!OnUnknownMethod(cx, obj, rref, res))
             return false;
     }
 #endif
     return true;
 }
 
 static JS_ALWAYS_INLINE bool
-SetObjectElementOperation(JSContext *cx, JSObject *obj, jsid id, const Value &value, bool strict)
+SetObjectElementOperation(JSContext *cx, JSObject *obj, HandleId id, const Value &value, bool strict)
 {
     types::TypeScript::MonitorAssign(cx, obj, id);
 
     do {
         if (obj->isDenseArray() && JSID_IS_INT(id)) {
             uint32_t length = obj->getDenseArrayInitializedLength();
             int32_t i = JSID_TO_INT(id);
             if ((uint32_t)i < length) {
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -81,17 +81,17 @@
 #include "vm/String-inl.h"
 
 using namespace mozilla;
 using namespace js;
 using namespace js::gc;
 
 static void iterator_finalize(FreeOp *fop, JSObject *obj);
 static void iterator_trace(JSTracer *trc, JSObject *obj);
-static JSObject *iterator_iterator(JSContext *cx, JSObject *obj, JSBool keysonly);
+static JSObject *iterator_iterator(JSContext *cx, HandleObject obj, JSBool keysonly);
 
 Class js::IteratorClass = {
     "Iterator",
     JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS |
     JSCLASS_HAS_CACHED_PROTO(JSProto_Iterator),
     JS_PropertyStub,         /* addProperty */
     JS_PropertyStub,         /* delProperty */
     JS_PropertyStub,         /* getProperty */
@@ -459,17 +459,17 @@ GetCustomIterator(JSContext *cx, HandleO
     if (flags == JSITER_FOR_OF) {
         js_ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_NOT_ITERABLE,
                                  JSDVG_SEARCH_STACK, ObjectValue(*obj), NULL, NULL, NULL);
         return false;
     }
 
     /* Check whether we have a valid __iterator__ method. */
     PropertyName *name = cx->runtime->atomState.iteratorAtom;
-    if (!js_GetMethod(cx, obj, NameToId(name), 0, vp))
+    if (!GetMethod(cx, obj, name, 0, vp))
         return false;
 
     /* If there is no custom __iterator__ method, we are done here. */
     if (!vp->isObject()) {
         vp->setUndefined();
         return true;
     }
 
@@ -817,17 +817,17 @@ GetIterator(JSContext *cx, HandleObject 
     if (shapes.length() == 2)
         cx->runtime->nativeIterCache.last = iterobj;
     return true;
 }
 
 }
 
 static JSObject *
-iterator_iterator(JSContext *cx, JSObject *obj, JSBool keysonly)
+iterator_iterator(JSContext *cx, HandleObject obj, JSBool keysonly)
 {
     return obj;
 }
 
 static JSBool
 Iterator(JSContext *cx, unsigned argc, Value *vp)
 {
     Value *argv = JS_ARGV(cx, vp);
@@ -1013,18 +1013,18 @@ SuppressDeletedPropertyHelper(JSContext 
                     /*
                      * Check whether another property along the prototype chain
                      * became visible as a result of this deletion.
                      */
                     if (obj->getProto()) {
                         JSObject *proto = obj->getProto();
                         JSObject *obj2;
                         JSProperty *prop;
-                        jsid id;
-                        if (!ValueToId(cx, StringValue(*idp), &id))
+                        RootedVarId id(cx);
+                        if (!ValueToId(cx, StringValue(*idp), id.address()))
                             return false;
                         if (!proto->lookupGeneric(cx, id, &obj2, &prop))
                             return false;
                         if (prop) {
                             unsigned attrs;
                             if (obj2->isNative())
                                 attrs = ((Shape *) prop)->attributes();
                             else if (!obj2->getGenericAttributes(cx, id, &attrs))
@@ -1213,18 +1213,18 @@ js_IteratorMore(JSContext *cx, HandleObj
     }
 
     /* We're reentering below and can call anything. */
     JS_CHECK_RECURSION(cx, return false);
 
     /* Fetch and cache the next value from the iterator. */
     if (ni) {
         JS_ASSERT(!ni->isKeyIter());
-        jsid id;
-        if (!ValueToId(cx, StringValue(*ni->current()), &id))
+        RootedVarId id(cx);
+        if (!ValueToId(cx, StringValue(*ni->current()), id.address()))
             return false;
         ni->incCursor();
         if (!ni->obj->getGeneric(cx, id, rval))
             return false;
         if ((ni->flags & JSITER_KEYVALUE) && !NewKeyValuePair(cx, id, *rval, rval))
             return false;
     } else if (iterobj->isElementIterator()) {
         /*
@@ -1242,18 +1242,17 @@ js_IteratorMore(JSContext *cx, HandleObj
         if (!Proxy::iteratorNext(cx, iterobj, rval))
             return false;
         if (rval->isMagic(JS_NO_ITER_VALUE)) {
             rval->setBoolean(false);
             return true;
         }
     } else {
         /* Call the iterator object's .next method. */
-        jsid id = NameToId(cx->runtime->atomState.nextAtom);
-        if (!js_GetMethod(cx, iterobj, id, 0, rval))
+        if (!GetMethod(cx, iterobj, cx->runtime->atomState.nextAtom, 0, rval))
             return false;
         if (!Invoke(cx, ObjectValue(*iterobj), *rval, 0, NULL, rval)) {
             /* Check for StopIteration. */
             if (!cx->isExceptionPending() || !IsStopIteration(cx->getPendingException()))
                 return false;
 
             cx->clearPendingException();
             cx->iterValue.setMagic(JS_NO_ITER_VALUE);
@@ -1305,17 +1304,17 @@ js_IteratorNext(JSContext *cx, JSObject 
     JS_ASSERT(!cx->iterValue.isMagic(JS_NO_ITER_VALUE));
     *rval = cx->iterValue;
     cx->iterValue.setMagic(JS_NO_ITER_VALUE);
 
     return true;
 }
 
 static JSBool
-stopiter_hasInstance(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp)
+stopiter_hasInstance(JSContext *cx, HandleObject obj, const Value *v, JSBool *bp)
 {
     *bp = IsStopIteration(*v);
     return JS_TRUE;
 }
 
 Class js::StopIterationClass = {
     js_StopIteration_str,
     JSCLASS_HAS_CACHED_PROTO(JSProto_StopIteration) |
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -1034,20 +1034,20 @@ js_InitNumberClass(JSContext *cx, JSObje
 
     if (!DefinePropertiesAndBrand(cx, numberProto, NULL, number_methods))
         return NULL;
 
     if (!JS_DefineFunctions(cx, global, number_functions))
         return NULL;
 
     /* ES5 15.1.1.1, 15.1.1.2 */
-    if (!DefineNativeProperty(cx, global, NameToId(cx->runtime->atomState.NaNAtom),
+    if (!DefineNativeProperty(cx, global, cx->runtime->atomState.NaNAtom,
                               cx->runtime->NaNValue, JS_PropertyStub, JS_StrictPropertyStub,
                               JSPROP_PERMANENT | JSPROP_READONLY, 0, 0) ||
-        !DefineNativeProperty(cx, global, NameToId(cx->runtime->atomState.InfinityAtom),
+        !DefineNativeProperty(cx, global, cx->runtime->atomState.InfinityAtom,
                               cx->runtime->positiveInfinityValue,
                               JS_PropertyStub, JS_StrictPropertyStub,
                               JSPROP_PERMANENT | JSPROP_READONLY, 0, 0))
     {
         return NULL;
     }
 
     if (!DefineConstructorAndPrototype(cx, global, JSProto_Number, ctor, numberProto))
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -118,72 +118,68 @@ Class js::ObjectClass = {
 
 JS_FRIEND_API(JSObject *)
 JS_ObjectToInnerObject(JSContext *cx, JSObject *obj)
 {
     if (!obj) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INACTIVE);
         return NULL;
     }
-    OBJ_TO_INNER_OBJECT(cx, obj);
-    return obj;
+    return GetInnerObject(cx, RootedVarObject(cx, obj));
 }
 
 JS_FRIEND_API(JSObject *)
 JS_ObjectToOuterObject(JSContext *cx, JSObject *obj)
 {
-    OBJ_TO_OUTER_OBJECT(cx, obj);
-    return obj;
+    return GetOuterObject(cx, RootedVarObject(cx, obj));
 }
 
 #if JS_HAS_OBJ_PROTO_PROP
 
 static JSBool
-obj_getProto(JSContext *cx, JSObject *obj, jsid id, Value *vp);
+obj_getProto(JSContext *cx, HandleObject obj, HandleId id, Value *vp);
 
 static JSBool
-obj_setProto(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp);
+obj_setProto(JSContext *cx, HandleObject obj, HandleId id, JSBool strict, Value *vp);
 
 JSPropertySpec object_props[] = {
     {js_proto_str, 0, JSPROP_PERMANENT|JSPROP_SHARED, obj_getProto, obj_setProto},
     {0,0,0,0,0}
 };
 
 static JSBool
-obj_getProto(JSContext *cx, JSObject *obj, jsid id, Value *vp)
+obj_getProto(JSContext *cx, HandleObject obj, HandleId id, Value *vp)
 {
     /* Let CheckAccess get the slot's value, based on the access mode. */
     unsigned attrs;
-    id = NameToId(cx->runtime->atomState.protoAtom);
-    return CheckAccess(cx, obj, id, JSACC_PROTO, vp, &attrs);
+    RootedVarId nid(cx, NameToId(cx->runtime->atomState.protoAtom));
+    return CheckAccess(cx, obj, nid, JSACC_PROTO, vp, &attrs);
 }
 
 size_t sSetProtoCalled = 0;
 
 static JSBool
-obj_setProto(JSContext *cx, JSObject *obj_, jsid id, JSBool strict, Value *vp)
-{
-    RootedVarObject obj(cx, obj_);
-
+obj_setProto(JSContext *cx, HandleObject obj, HandleId id, JSBool strict, Value *vp)
+{
     if (!cx->runningWithTrustedPrincipals())
         ++sSetProtoCalled;
 
     /* ECMAScript 5 8.6.2 forbids changing [[Prototype]] if not [[Extensible]]. */
     if (!obj->isExtensible()) {
         obj->reportNotExtensible(cx);
         return false;
     }
 
     if (!vp->isObjectOrNull())
         return true;
 
     RootedVarObject pobj(cx, vp->toObjectOrNull());
     unsigned attrs;
-    id = NameToId(cx->runtime->atomState.protoAtom);
-    if (!CheckAccess(cx, obj, id, JSAccessMode(JSACC_PROTO|JSACC_WRITE), vp, &attrs))
+    RootedVarId nid(cx, NameToId(cx->runtime->atomState.protoAtom));
+    if (!CheckAccess(cx, obj, nid, JSAccessMode(JSACC_PROTO|JSACC_WRITE), vp, &attrs))
         return false;
 
     return SetProto(cx, obj, pobj, true);
 }
 
 #else  /* !JS_HAS_OBJ_PROTO_PROP */
 
 #define object_props NULL
@@ -205,18 +201,19 @@ MarkSharpObjects(JSContext *cx, HandleOb
         if (!map->table.put(obj.value(), sharpid))
             return false;
 
         ida = JS_Enumerate(cx, obj);
         if (!ida)
             return false;
 
         bool ok = true;
+        RootedVarId id(cx);
         for (int i = 0, length = ida->length; i < length; i++) {
-            jsid id = ida->vector[i];
+            id = ida->vector[i];
             JSObject *obj2;
             JSProperty *prop;
             ok = obj->lookupGeneric(cx, id, &obj2, &prop);
             if (!ok)
                 break;
             if (!prop)
                 continue;
             bool hasGetter, hasSetter;
@@ -479,19 +476,20 @@ obj_toSource(JSContext *cx, unsigned arg
 
     /*
      * We have four local roots for cooked and raw value GC safety.  Hoist the
      * "localroot + 2" out of the loop using the val local, which refers to
      * the raw (unconverted, "uncooked") values.
      */
     val = localroot + 2;
 
+    RootedVarId id(cx);
     for (int i = 0; i < ida->length; i++) {
         /* Get strings for id and value and GC-root them via vp. */
-        jsid id = ida->vector[i];
+        id = ida->vector[i];
         JSLinearString *idstr;
 
         JSObject *obj2;
         JSProperty *prop;
         if (!obj->lookupGeneric(cx, id, &obj2, &prop))
             return false;
 
         /*
@@ -711,17 +709,18 @@ obj_toLocaleString(JSContext *cx, unsign
     JS_CHECK_RECURSION(cx, return false);
 
     /* Step 1. */
     JSObject *obj = ToObject(cx, &vp[1]);
     if (!obj)
         return false;
 
     /* Steps 2-4. */
-    return obj->callMethod(cx, NameToId(cx->runtime->atomState.toStringAtom), 0, NULL, vp);
+    RootedVarId id(cx, NameToId(cx->runtime->atomState.toStringAtom));
+    return obj->callMethod(cx, id, 0, NULL, vp);
 }
 
 static JSBool
 obj_valueOf(JSContext *cx, unsigned argc, Value *vp)
 {
     JSObject *obj = ToObject(cx, &vp[1]);
     if (!obj)
         return false;
@@ -731,17 +730,17 @@ obj_valueOf(JSContext *cx, unsigned argc
 
 /* We should be able to assert this for *any* fp->scopeChain(). */
 static void
 AssertInnerizedScopeChain(JSContext *cx, JSObject &scopeobj)
 {
 #ifdef DEBUG
     for (JSObject *o = &scopeobj; o; o = o->enclosingScope()) {
         if (JSObjectOp op = o->getClass()->ext.innerObject)
-            JS_ASSERT(op(cx, o) == o);
+            JS_ASSERT(op(cx, RootedVarObject(cx, o)) == o);
     }
 #endif
 }
 
 #ifndef EVAL_CACHE_CHAIN_LIMIT
 # define EVAL_CACHE_CHAIN_LIMIT 4
 #endif
 
@@ -1272,18 +1271,18 @@ obj_hasOwnProperty(JSContext *cx, unsign
         return false;
     return js_HasOwnPropertyHelper(cx, obj->getOps()->lookupGeneric, argc, vp);
 }
 
 JSBool
 js_HasOwnPropertyHelper(JSContext *cx, LookupGenericOp lookup, unsigned argc,
                         Value *vp)
 {
-    jsid id;
-    if (!ValueToId(cx, argc != 0 ? vp[2] : UndefinedValue(), &id))
+    RootedVarId id(cx);
+    if (!ValueToId(cx, argc != 0 ? vp[2] : UndefinedValue(), id.address()))
         return JS_FALSE;
 
     RootedVarObject obj(cx, ToObject(cx, &vp[1]));
     if (!obj)
         return false;
     JSObject *obj2;
     JSProperty *prop;
     if (obj->isProxy()) {
@@ -1295,31 +1294,36 @@ js_HasOwnPropertyHelper(JSContext *cx, L
     }
     if (!js_HasOwnProperty(cx, lookup, obj, id, &obj2, &prop))
         return JS_FALSE;
     vp->setBoolean(!!prop);
     return JS_TRUE;
 }
 
 JSBool
-js_HasOwnProperty(JSContext *cx, LookupGenericOp lookup, HandleObject obj, jsid id,
+js_HasOwnProperty(JSContext *cx, LookupGenericOp lookup, HandleObject obj, HandleId id,
                   JSObject **objp, JSProperty **propp)
 {
     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING);
-    if (!(lookup ? lookup : js_LookupProperty)(cx, obj, id, objp, propp))
-        return false;
+    if (lookup) {
+        if (!lookup(cx, obj, id, objp, propp))
+            return false;
+    } else {
+        if (!baseops::LookupProperty(cx, obj, id, objp, propp))
+            return false;
+    }
     if (!*propp)
         return true;
 
     if (*objp == obj)
         return true;
 
     JSObject *outer = NULL;
     if (JSObjectOp op = (*objp)->getClass()->ext.outerObject) {
-        outer = op(cx, *objp);
+        outer = op(cx, RootedVarObject(cx, *objp));
         if (!outer)
             return false;
     }
 
     if (outer != *objp)
         *propp = NULL;
     return true;
 }
@@ -1344,31 +1348,31 @@ obj_isPrototypeOf(JSContext *cx, unsigne
     return true;
 }
 
 /* ES5 15.2.4.7. */
 static JSBool
 obj_propertyIsEnumerable(JSContext *cx, unsigned argc, Value *vp)
 {
     /* Step 1. */
-    jsid id;
-    if (!ValueToId(cx, argc != 0 ? vp[2] : UndefinedValue(), &id))
+    RootedVarId id(cx);
+    if (!ValueToId(cx, argc != 0 ? vp[2] : UndefinedValue(), id.address()))
         return false;
 
     /* Step 2. */
-    JSObject *obj = ToObject(cx, &vp[1]);
+    RootedVarObject obj(cx, ToObject(cx, &vp[1]));
     if (!obj)
         return false;
 
     /* Steps 3-5. */
     return js_PropertyIsEnumerable(cx, obj, id, vp);
 }
 
 JSBool
-js_PropertyIsEnumerable(JSContext *cx, JSObject *obj, jsid id, Value *vp)
+js_PropertyIsEnumerable(JSContext *cx, HandleObject obj, HandleId id, Value *vp)
 {
     JSObject *pobj;
     JSProperty *prop;
     if (!obj->lookupGeneric(cx, id, &pobj, &prop))
         return false;
 
     if (!prop) {
         vp->setBoolean(false);
@@ -1453,20 +1457,20 @@ JS_FRIEND_API(JSBool)
 js::obj_defineSetter(JSContext *cx, unsigned argc, Value *vp)
 {
     return DefineAccessor<Setter>(cx, argc, vp);
 }
 
 static JSBool
 obj_lookupGetter(JSContext *cx, unsigned argc, Value *vp)
 {
-    jsid id;
-    if (!ValueToId(cx, argc != 0 ? vp[2] : UndefinedValue(), &id))
+    RootedVarId id(cx);
+    if (!ValueToId(cx, argc != 0 ? vp[2] : UndefinedValue(), id.address()))
         return JS_FALSE;
-    JSObject *obj = ToObject(cx, &vp[1]);
+    RootedVarObject obj(cx, ToObject(cx, &vp[1]));
     if (!obj)
         return JS_FALSE;
     JSObject *pobj;
     JSProperty *prop;
     if (!obj->lookupGeneric(cx, id, &pobj, &prop))
         return JS_FALSE;
     vp->setUndefined();
     if (prop) {
@@ -1477,20 +1481,20 @@ obj_lookupGetter(JSContext *cx, unsigned
         }
     }
     return JS_TRUE;
 }
 
 static JSBool
 obj_lookupSetter(JSContext *cx, unsigned argc, Value *vp)
 {
-    jsid id;
-    if (!ValueToId(cx, argc != 0 ? vp[2] : UndefinedValue(), &id))
+    RootedVarId id(cx);
+    if (!ValueToId(cx, argc != 0 ? vp[2] : UndefinedValue(), id.address()))
         return JS_FALSE;
-    JSObject *obj = ToObject(cx, &vp[1]);
+    RootedVarObject obj(cx, ToObject(cx, &vp[1]));
     if (!obj)
         return JS_FALSE;
     JSObject *pobj;
     JSProperty *prop;
     if (!obj->lookupGeneric(cx, id, &pobj, &prop))
         return JS_FALSE;
     vp->setUndefined();
     if (prop) {
@@ -1519,18 +1523,18 @@ obj_getPrototypeOf(JSContext *cx, unsign
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                              JSMSG_UNEXPECTED_TYPE, bytes, "not an object");
         JS_free(cx, bytes);
         return JS_FALSE;
     }
 
     JSObject *obj = &vp[2].toObject();
     unsigned attrs;
-    return CheckAccess(cx, obj, NameToId(cx->runtime->atomState.protoAtom),
-                       JSACC_PROTO, vp, &attrs);
+    RootedVarId nid(cx, NameToId(cx->runtime->atomState.protoAtom));
+    return CheckAccess(cx, obj, nid, JSACC_PROTO, vp, &attrs);
 }
 
 namespace js {
 
 bool
 NewPropertyDescriptorObject(JSContext *cx, const PropertyDescriptor *desc, Value *vp)
 {
     if (!desc->obj) {
@@ -1731,17 +1735,17 @@ obj_keys(JSContext *cx, unsigned argc, V
     if (!aobj)
         return false;
     vp->setObject(*aobj);
 
     return true;
 }
 
 static bool
-HasProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, bool *foundp)
+HasProperty(JSContext *cx, HandleObject obj, HandleId id, Value *vp, bool *foundp)
 {
     if (!obj->hasProperty(cx, id, foundp, JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING))
         return false;
     if (!*foundp) {
         vp->setUndefined();
         return true;
     }
 
@@ -1759,83 +1763,87 @@ PropDesc::initialize(JSContext *cx, cons
 {
     Value v = origval;
 
     /* 8.10.5 step 1 */
     if (v.isPrimitive()) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_NONNULL_OBJECT);
         return false;
     }
-    JSObject *desc = &v.toObject();
+    RootedVarObject desc(cx, &v.toObject());
 
     /* Make a copy of the descriptor. We might need it later. */
     pd_ = v;
 
     isUndefined_ = false;
 
     /*
      * Start with the proper defaults.  XXX shouldn't be necessary when we get
      * rid of PropDesc::attributes()
      */
     attrs = JSPROP_PERMANENT | JSPROP_READONLY;
 
-    bool found;
+    bool found = false;
+    RootedVarId id(cx);
 
     /* 8.10.5 step 3 */
-#ifdef __GNUC__ /* quell GCC overwarning */
-    found = false;
-#endif
-    if (!HasProperty(cx, desc, NameToId(cx->runtime->atomState.enumerableAtom), &v, &found))
+    id = NameToId(cx->runtime->atomState.enumerableAtom);
+    if (!HasProperty(cx, desc, id, &v, &found))
         return false;
     if (found) {
         hasEnumerable_ = true;
         if (js_ValueToBoolean(v))
             attrs |= JSPROP_ENUMERATE;
     }
 
     /* 8.10.5 step 4 */
-    if (!HasProperty(cx, desc, NameToId(cx->runtime->atomState.configurableAtom), &v, &found))
+    id = NameToId(cx->runtime->atomState.configurableAtom);
+    if (!HasProperty(cx, desc, id, &v, &found))
         return false;
     if (found) {
         hasConfigurable_ = true;
         if (js_ValueToBoolean(v))
             attrs &= ~JSPROP_PERMANENT;
     }
 
     /* 8.10.5 step 5 */
-    if (!HasProperty(cx, desc, NameToId(cx->runtime->atomState.valueAtom), &v, &found))
+    id = NameToId(cx->runtime->atomState.valueAtom);
+    if (!HasProperty(cx, desc, id, &v, &found))
         return false;
     if (found) {
         hasValue_ = true;
         value_ = v;
     }
 
     /* 8.10.6 step 6 */
-    if (!HasProperty(cx, desc, NameToId(cx->runtime->atomState.writableAtom), &v, &found))
+    id = NameToId(cx->runtime->atomState.writableAtom);
+    if (!HasProperty(cx, desc, id, &v, &found))
         return false;
     if (found) {
         hasWritable_ = true;
         if (js_ValueToBoolean(v))
             attrs &= ~JSPROP_READONLY;
     }
 
     /* 8.10.7 step 7 */
-    if (!HasProperty(cx, desc, NameToId(cx->runtime->atomState.getAtom), &v, &found))
+    id = NameToId(cx->runtime->atomState.getAtom);
+    if (!HasProperty(cx, desc, id, &v, &found))
         return false;
     if (found) {
         hasGet_ = true;
         get_ = v;
         attrs |= JSPROP_GETTER | JSPROP_SHARED;
         attrs &= ~JSPROP_READONLY;
         if (checkAccessors && !checkGetter(cx))
             return false;
     }
 
     /* 8.10.7 step 8 */
-    if (!HasProperty(cx, desc, NameToId(cx->runtime->atomState.setAtom), &v, &found))
+    id = NameToId(cx->runtime->atomState.setAtom);
+    if (!HasProperty(cx, desc, id, &v, &found))
         return false;
     if (found) {
         hasSet_ = true;
         set_ = v;
         attrs |= JSPROP_SETTER | JSPROP_SHARED;
         attrs &= ~JSPROP_READONLY;
         if (checkAccessors && !checkSetter(cx))
             return false;
@@ -1923,35 +1931,35 @@ DefinePropertyOnObject(JSContext *cx, Ha
         if (!obj->isExtensible())
             return Reject(cx, obj, JSMSG_OBJECT_NOT_EXTENSIBLE, throwError, rval);
 
         *rval = true;
 
         if (desc.isGenericDescriptor() || desc.isDataDescriptor()) {
             JS_ASSERT(!obj->getOps()->defineProperty);
             Value v = desc.hasValue() ? desc.value() : UndefinedValue();
-            return js_DefineProperty(cx, obj, id, &v,
-                                     JS_PropertyStub, JS_StrictPropertyStub,
-                                     desc.attributes());
+            return baseops::DefineProperty(cx, obj, id, &v,
+                                           JS_PropertyStub, JS_StrictPropertyStub,
+                                           desc.attributes());
         }
 
         JS_ASSERT(desc.isAccessorDescriptor());
 
         /*
          * Getters and setters are just like watchpoints from an access
          * control point of view.
          */
         Value dummy;
         unsigned dummyAttrs;
         if (!CheckAccess(cx, obj, id, JSACC_WATCH, &dummy, &dummyAttrs))
             return JS_FALSE;
 
         Value tmp = UndefinedValue();
-        return js_DefineProperty(cx, obj, id, &tmp,
-                                 desc.getter(), desc.setter(), desc.attributes());
+        return baseops::DefineProperty(cx, obj, id, &tmp,
+                                       desc.getter(), desc.setter(), desc.attributes());
     }
 
     /* 8.12.9 steps 5-6 (note 5 is merely a special case of 6). */
     Value v = UndefinedValue();
 
     JS_ASSERT(obj == obj2);
 
     const Shape *shape = reinterpret_cast<Shape *>(current);
@@ -2191,17 +2199,17 @@ DefinePropertyOnObject(JSContext *cx, Ha
      * redefining it or we had invoked its setter to change its value).
      */
     if (callDelProperty) {
         Value dummy = UndefinedValue();
         if (!CallJSPropertyOp(cx, obj2->getClass()->delProperty, obj2, id, &dummy))
             return false;
     }
 
-    return js_DefineProperty(cx, obj, id, &v, getter, setter, attrs);
+    return baseops::DefineProperty(cx, obj, id, &v, getter, setter, attrs);
 }
 
 static JSBool
 DefinePropertyOnArray(JSContext *cx, HandleObject obj, HandleId id, const PropDesc &desc,
                       bool throwError, bool *rval)
 {
     /*
      * We probably should optimize dense array property definitions where
@@ -2312,18 +2320,19 @@ namespace js {
 
 bool
 ReadPropertyDescriptors(JSContext *cx, JSObject *props, bool checkAccessors,
                         AutoIdVector *ids, AutoPropDescArrayRooter *descs)
 {
     if (!GetPropertyNames(cx, props, JSITER_OWNONLY, ids))
         return false;
 
+    RootedVarId id(cx);
     for (size_t i = 0, len = ids->length(); i < len; i++) {
-        jsid id = (*ids)[i];
+        id = (*ids)[i];
         PropDesc* desc = descs->append();
         Value v;
         if (!desc || !props->getGeneric(cx, id, &v) || !desc->initialize(cx, v, checkAccessors))
             return false;
     }
     return true;
 }
 
@@ -2557,18 +2566,19 @@ JSObject::sealOrFreeze(JSContext *cx, Im
             last = cx->propertyTree().getChild(cx, last, self->numFixedSlots(), child);
             if (!last)
                 return NULL;
         }
 
         JS_ASSERT(self->lastProperty()->slotSpan() == last->slotSpan());
         JS_ALWAYS_TRUE(self->setLastProperty(cx, last));
     } else {
+        RootedVarId id(cx);
         for (size_t i = 0; i < props.length(); i++) {
-            jsid id = props[i];
+            id = props[i];
 
             unsigned attrs;
             if (!self->getGenericAttributes(cx, id, &attrs))
                 return false;
 
             unsigned new_attrs = getSealedOrFrozenAttributes(attrs, it);
 
             /* If we already have the attributes we need, skip the setAttributes call. */
@@ -2591,18 +2601,19 @@ JSObject::isSealedOrFrozen(JSContext *cx
         *resultp = false;
         return true;
     }
 
     AutoIdVector props(cx);
     if (!GetPropertyNames(cx, this, JSITER_HIDDEN | JSITER_OWNONLY, &props))
         return false;
 
+    RootedVarId id(cx);
     for (size_t i = 0, len = props.length(); i < len; i++) {
-        jsid id = props[i];
+        id = props[i];
 
         unsigned attrs;
         if (!getGenericAttributes(cx, id, &attrs))
             return false;
 
         /*
          * If the property is configurable, this object is neither sealed nor
          * frozen. If the property is a writable data property, this object is
@@ -2911,18 +2922,20 @@ js::NewReshapedObject(JSContext *cx, Han
     }
     const js::Shape *nshape = shape;
     while (!nshape->isEmptyShape()) {
         ids[nshape->slot()] = nshape->propid();
         nshape = nshape->previous();
     }
 
     /* Construct the new shape. */
+    RootedVarId id(cx);
     for (unsigned i = 0; i < ids.length(); i++) {
-        if (!DefineNativeProperty(cx, res, ids[i], js::UndefinedValue(), NULL, NULL,
+        id = ids[i];
+        if (!DefineNativeProperty(cx, res, id, js::UndefinedValue(), NULL, NULL,
                                   JSPROP_ENUMERATE, 0, 0, DNP_SKIP_TYPE)) {
             return NULL;
         }
     }
     JS_ASSERT(!res->inDictionaryMode());
 
     return res;
 }
@@ -3088,72 +3101,65 @@ js_InferFlags(JSContext *cx, unsigned de
             flags |= JSRESOLVE_DETECTING;
     }
     if (format & JOF_DECLARING)
         flags |= JSRESOLVE_DECLARING;
     return flags;
 }
 
 JSBool
-JSObject::nonNativeSetProperty(JSContext *cx, jsid id, js::Value *vp, JSBool strict)
-{
-    JSObject *self = this;
+JSObject::nonNativeSetProperty(JSContext *cx, HandleId id, js::Value *vp, JSBool strict)
+{
+    RootedVarObject self(cx, this);
     if (JS_UNLIKELY(watched())) {
-        RootObject selfRoot(cx, &self);
-        RootId idRoot(cx, &id);
-
         WatchpointMap *wpmap = cx->compartment->watchpointMap;
-        if (wpmap && !wpmap->triggerWatchpoint(cx, selfRoot, idRoot, vp))
+        if (wpmap && !wpmap->triggerWatchpoint(cx, self, id, vp))
             return false;
     }
     return self->getOps()->setGeneric(cx, self, id, vp, strict);
 }
 
 JSBool
 JSObject::nonNativeSetElement(JSContext *cx, uint32_t index, js::Value *vp, JSBool strict)
 {
-    JSObject *self = this;
+    RootedVarObject self(cx, this);
     if (JS_UNLIKELY(watched())) {
-        RootObject selfRoot(cx, &self);
-
-        jsid id;
-        if (!IndexToId(cx, index, &id))
+        RootedVarId id(cx);
+        if (!IndexToId(cx, index, id.address()))
             return false;
 
-        RootId idRoot(cx, &id);
-
         WatchpointMap *wpmap = cx->compartment->watchpointMap;
-        if (wpmap && !wpmap->triggerWatchpoint(cx, selfRoot, idRoot, vp))
+        if (wpmap && !wpmap->triggerWatchpoint(cx, self, id, vp))
             return false;
     }
     return self->getOps()->setElement(cx, self, index, vp, strict);
 }
 
 bool
 JSObject::deleteByValue(JSContext *cx, const Value &property, Value *rval, bool strict)
 {
     uint32_t index;
     if (IsDefinitelyIndex(property, &index))
         return deleteElement(cx, index, rval, strict);
 
     Value propval = property;
     SpecialId sid;
     if (ValueIsSpecial(this, &propval, &sid, cx))
-        return deleteSpecial(cx, sid, rval, strict);
+        return deleteSpecial(cx, RootedVar<SpecialId>(cx, sid), rval, strict);
 
     RootedVarObject self(cx, this);
 
     JSAtom *name;
     if (!js_ValueToAtom(cx, propval, &name))
         return false;
 
     if (name->isIndex(&index))
         return self->deleteElement(cx, index, rval, false);
 
-    return self->deleteProperty(cx, name->asPropertyName(), rval, false);
+    return self->deleteProperty(cx, RootedVarPropertyName(cx, name->asPropertyName()), rval, false);
 }
 
 JS_FRIEND_API(bool)
 JS_CopyPropertiesFrom(JSContext *cx, JSObject *target, JSObject *obj)
 {
     // If we're not native, then we cannot copy properties.
     JS_ASSERT(target->isNative() == obj->isNative());
     if (!target->isNative())
@@ -3165,25 +3171,26 @@ JS_CopyPropertiesFrom(JSContext *cx, JSO
             return false;
     }
 
     size_t n = shapes.length();
     while (n > 0) {
         const Shape *shape = shapes[--n];
         unsigned attrs = shape->attributes();
         PropertyOp getter = shape->getter();
+        StrictPropertyOp setter = shape->setter();
+        RootGetterSetter gsRoot(cx, attrs, &getter, &setter);
         if ((attrs & JSPROP_GETTER) && !cx->compartment->wrap(cx, &getter))
             return false;
-        StrictPropertyOp setter = shape->setter();
         if ((attrs & JSPROP_SETTER) && !cx->compartment->wrap(cx, &setter))
             return false;
         Value v = shape->hasSlot() ? obj->getSlot(shape->slot()) : UndefinedValue();
         if (!cx->compartment->wrap(cx, &v))
             return false;
-        if (!target->defineGeneric(cx, shape->propid(), v, getter, setter, attrs))
+        if (!target->defineGeneric(cx, RootedVarId(cx, shape->propid()), v, getter, setter, attrs))
             return false;
     }
     return true;
 }
 
 static bool
 CopySlots(JSContext *cx, JSObject *from, JSObject *to)
 {
@@ -3553,17 +3560,17 @@ JSObject::swap(JSContext *cx, JSObject *
 
     return true;
 }
 
 static bool
 DefineStandardSlot(JSContext *cx, JSObject *obj, JSProtoKey key, JSAtom *atom,
                    const Value &v, uint32_t attrs, bool &named)
 {
-    jsid id = AtomToId(atom);
+    RootedVarId id(cx, AtomToId(atom));
 
     if (key != JSProto_Null) {
         /*
          * Initializing an actual standard class on a global object. If the
          * property is not yet present, force it into a new one bound to a
          * reserved slot. Otherwise, go through the normal property path.
          */
         JS_ASSERT(obj->isGlobal());
@@ -4112,17 +4119,17 @@ js_InitNullClass(JSContext *cx, JSObject
     JS_ASSERT(0);
     return NULL;
 }
 
 #define JS_PROTO(name,code,init) extern JSObject *init(JSContext *, JSObject *);
 #include "jsproto.tbl"
 #undef JS_PROTO
 
-static JSObjectOp lazy_prototype_init[JSProto_LIMIT] = {
+static JSClassInitializerOp lazy_prototype_init[JSProto_LIMIT] = {
 #define JS_PROTO(name,code,init) init,
 #include "jsproto.tbl"
 #undef JS_PROTO
 };
 
 namespace js {
 
 bool
@@ -4237,42 +4244,42 @@ js_GetClassObject(JSContext *cx, JSObjec
     AutoResolving resolving(cx, obj, NameToId(cx->runtime->atomState.classAtoms[key]));
     if (resolving.alreadyStarted()) {
         /* Already caching id in obj -- suppress recursion. */
         *objp = NULL;
         return true;
     }
 
     JSObject *cobj = NULL;
-    if (JSObjectOp init = lazy_prototype_init[key]) {
+    if (JSClassInitializerOp init = lazy_prototype_init[key]) {
         if (!init(cx, obj))
             return false;
         v = obj->getReservedSlot(key);
         if (v.isObject())
             cobj = &v.toObject();
     }
 
     *objp = cobj;
     return true;
 }
 
 JSBool
 js_FindClassObject(JSContext *cx, JSObject *start, JSProtoKey protoKey,
                    Value *vp, Class *clasp)
 {
     JSObject *cobj, *pobj;
-    jsid id;
+    RootedVarId id(cx);
     JSProperty *prop;
     const Shape *shape;
 
     RootedVarObject obj(cx);
 
     if (start) {
         obj = &start->global();
-        OBJ_TO_INNER_OBJECT(cx, *obj.address());
+        obj = GetInnerObject(cx, obj);
     } else {
         obj = GetGlobalForScopeChain(cx);
     }
     if (!obj)
         return false;
 
     if (protoKey != JSProto_Null) {
         JS_ASSERT(JSProto_Null < protoKey);
@@ -4440,103 +4447,99 @@ js_AddNativeProperty(JSContext *cx, Hand
      */
     if (!js_PurgeScopeChain(cx, obj, id))
         return NULL;
 
     return obj->putProperty(cx, id, getter, setter, slot, attrs, flags, shortid);
 }
 
 JSBool
-js_DefineProperty(JSContext *cx, JSObject *obj_, jsid id, const Value *value,
-                  PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
-{
-    RootObject obj(cx, &obj_);
+baseops::DefineProperty(JSContext *cx, HandleObject obj, HandleId id, const Value *value,
+                        PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
+{
     return !!DefineNativeProperty(cx, obj, id, *value, getter, setter, attrs, 0, 0);
 }
 
 JSBool
-js_DefineElement(JSContext *cx, JSObject *obj, uint32_t index, const Value *value,
-                 PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
+baseops::DefineElement(JSContext *cx, HandleObject obj, uint32_t index, const Value *value,
+                       PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
 {
     if (index <= JSID_INT_MAX) {
-        return !!DefineNativeProperty(cx, RootedVarObject(cx, obj), INT_TO_JSID(index), *value,
+        return !!DefineNativeProperty(cx, obj, RootedVarId(cx, INT_TO_JSID(index)), *value,
                                       getter, setter, attrs, 0, 0);
     }
 
-    RootObject objRoot(cx, &obj);
     RootGetterSetter gsRoot(cx, attrs, &getter, &setter);
-    RootValue valueRoot(cx, value);
-
-    jsid id;
-    if (!IndexToId(cx, index, &id))
+
+    RootedVarId id(cx);
+    if (!IndexToId(cx, index, id.address()))
         return false;
 
-    return !!DefineNativeProperty(cx, objRoot, id, *value, getter, setter, attrs, 0, 0);
+    return !!DefineNativeProperty(cx, obj, id, *value, getter, setter, attrs, 0, 0);
 }
 
 /*
  * Backward compatibility requires allowing addProperty hooks to mutate the
  * nominal initial value of a slotful property, while GC safety wants that
  * value to be stored before the call-out through the hook.  Optimize to do
  * both while saving cycles for classes that stub their addProperty hook.
  */
 static inline bool
-CallAddPropertyHook(JSContext *cx, Class *clasp, JSObject *obj, const Shape *shape, Value *vp)
+CallAddPropertyHook(JSContext *cx, Class *clasp, HandleObject obj, HandleShape shape, Value *vp)
 {
     if (clasp->addProperty != JS_PropertyStub) {
         Value nominal = *vp;
 
-        if (!CallJSPropertyOp(cx, clasp->addProperty, obj, shape->propid(), vp))
+        if (!CallJSPropertyOp(cx, clasp->addProperty, obj, RootedVarId(cx, shape->propid()), vp))
             return false;
         if (*vp != nominal) {
             if (shape->hasSlot())
                 obj->nativeSetSlotWithType(cx, shape, *vp);
         }
     }
     return true;
 }
 
 namespace js {
 
 const Shape *
-DefineNativeProperty(JSContext *cx, HandleObject obj, jsid id, const Value &value_,
+DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, const Value &value_,
                      PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
                      unsigned flags, int shortid, unsigned defineHow /* = 0 */)
 {
     JS_ASSERT((defineHow & ~(DNP_CACHE_RESULT | DNP_DONT_PURGE |
                              DNP_SKIP_TYPE)) == 0);
     JS_ASSERT(!(attrs & JSPROP_NATIVE_ACCESSORS));
 
-    RootId idRoot(cx, &id);
     RootGetterSetter gsRoot(cx, attrs, &getter, &setter);
 
     /* Make a local copy of value so addProperty can mutate its inout parameter. */
     RootedVarValue value(cx);
     value = value_;
 
     /*
      * If defining a getter or setter, we must check for its counterpart and
      * update the attributes and property ops.  A getter or setter is really
      * only half of a property.
      */
-    Shape *shape = NULL;
+    RootedVarShape shape(cx);
     if (attrs & (JSPROP_GETTER | JSPROP_SETTER)) {
         JSObject *pobj;
         JSProperty *prop;
 
         /* Type information for getter/setter properties is unknown. */
         AddTypePropertyId(cx, obj, id, types::Type::UnknownType());
         MarkTypePropertyConfigured(cx, obj, id);
 
         /*
          * If we are defining a getter whose setter was already defined, or
          * vice versa, finish the job via obj->changeProperty, and refresh the
          * property cache line for (obj, id) to map shape.
          */
-        if (!js_LookupProperty(cx, obj, id, &pobj, &prop))
+        if (!baseops::LookupProperty(cx, obj, id, &pobj, &prop))
             return NULL;
         if (prop && pobj == obj) {
             shape = (Shape *) prop;
             if (shape->isAccessorDescriptor()) {
                 shape = obj->changeProperty(cx, shape, attrs,
                                             JSPROP_GETTER | JSPROP_SETTER,
                                             (attrs & JSPROP_GETTER)
                                             ? getter
@@ -4681,49 +4684,46 @@ CallResolveOp(JSContext *cx, JSObject *s
             *propp = (JSProperty *) shape;
         }
     }
 
     return true;
 }
 
 static JS_ALWAYS_INLINE bool
-LookupPropertyWithFlagsInline(JSContext *cx, JSObject *obj_, jsid id_, unsigned flags,
+LookupPropertyWithFlagsInline(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
                               JSObject **objp, JSProperty **propp)
 {
-    RootedVarObject obj(cx, obj_);
-    RootedVarId id(cx, id_);
-
     /* Search scopes starting with obj and following the prototype link. */
-    RootedVarObject start(cx, obj);
+    RootedVarObject current(cx, obj);
     while (true) {
-        const Shape *shape = obj->nativeLookup(cx, id);
+        const Shape *shape = current->nativeLookup(cx, id);
         if (shape) {
-            *objp = obj;
+            *objp = current;
             *propp = (JSProperty *) shape;
             return true;
         }
 
         /* Try obj's class resolve hook if id was not found in obj's scope. */
-        if (obj->getClass()->resolve != JS_ResolveStub) {
+        if (current->getClass()->resolve != JS_ResolveStub) {
             bool recursed;
-            if (!CallResolveOp(cx, start, obj, id, flags, objp, propp, &recursed))
+            if (!CallResolveOp(cx, obj, current, id, flags, objp, propp, &recursed))
                 return false;
             if (recursed)
                 break;
             if (*propp) {
                 /*
                  * For stats we do not recalculate protoIndex even if it was
                  * resolved on some other object.
                  */
                 return true;
             }
         }
 
-        JSObject *proto = obj->getProto();
+        JSObject *proto = current->getProto();
         if (!proto)
             break;
         if (!proto->isNative()) {
             if (!proto->lookupGeneric(cx, id, objp, propp))
                 return false;
 #ifdef DEBUG
             /*
              * Non-native objects must have either non-native lookup results,
@@ -4737,43 +4737,43 @@ LookupPropertyWithFlagsInline(JSContext 
             if (*propp && (*objp)->isNative()) {
                 while ((proto = proto->getProto()) != *objp)
                     JS_ASSERT(proto);
             }
 #endif
             return true;
         }
 
-        obj = proto;
+        current = proto;
     }
 
     *objp = NULL;
     *propp = NULL;
     return true;
 }
 
 JS_FRIEND_API(JSBool)
-js_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
-                  JSProperty **propp)
+baseops::LookupProperty(JSContext *cx, HandleObject obj, HandleId id, JSObject **objp,
+                        JSProperty **propp)
 {
     return LookupPropertyWithFlagsInline(cx, obj, id, cx->resolveFlags, objp, propp);
 }
 
 JS_FRIEND_API(JSBool)
-js_LookupElement(JSContext *cx, JSObject *obj, uint32_t index, JSObject **objp, JSProperty **propp)
-{
-    jsid id;
-    if (!IndexToId(cx, index, &id))
+baseops::LookupElement(JSContext *cx, HandleObject obj, uint32_t index, JSObject **objp, JSProperty **propp)
+{
+    RootedVarId id(cx);
+    if (!IndexToId(cx, index, id.address()))
         return false;
 
     return LookupPropertyWithFlagsInline(cx, obj, id, cx->resolveFlags, objp, propp);
 }
 
 bool
-js::LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, unsigned flags,
+js::LookupPropertyWithFlags(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
                             JSObject **objp, JSProperty **propp)
 {
     return LookupPropertyWithFlagsInline(cx, obj, id, flags, objp, propp);
 }
 
 bool
 js::FindPropertyHelper(JSContext *cx,
                        HandlePropertyName name, bool cacheResult, HandleObject scopeChain,
@@ -4895,17 +4895,17 @@ js::FindIdentifierBase(JSContext *cx, Ha
      * The test order here matters because IsCacheableNonGlobalScope
      * must not be passed a global object (i.e. one with null parent).
      */
     for (int scopeIndex = 0;
          obj->isGlobal() || IsCacheableNonGlobalScope(obj);
          scopeIndex++) {
         JSObject *pobj;
         JSProperty *prop;
-        if (!LookupPropertyWithFlags(cx, obj, name, cx->resolveFlags, &pobj, &prop))
+        if (!LookupPropertyWithFlags(cx, obj, name.value(), cx->resolveFlags, &pobj, &prop))
             return NULL;
         if (prop) {
             if (!pobj->isNative()) {
                 JS_ASSERT(obj->isGlobal());
                 return obj;
             }
             JS_ASSERT_IF(obj->isScope(), pobj->getClass() == obj->getClass());
             JS_PROPERTY_CACHE(cx).fill(cx, scopeChain, scopeIndex, pobj, (Shape *) prop);
@@ -4963,17 +4963,17 @@ js_NativeGetInline(JSContext *cx, JSObje
         analyze::Bytecode *code = script->analysis()->maybeCode(pc);
         if (code)
             code->accessGetter = true;
     }
 
     Root<const Shape*> rootShape(cx, &shape);
     RootObject pobjRoot(cx, &pobj);
 
-    if (!shape->get(cx, receiver, obj, pobj, vp))
+    if (!shape->get(cx, RootedVarObject(cx, receiver), obj, pobj, vp))
         return false;
 
     /* Update slotful shapes according to the value produced by the getter. */
     if (shape->hasSlot() && pobj->nativeContains(cx, *shape))
         pobj->nativeSetSlot(shape->slot(), *vp);
 
     return true;
 }
@@ -5006,21 +5006,20 @@ js_NativeSet(JSContext *cx, JSObject *ob
          * Such properties effectively function as data descriptors which are
          * not writable, so attempting to set such a property should do nothing
          * or throw if we're in strict mode.
          */
         if (!shape->hasGetterValue() && shape->hasDefaultSetter())
             return js_ReportGetterOnlyAssignment(cx);
     }
 
-    RootObject objRoot(cx, &obj);
     Root<const Shape *> shapeRoot(cx, &shape);
 
     int32_t sample = cx->runtime->propertyRemovals;
-    if (!shape->set(cx, obj, strict, vp))
+    if (!shape->set(cx, RootedVarObject(cx, obj), strict, vp))
         return false;
 
     /*
      * Update any slot for the shape with the value produced by the setter,
      * unless the setter deleted the shape.
      */
     if (shape->hasSlot() &&
         (JS_LIKELY(cx->runtime->propertyRemovals == sample) ||
@@ -5126,51 +5125,51 @@ js_GetPropertyHelperInline(JSContext *cx
 
 bool
 js::GetPropertyHelper(JSContext *cx, HandleObject obj, jsid id, uint32_t getHow, Value *vp)
 {
     return !!js_GetPropertyHelperInline(cx, obj, obj, id, getHow, vp);
 }
 
 JSBool
-js_GetProperty(JSContext *cx, HandleObject obj, HandleObject receiver, jsid id, Value *vp)
+baseops::GetProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id, Value *vp)
 {
     /* This call site is hot -- use the always-inlined variant of js_GetPropertyHelper(). */
     return js_GetPropertyHelperInline(cx, obj, receiver, id, 0, vp);
 }
 
 JSBool
-js_GetElement(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index, Value *vp)
+baseops::GetElement(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index, Value *vp)
 {
     jsid id;
     if (!IndexToId(cx, index, &id))
         return false;
 
     /* This call site is hot -- use the always-inlined variant of js_GetPropertyHelper(). */
     return js_GetPropertyHelperInline(cx, obj, receiver, id, 0, vp);
 }
 
 JSBool
-js::GetPropertyDefault(JSContext *cx, HandleObject obj, HandleId id, const Value &def, Value *vp)
+baseops::GetPropertyDefault(JSContext *cx, HandleObject obj, HandleId id, const Value &def, Value *vp)
 {
     JSProperty *prop;
     RootedVarObject obj2(cx);
     if (!LookupPropertyWithFlags(cx, obj, id, JSRESOLVE_QUALIFIED, obj2.address(), &prop))
         return false;
 
     if (!prop) {
         *vp = def;
         return true;
     }
 
-    return js_GetProperty(cx, obj2, id, vp);
+    return baseops::GetProperty(cx, obj2, id, vp);
 }
 
 JSBool
-js_GetMethod(JSContext *cx, HandleObject obj, jsid id, unsigned getHow, Value *vp)
+js::GetMethod(JSContext *cx, HandleObject obj, HandleId id, unsigned getHow, Value *vp)
 {
     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
 
     GenericIdOp op = obj->getOps()->getGeneric;
     if (!op) {
 #if JS_HAS_XML_SUPPORT
         JS_ASSERT(!obj->isXML());
 #endif
@@ -5225,43 +5224,42 @@ bool
 JSObject::reportNotExtensible(JSContext *cx, unsigned report)
 {
     return js_ReportValueErrorFlags(cx, report, JSMSG_OBJECT_NOT_EXTENSIBLE,
                                     JSDVG_IGNORE_STACK, ObjectValue(*this),
                                     NULL, NULL, NULL);
 }
 
 bool
-JSObject::callMethod(JSContext *cx, jsid id, unsigned argc, Value *argv, Value *vp)
+JSObject::callMethod(JSContext *cx, HandleId id, unsigned argc, Value *argv, Value *vp)
 {
     Value fval;
-    return js_GetMethod(cx, RootedVarObject(cx, this), id, 0, &fval) &&
+    return GetMethod(cx, RootedVarObject(cx, this), id, 0, &fval) &&
            Invoke(cx, ObjectValue(*this), fval, argc, argv, vp);
 }
 
 JSBool
-js_SetPropertyHelper(JSContext *cx, HandleObject obj, jsid id, unsigned defineHow,
-                     Value *vp, JSBool strict)
+baseops::SetPropertyHelper(JSContext *cx, HandleObject obj, HandleId id, unsigned defineHow,
+                           Value *vp, JSBool strict)
 {
     JSObject *pobj;
     JSProperty *prop;
     unsigned attrs, flags;
     int shortid;
     Class *clasp;
     PropertyOp getter;
     StrictPropertyOp setter;
     bool added;
 
     JS_ASSERT((defineHow & ~(DNP_CACHE_RESULT | DNP_UNQUALIFIED)) == 0);
-    RootId idRoot(cx, &id);
 
     if (JS_UNLIKELY(obj->watched())) {
         /* Fire watchpoints, if any. */
         WatchpointMap *wpmap = cx->compartment->watchpointMap;
-        if (wpmap && !wpmap->triggerWatchpoint(cx, obj, idRoot, vp))
+        if (wpmap && !wpmap->triggerWatchpoint(cx, obj, id, vp))
             return false;
     }
 
     if (!LookupPropertyWithFlags(cx, obj, id, cx->resolveFlags, &pobj, &prop))
         return false;
     if (prop) {
         if (!pobj->isNative()) {
             if (pobj->isProxy()) {
@@ -5419,100 +5417,101 @@ js_SetPropertyHelper(JSContext *cx, Hand
 
     if ((defineHow & DNP_CACHE_RESULT) && !added)
         JS_PROPERTY_CACHE(cx).fill(cx, obj, 0, obj, shape);
 
     return js_NativeSet(cx, obj, shape, added, strict, vp);
 }
 
 JSBool
-js_SetElementHelper(JSContext *cx, HandleObject obj, uint32_t index, unsigned defineHow,
-                    Value *vp, JSBool strict)
-{
-    jsid id;
-    if (!IndexToId(cx, index, &id))
+baseops::SetElementHelper(JSContext *cx, HandleObject obj, uint32_t index, unsigned defineHow,
+                          Value *vp, JSBool strict)
+{
+    RootedVarId id(cx);
+    if (!IndexToId(cx, index, id.address()))
         return false;
-    return js_SetPropertyHelper(cx, obj, id, defineHow, vp, strict);
+    return baseops::SetPropertyHelper(cx, obj, id, defineHow, vp, strict);
 }
 
 JSBool
-js_GetAttributes(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp)
-{
+baseops::GetAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp)
+{
+    JSObject *nobj;
     JSProperty *prop;
-    if (!js_LookupProperty(cx, obj, id, &obj, &prop))
+    if (!baseops::LookupProperty(cx, obj, id, &nobj, &prop))
         return false;
     if (!prop) {
         *attrsp = 0;
         return true;
     }
-    if (!obj->isNative())
-        return obj->getGenericAttributes(cx, id, attrsp);
+    if (!nobj->isNative())
+        return nobj->getGenericAttributes(cx, id, attrsp);
 
     const Shape *shape = (Shape *)prop;
     *attrsp = shape->attributes();
     return true;
 }
 
 JSBool
-js_GetElementAttributes(JSContext *cx, JSObject *obj, uint32_t index, unsigned *attrsp)
-{
+baseops::GetElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp)
+{
+    JSObject *nobj;
     JSProperty *prop;
-    if (!js_LookupElement(cx, obj, index, &obj, &prop))
+    if (!baseops::LookupElement(cx, obj, index, &nobj, &prop))
         return false;
     if (!prop) {
         *attrsp = 0;
         return true;
     }
-    if (!obj->isNative())
-        return obj->getElementAttributes(cx, index, attrsp);
+    if (!nobj->isNative())
+        return nobj->getElementAttributes(cx, index, attrsp);
 
     const Shape *shape = (Shape *)prop;
     *attrsp = shape->attributes();
     return true;
 }
 
 JSBool
-js_SetAttributes(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp)
-{
+baseops::SetAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp)
+{
+    JSObject *nobj;
     JSProperty *prop;
-    if (!js_LookupProperty(cx, obj, id, &obj, &prop))
+    if (!baseops::LookupProperty(cx, obj, id, &nobj, &prop))
         return false;
     if (!prop)
         return true;
-    return obj->isNative()
-           ? obj->changePropertyAttributes(cx, (Shape *) prop, *attrsp)
-           : obj->setGenericAttributes(cx, id, attrsp);
+    return nobj->isNative()
+           ? nobj->changePropertyAttributes(cx, (Shape *) prop, *attrsp)
+           : nobj->setGenericAttributes(cx, id, attrsp);
 }
 
 JSBool
-js_SetElementAttributes(JSContext *cx, JSObject *obj, uint32_t index, unsigned *attrsp)
-{
+baseops::SetElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp)
+{
+    JSObject *nobj;
     JSProperty *prop;
-    if (!js_LookupElement(cx, obj, index, &obj, &prop))
+    if (!baseops::LookupElement(cx, obj, index, &nobj, &prop))
         return false;
     if (!prop)
         return true;
-    return obj->isNative()
-           ? obj->changePropertyAttributes(cx, (Shape *) prop, *attrsp)
-           : obj->setElementAttributes(cx, index, attrsp);
+    return nobj->isNative()
+           ? nobj->changePropertyAttributes(cx, (Shape *) prop, *attrsp)
+           : nobj->setElementAttributes(cx, index, attrsp);
 }
 
 JSBool
-js_DeleteGeneric(JSContext *cx, JSObject *obj_, jsid id_, Value *rval, JSBool strict)
+baseops::DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, Value *rval, JSBool strict)
 {
     JSObject *proto;
     JSProperty *prop;
     const Shape *shape;
 
     rval->setBoolean(true);
 
-    RootedVarObject obj(cx, obj_);
-    RootedVarId id(cx, id_);
-
-    if (!js_LookupProperty(cx, obj, id, &proto, &prop))
+    if (!baseops::LookupProperty(cx, obj, id, &proto, &prop))
         return false;
     if (!prop || proto != obj) {
         /*
          * If no property, or the property comes from a prototype, call the
          * class's delProperty hook, passing rval as the result parameter.
          */
         return CallJSPropertyOp(cx, obj->getClass()->delProperty, obj, id, rval);
     }
@@ -5525,49 +5524,47 @@ js_DeleteGeneric(JSContext *cx, JSObject
         return true;
     }
 
     if (shape->hasSlot()) {
         const Value &v = obj->nativeGetSlot(shape->slot());
         GCPoke(cx->runtime, v);
     }
 
-    jsid userid;
-    if (!shape->getUserId(cx, &userid))
+    RootedVarId userid(cx);
+    if (!shape->getUserId(cx, userid.address()))
         return false;
 
     if (!CallJSPropertyOp(cx, obj->getClass()->delProperty, obj, userid, rval))
         return false;
     if (rval->isFalse())
         return true;
 
     return obj->removeProperty(cx, id) && js_SuppressDeletedProperty(cx, obj, id);
 }
 
 JSBool
-js_DeleteProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *rval, JSBool strict)
-{
-    return js_DeleteGeneric(cx, obj, NameToId(name), rval, strict);
+baseops::DeleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, Value *rval, JSBool strict)
+{
+    return baseops::DeleteGeneric(cx, obj, RootedVarId(cx, NameToId(name)), rval, strict);
 }
 
 JSBool
-js_DeleteElement(JSContext *cx, JSObject *obj_, uint32_t index, Value *rval, JSBool strict)
-{
-    RootedVarObject obj(cx, obj_);
-
-    jsid id;
-    if (!IndexToId(cx, index, &id))
+baseops::DeleteElement(JSContext *cx, HandleObject obj, uint32_t index, Value *rval, JSBool strict)
+{
+    RootedVarId id(cx);
+    if (!IndexToId(cx, index, id.address()))
         return false;
-    return js_DeleteGeneric(cx, obj, id, rval, strict);
+    return baseops::DeleteGeneric(cx, obj, id, rval, strict);
 }
 
 JSBool
-js_DeleteSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *rval, JSBool strict)
-{
-    return js_DeleteGeneric(cx, obj, SPECIALID_TO_JSID(sid), rval, strict);
+baseops::DeleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, Value *rval, JSBool strict)
+{
+    return baseops::DeleteGeneric(cx, obj, RootedVarId(cx, SPECIALID_TO_JSID(sid)), rval, strict);
 }
 
 namespace js {
 
 bool
 HasDataProperty(JSContext *cx, HandleObject obj, jsid id, Value *vp)
 {
     if (const Shape *shape = obj->nativeLookup(cx, id)) {
@@ -5586,17 +5583,17 @@ HasDataProperty(JSContext *cx, HandleObj
  * and |obj| as |this|, returning the result in *vp.
  *
  * This is a mini-abstraction for ES5 8.12.8 [[DefaultValue]], either steps 1-2
  * or steps 3-4.
  */
 static bool
 MaybeCallMethod(JSContext *cx, HandleObject obj, jsid id, Value *vp)
 {
-    if (!js_GetMethod(cx, obj, id, 0, vp))
+    if (!GetMethod(cx, obj, RootedVarId(cx, id), 0, vp))
         return false;
     if (!js_IsCallable(*vp)) {
         *vp = ObjectValue(*obj);
         return true;
     }
     return Invoke(cx, ObjectValue(*obj), *vp, 0, NULL, vp);
 }
 
@@ -5669,17 +5666,17 @@ DefaultValue(JSContext *cx, HandleObject
     js_ReportValueError2(cx, JSMSG_CANT_CONVERT_TO, JSDVG_SEARCH_STACK, ObjectValue(*obj), str,
                          (hint == JSTYPE_VOID) ? "primitive type" : JS_TYPE_STR(hint));
     return false;
 }
 
 } /* namespace js */
 
 JS_FRIEND_API(JSBool)
-JS_EnumerateState(JSContext *cx, JSObject *obj, JSIterateOp enum_op, Value *statep, jsid *idp)
+JS_EnumerateState(JSContext *cx, JSHandleObject obj, JSIterateOp enum_op, Value *statep, jsid *idp)
 {
     /* If the class has a custom JSCLASS_NEW_ENUMERATE hook, call it. */
     Class *clasp = obj->getClass();
     JSEnumerateOp enumerate = clasp->enumerate;
     if (clasp->flags & JSCLASS_NEW_ENUMERATE) {
         JS_ASSERT(enumerate != JS_EnumerateStub);
         return ((JSNewEnumerateOp) enumerate)(cx, obj, enum_op, statep, idp);
     }
@@ -5691,24 +5688,25 @@ JS_EnumerateState(JSContext *cx, JSObjec
     JS_ASSERT(enum_op == JSENUMERATE_INIT || enum_op == JSENUMERATE_INIT_ALL);
     statep->setMagic(JS_NATIVE_ENUMERATE);
     return true;
 }
 
 namespace js {
 
 JSBool
-CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
+CheckAccess(JSContext *cx, JSObject *obj_, HandleId id, JSAccessMode mode,
             Value *vp, unsigned *attrsp)
 {
     JSBool writing;
-    JSObject *pobj;
     JSProperty *prop;
     const Shape *shape;
 
+    RootedVarObject obj(cx, obj_), pobj(cx);
+
     while (JS_UNLIKELY(obj->isWith()))
         obj = obj->getProto();
 
     writing = (mode & JSACC_WRITE) != 0;
     switch (mode & JSACC_TYPEMASK) {
       case JSACC_PROTO:
         pobj = obj;
         if (!writing)
@@ -5719,17 +5717,17 @@ CheckAccess(JSContext *cx, JSObject *obj
       case JSACC_PARENT:
         JS_ASSERT(!writing);
         pobj = obj;
         vp->setObject(*obj->getParent());
         *attrsp = JSPROP_READONLY | JSPROP_PERMANENT;
         break;
 
       default:
-        if (!obj->lookupGeneric(cx, id, &pobj, &prop))
+        if (!obj->lookupGeneric(cx, id, pobj.address(), &prop))
             return JS_FALSE;
         if (!prop) {
             if (!writing)
                 vp->setUndefined();
             *attrsp = 0;
             pobj = obj;
             break;
         }
@@ -5770,17 +5768,17 @@ CheckAccess(JSContext *cx, JSObject *obj
     if (!check)
         check = cx->runtime->securityCallbacks->checkObjectAccess;
     return !check || check(cx, pobj, id, mode, vp);
 }
 
 }
 
 JSType
-js_TypeOf(JSContext *cx, JSObject *obj)
+baseops::TypeOf(JSContext *cx, HandleObject obj)
 {
     return obj->isCallable() ? JSTYPE_FUNCTION : JSTYPE_OBJECT;
 }
 
 bool
 js_IsDelegate(JSContext *cx, JSObject *obj, const Value &v)
 {
     if (v.isPrimitive())
@@ -6000,17 +5998,17 @@ js_ReportGetterOnlyAssignment(JSContext 
     return JS_ReportErrorFlagsAndNumber(cx,
                                         JSREPORT_WARNING | JSREPORT_STRICT |
                                         JSREPORT_STRICT_MODE_ERROR,
                                         js_GetErrorMessage, NULL,
                                         JSMSG_GETTER_ONLY);
 }
 
 JS_FRIEND_API(JSBool)
-js_GetterOnlyPropertyStub(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
+js_GetterOnlyPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, jsval *vp)
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_GETTER_ONLY);
     return JS_FALSE;
 }
 
 #ifdef DEBUG
 
 /*
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -112,122 +112,116 @@ CastAsObjectJsval(StrictPropertyOp op)
     {name, 0, (flags) | JSPROP_SHARED | JSPROP_NATIVE_ACCESSORS,              \
      (JSPropertyOp)getter, (JSStrictPropertyOp)setter}
 #define JS_PS_END {0, 0, 0, 0, 0}
 
 /******************************************************************************/
 
 typedef Vector<PropDesc, 1> PropDescArray;
 
-} /* namespace js */
+/*
+ * The baseops namespace encapsulates the default behavior when performing
+ * various operations on an object, irrespective of hooks installed in the
+ * object's class. In general, instance methods on the object itself should be
+ * called instead of calling these methods directly.
+ */
+namespace baseops {
 
 /*
  * On success, and if id was found, return true with *objp non-null and with a
  * property of *objp stored in *propp. If successful but id was not found,
  * return true with both *objp and *propp null.
  */
 extern JS_FRIEND_API(JSBool)
-js_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
-                  JSProperty **propp);
-
-namespace js {
+LookupProperty(JSContext *cx, HandleObject obj, HandleId id, JSObject **objp,
+               JSProperty **propp);
 
 inline bool
-LookupProperty(JSContext *cx, JSObject *obj, PropertyName *name,
+LookupProperty(JSContext *cx, HandleObject obj, PropertyName *name,
                JSObject **objp, JSProperty **propp)
 {
-    return js_LookupProperty(cx, obj, NameToId(name), objp, propp);
-}
-
+    return LookupProperty(cx, obj, RootedVarId(cx, NameToId(name)), objp, propp);
 }
 
 extern JS_FRIEND_API(JSBool)
-js_LookupElement(JSContext *cx, JSObject *obj, uint32_t index,
-                 JSObject **objp, JSProperty **propp);
+LookupElement(JSContext *cx, HandleObject obj, uint32_t index,
+              JSObject **objp, JSProperty **propp);
 
 extern JSBool
-js_DefineProperty(JSContext *cx, JSObject *obj, jsid id, const js::Value *value,
-                  JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
+DefineProperty(JSContext *cx, HandleObject obj, HandleId id, const js::Value *value,
+               JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
 
 extern JSBool
-js_DefineElement(JSContext *cx, JSObject *obj, uint32_t index, const js::Value *value,
-                 JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
+DefineElement(JSContext *cx, HandleObject obj, uint32_t index, const js::Value *value,
+              JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
 
 extern JSBool
-js_GetProperty(JSContext *cx, js::HandleObject obj, js::HandleObject receiver, jsid id, js::Value *vp);
+GetProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id, js::Value *vp);
 
 extern JSBool
-js_GetElement(JSContext *cx, js::HandleObject obj, js::HandleObject receiver, uint32_t, js::Value *vp);
+GetElement(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index, js::Value *vp);
 
 inline JSBool
-js_GetProperty(JSContext *cx, js::HandleObject obj, jsid id, js::Value *vp)
+GetProperty(JSContext *cx, HandleObject obj, HandleId id, js::Value *vp)
 {
-    return js_GetProperty(cx, obj, obj, id, vp);
+    return GetProperty(cx, obj, obj, id, vp);
 }
 
 inline JSBool
-js_GetElement(JSContext *cx, js::HandleObject obj, uint32_t index, js::Value *vp)
+GetElement(JSContext *cx, HandleObject obj, uint32_t index, js::Value *vp)
 {
-    return js_GetElement(cx, obj, obj, index, vp);
+    return GetElement(cx, obj, obj, index, vp);
 }
 
-namespace js {
-
 extern JSBool
-GetPropertyDefault(JSContext *cx, js::HandleObject obj, js::HandleId id, const Value &def, Value *vp);
-
-} /* namespace js */
+GetPropertyDefault(JSContext *cx, HandleObject obj, HandleId id, const Value &def, Value *vp);
 
 extern JSBool
-js_SetPropertyHelper(JSContext *cx, js::HandleObject obj, jsid id, unsigned defineHow,
-                     js::Value *vp, JSBool strict);
-
-namespace js {
+SetPropertyHelper(JSContext *cx, HandleObject obj, HandleId id, unsigned defineHow,
+                  Value *vp, JSBool strict);
 
 inline bool
 SetPropertyHelper(JSContext *cx, HandleObject obj, PropertyName *name, unsigned defineHow,
                   Value *vp, JSBool strict)
 {
-    return !!js_SetPropertyHelper(cx, obj, NameToId(name), defineHow, vp, strict);
+    return SetPropertyHelper(cx, obj, RootedVarId(cx, NameToId(name)), defineHow, vp, strict);
 }
 
-} /* namespace js */
-
 extern JSBool
-js_SetElementHelper(JSContext *cx, js::HandleObject obj, uint32_t index, unsigned defineHow,
-                    js::Value *vp, JSBool strict);
+SetElementHelper(JSContext *cx, HandleObject obj, uint32_t index, unsigned defineHow,
+                 Value *vp, JSBool strict);
+
+extern JSType
+TypeOf(JSContext *cx, HandleObject obj);
 
 extern JSBool
-js_GetAttributes(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp);
+GetAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp);
 
 extern JSBool
-js_GetElementAttributes(JSContext *cx, JSObject *obj, uint32_t index, unsigned *attrsp);
-
-extern JSBool
-js_SetAttributes(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp);
+SetAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp);
 
 extern JSBool
-js_SetElementAttributes(JSContext *cx, JSObject *obj, uint32_t index, unsigned *attrsp);
+GetElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp);
 
 extern JSBool
-js_DeleteProperty(JSContext *cx, JSObject *obj, js::PropertyName *name, js::Value *rval, JSBool strict);
+SetElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp);
 
 extern JSBool
-js_DeleteElement(JSContext *cx, JSObject *obj, uint32_t index, js::Value *rval, JSBool strict);
+DeleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, Value *rval, JSBool strict);
 
 extern JSBool
-js_DeleteSpecial(JSContext *cx, JSObject *obj, js::SpecialId sid, js::Value *rval, JSBool strict);
+DeleteElement(JSContext *cx, HandleObject obj, uint32_t index, Value *rval, JSBool strict);
 
 extern JSBool
-js_DeleteGeneric(JSContext *cx, JSObject *obj, jsid id, js::Value *rval, JSBool strict);
+DeleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, Value *rval, JSBool strict);
 
-extern JSType
-js_TypeOf(JSContext *cx, JSObject *obj);
+extern JSBool
+DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, Value *rval, JSBool strict);
 
-namespace js {
+} /* namespace js::baseops */
 
 /* ES5 8.12.8. */
 extern JSBool
 DefaultValue(JSContext *cx, HandleObject obj, JSType hint, Value *vp);
 
 extern Class ArrayClass;
 extern Class ArrayBufferClass;
 extern Class BlockClass;
@@ -720,17 +714,17 @@ struct JSObject : public js::ObjectImpl
     /*
      * Back to generic stuff.
      */
     inline bool isCallable();
 
     inline void finish(js::FreeOp *fop);
     JS_ALWAYS_INLINE void finalize(js::FreeOp *fop);
 
-    inline bool hasProperty(JSContext *cx, jsid id, bool *foundp, unsigned flags = 0);
+    inline bool hasProperty(JSContext *cx, js::HandleId id, bool *foundp, unsigned flags = 0);
 
     /*
      * Allocate and free an object slot.
      *
      * FIXME: bug 593129 -- slot allocation should be done by object methods
      * after calling object-parameter-free shape methods, avoiding coupling
      * logic across the object vs. shape module wall.
      */
@@ -742,17 +736,17 @@ struct JSObject : public js::ObjectImpl
     bool reportNotExtensible(JSContext *cx, unsigned report = JSREPORT_ERROR);
 
     /*
      * Get the property with the given id, then call it as a function with the
      * given arguments, providing this object as |this|. If the property isn't
      * callable a TypeError will be thrown. On success the value returned by
      * the call is stored in *vp.
      */
-    bool callMethod(JSContext *cx, jsid id, unsigned argc, js::Value *argv, js::Value *vp);
+    bool callMethod(JSContext *cx, js::HandleId id, unsigned argc, js::Value *argv, js::Value *vp);
 
   private:
     js::Shape *getChildProperty(JSContext *cx, js::Shape *parent, js::StackShape &child);
 
   protected:
     /*
      * Internal helper that adds a shape not yet mapped by this object.
      *
@@ -808,24 +802,24 @@ struct JSObject : public js::ObjectImpl
     inline bool changePropertyAttributes(JSContext *cx, js::Shape *shape, unsigned attrs);
 
     /* Remove the property named by id from this object. */
     bool removeProperty(JSContext *cx, jsid id);
 
     /* Clear the scope, making it empty. */
     void clear(JSContext *cx);
 
-    inline JSBool lookupGeneric(JSContext *cx, jsid id, JSObject **objp, JSProperty **propp);
+    inline JSBool lookupGeneric(JSContext *cx, js::HandleId id, JSObject **objp, JSProperty **propp);
     inline JSBool lookupProperty(JSContext *cx, js::PropertyName *name, JSObject **objp, JSProperty **propp);
     inline JSBool lookupElement(JSContext *cx, uint32_t index,
                                 JSObject **objp, JSProperty **propp);
     inline JSBool lookupSpecial(JSContext *cx, js::SpecialId sid,
                                 JSObject **objp, JSProperty **propp);
 
-    inline JSBool defineGeneric(JSContext *cx, jsid id, const js::Value &value,
+    inline JSBool defineGeneric(JSContext *cx, js::HandleId id, const js::Value &value,
                                 JSPropertyOp getter = JS_PropertyStub,
                                 JSStrictPropertyOp setter = JS_StrictPropertyStub,
                                 unsigned attrs = JSPROP_ENUMERATE);
     inline JSBool defineProperty(JSContext *cx, js::PropertyName *name, const js::Value &value,
                                  JSPropertyOp getter = JS_PropertyStub,
                                  JSStrictPropertyOp setter = JS_StrictPropertyStub,
                                  unsigned attrs = JSPROP_ENUMERATE);
 
@@ -833,52 +827,52 @@ struct JSObject : public js::ObjectImpl
                                 JSPropertyOp getter = JS_PropertyStub,
                                 JSStrictPropertyOp setter = JS_StrictPropertyStub,
                                 unsigned attrs = JSPROP_ENUMERATE);
     inline JSBool defineSpecial(JSContext *cx, js::SpecialId sid, const js::Value &value,
                                 JSPropertyOp getter = JS_PropertyStub,
                                 JSStrictPropertyOp setter = JS_StrictPropertyStub,
                                 unsigned attrs = JSPROP_ENUMERATE);
 
-    inline JSBool getGeneric(JSContext *cx, JSObject *receiver, jsid id, js::Value *vp);
-    inline JSBool getProperty(JSContext *cx, JSObject *receiver, js::PropertyName *name,
+    inline JSBool getGeneric(JSContext *cx, js::HandleObject receiver, js::HandleId id, js::Value *vp);
+    inline JSBool getProperty(JSContext *cx, js::HandleObject receiver, js::PropertyName *name,
                               js::Value *vp);
-    inline JSBool getElement(JSContext *cx, JSObject *receiver, uint32_t index, js::Value *vp);
+    inline JSBool getElement(JSContext *cx, js::HandleObject receiver, uint32_t index, js::Value *vp);
     /* If element is not present (e.g. array hole) *present is set to
        false and the contents of *vp are unusable garbage. */
-    inline JSBool getElementIfPresent(JSContext *cx, JSObject *receiver, uint32_t index,
+    inline JSBool getElementIfPresent(JSContext *cx, js::HandleObject receiver, uint32_t index,
                                       js::Value *vp, bool *present);
-    inline JSBool getSpecial(JSContext *cx, JSObject *receiver, js::SpecialId sid, js::Value *vp);
+    inline JSBool getSpecial(JSContext *cx, js::HandleObject receiver, js::SpecialId sid, js::Value *vp);
 
-    inline JSBool getGeneric(JSContext *cx, jsid id, js::Value *vp);
+    inline JSBool getGeneric(JSContext *cx, js::HandleId id, js::Value *vp);
     inline JSBool getProperty(JSContext *cx, js::PropertyName *name, js::Value *vp);
     inline JSBool getElement(JSContext *cx, uint32_t index, js::Value *vp);
     inline JSBool getSpecial(JSContext *cx, js::SpecialId sid, js::Value *vp);
 
-    inline JSBool setGeneric(JSContext *cx, jsid id, js::Value *vp, JSBool strict);
+    inline JSBool setGeneric(JSContext *cx, js::HandleId id, js::Value *vp, JSBool strict);
     inline JSBool setProperty(JSContext *cx, js::PropertyName *name, js::Value *vp, JSBool strict);
     inline JSBool setElement(JSContext *cx, uint32_t index, js::Value *vp, JSBool strict);
     inline JSBool setSpecial(JSContext *cx, js::SpecialId sid, js::Value *vp, JSBool strict);
 
-    JSBool nonNativeSetProperty(JSContext *cx, jsid id, js::Value *vp, JSBool strict);
+    JSBool nonNativeSetProperty(JSContext *cx, js::HandleId id, js::Value *vp, JSBool strict);
     JSBool nonNativeSetElement(JSContext *cx, uint32_t index, js::Value *vp, JSBool strict);
 
-    inline JSBool getGenericAttributes(JSContext *cx, jsid id, unsigned *attrsp);
+    inline JSBool getGenericAttributes(JSContext *cx, js::HandleId id, unsigned *attrsp);
     inline JSBool getPropertyAttributes(JSContext *cx, js::PropertyName *name, unsigned *attrsp);
     inline JSBool getElementAttributes(JSContext *cx, uint32_t index, unsigned *attrsp);
     inline JSBool getSpecialAttributes(JSContext *cx, js::SpecialId sid, unsigned *attrsp);
 
-    inline JSBool setGenericAttributes(JSContext *cx, jsid id, unsigned *attrsp);
+    inline JSBool setGenericAttributes(JSContext *cx, js::HandleId id, unsigned *attrsp);
     inline JSBool setPropertyAttributes(JSContext *cx, js::PropertyName *name, unsigned *attrsp);
     inline JSBool setElementAttributes(JSContext *cx, uint32_t index, unsigned *attrsp);
     inline JSBool setSpecialAttributes(JSContext *cx, js::SpecialId sid, unsigned *attrsp);
 
-    inline bool deleteProperty(JSContext *cx, js::PropertyName *name, js::Value *rval, bool strict);
+    inline bool deleteProperty(JSContext *cx, js::HandlePropertyName name, js::Value *rval, bool strict);
     inline bool deleteElement(JSContext *cx, uint32_t index, js::Value *rval, bool strict);
-    inline bool deleteSpecial(JSContext *cx, js::SpecialId sid, js::Value *rval, bool strict);
+    inline bool deleteSpecial(JSContext *cx, js::HandleSpecialId sid, js::Value *rval, bool strict);
     bool deleteByValue(JSContext *cx, const js::Value &property, js::Value *rval, bool strict);
 
     inline bool enumerate(JSContext *cx, JSIterateOp iterop, js::Value *statep, jsid *idp);
     inline bool defaultValue(JSContext *cx, JSType hint, js::Value *vp);
     inline JSType typeOf(JSContext *cx);
     inline JSObject *thisObject(JSContext *cx);
 
     static bool thisObject(JSContext *cx, const js::Value &v, js::Value *vp);
@@ -1064,21 +1058,21 @@ js_LeaveSharpObject(JSContext *cx, JSIdA
 extern void
 js_TraceSharpMap(JSTracer *trc, JSSharpObjectMap *map);
 
 extern JSBool
 js_HasOwnPropertyHelper(JSContext *cx, js::LookupGenericOp lookup, unsigned argc,
                         js::Value *vp);
 
 extern JSBool
-js_HasOwnProperty(JSContext *cx, js::LookupGenericOp lookup, js::HandleObject obj, jsid id,
+js_HasOwnProperty(JSContext *cx, js::LookupGenericOp lookup, js::HandleObject obj, js::HandleId id,
                   JSObject **objp, JSProperty **propp);
 
 extern JSBool
-js_PropertyIsEnumerable(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
+js_PropertyIsEnumerable(JSContext *cx, js::HandleObject obj, js::HandleId id, js::Value *vp);
 
 #if JS_HAS_OBJ_PROTO_PROP
 extern JSPropertySpec object_props[];
 #else
 #define object_props NULL
 #endif
 
 extern JSFunctionSpec object_methods[];
@@ -1165,41 +1159,42 @@ const unsigned DNP_UNQUALIFIED  = 4;   /
                                        the defineHow argument of
                                        js_SetPropertyHelper. */
 const unsigned DNP_SKIP_TYPE    = 8;   /* Don't update type information */
 
 /*
  * Return successfully added or changed shape or NULL on error.
  */
 extern const Shape *
-DefineNativeProperty(JSContext *cx, HandleObject obj, jsid id, const Value &value,
+DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, const Value &value,
                      PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
                      unsigned flags, int shortid, unsigned defineHow = 0);
 
 inline const Shape *
 DefineNativeProperty(JSContext *cx, HandleObject obj, PropertyName *name, const Value &value,
                      PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
                      unsigned flags, int shortid, unsigned defineHow = 0)
 {
-    return DefineNativeProperty(cx, obj, NameToId(name), value, getter, setter, attrs, flags,
+    return DefineNativeProperty(cx, obj, RootedVarId(cx, NameToId(name)),
+                                value, getter, setter, attrs, flags,
                                 shortid, defineHow);
 }
 
 /*
  * Specialized subroutine that allows caller to preset JSRESOLVE_* flags.
  */
 extern bool
-LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, unsigned flags,
+LookupPropertyWithFlags(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
                         JSObject **objp, JSProperty **propp);
 
 inline bool
-LookupPropertyWithFlags(JSContext *cx, JSObject *obj, PropertyName *name, unsigned flags,
+LookupPropertyWithFlags(JSContext *cx, HandleObject obj, PropertyName *name, unsigned flags,
                         JSObject **objp, JSProperty **propp)
 {
-    return LookupPropertyWithFlags(cx, obj, NameToId(name), flags, objp, propp);
+    return LookupPropertyWithFlags(cx, obj, RootedVarId(cx, NameToId(name)), flags, objp, propp);
 }
 
 /*
  * Call the [[DefineOwnProperty]] internal method of obj.
  *
  * If obj is an array, this follows ES5 15.4.5.1.
  * If obj is any other native object, this follows ES5 8.12.9.
  * If obj is a proxy, this calls the proxy handler's defineProperty method.
@@ -1243,17 +1238,17 @@ FindProperty(JSContext *cx, HandleProper
 extern JSObject *
 FindIdentifierBase(JSContext *cx, HandleObject scopeChain, HandlePropertyName name);
 
 }
 
 extern JSObject *
 js_FindVariableScope(JSContext *cx, JSFunction **funp);
 
-/* JSGET_CACHE_RESULT is the analogue of DNP_CACHE_RESULT for js_GetMethod. */
+/* JSGET_CACHE_RESULT is the analogue of DNP_CACHE_RESULT for GetMethod. */
 const unsigned JSGET_CACHE_RESULT = 1; // from a caching interpreter opcode
 
 /*
  * NB: js_NativeGet and js_NativeSet are called with the scope containing shape
  * (pobj's scope for Get, obj's for Set) locked, and on successful return, that
  * scope is again locked.  But on failure, both functions return false with the
  * scope containing shape unlocked.
  */
@@ -1280,48 +1275,40 @@ bool
 GetOwnPropertyDescriptor(JSContext *cx, HandleObject obj, HandleId id, PropertyDescriptor *desc);
 
 bool
 GetOwnPropertyDescriptor(JSContext *cx, HandleObject obj, HandleId id, Value *vp);
 
 bool
 NewPropertyDescriptorObject(JSContext *cx, const PropertyDescriptor *desc, Value *vp);
 
-} /* namespace js */
-
 extern JSBool
-js_GetMethod(JSContext *cx, js::HandleObject obj, jsid id, unsigned getHow, js::Value *vp);
-
-namespace js {
+GetMethod(JSContext *cx, HandleObject obj, HandleId id, unsigned getHow, Value *vp);
 
 inline bool
 GetMethod(JSContext *cx, HandleObject obj, PropertyName *name, unsigned getHow, Value *vp)
 {
-    return js_GetMethod(cx, obj, NameToId(name), getHow, vp);
+    return GetMethod(cx, obj, RootedVarId(cx, NameToId(name)), getHow, vp);
 }
 
-} /* namespace js */
-
-namespace js {
-
 /*
  * If obj has an already-resolved data property for id, return true and
  * store the property value in *vp.
  */
 extern bool
 HasDataProperty(JSContext *cx, HandleObject obj, jsid id, Value *vp);
 
 inline bool
 HasDataProperty(JSContext *cx, HandleObject obj, PropertyName *name, Value *vp)
 {
     return HasDataProperty(cx, obj, NameToId(name), vp);
 }
 
 extern JSBool
-CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
+CheckAccess(JSContext *cx, JSObject *obj, HandleId id, JSAccessMode mode,
             js::Value *vp, unsigned *attrsp);
 
 } /* namespace js */
 
 extern bool
 js_IsDelegate(JSContext *cx, JSObject *obj, const js::Value &v);
 
 /*
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -82,174 +82,177 @@
 #include "vm/ObjectImpl-inl.h"
 #include "vm/RegExpStatics-inl.h"
 #include "vm/String-inl.h"
 
 inline bool
 JSObject::enumerate(JSContext *cx, JSIterateOp iterop, js::Value *statep, jsid *idp)
 {
     JSNewEnumerateOp op = getOps()->enumerate;
-    return (op ? op : JS_EnumerateState)(cx, this, iterop, statep, idp);
+    return (op ? op : JS_EnumerateState)(cx, js::RootedVarObject(cx, this), iterop, statep, idp);
 }
 
 inline bool
 JSObject::defaultValue(JSContext *cx, JSType hint, js::Value *vp)
 {
+    js::RootedVarObject self(cx, this);
+
     JSConvertOp op = getClass()->convert;
     bool ok;
     if (op == JS_ConvertStub)
-        ok = js::DefaultValue(cx, js::RootedVarObject(cx, this), hint, vp);
+        ok = js::DefaultValue(cx, self, hint, vp);
     else
-        ok = op(cx, this, hint, vp);
+        ok = op(cx, self, hint, vp);
     JS_ASSERT_IF(ok, vp->isPrimitive());
     return ok;
 }
 
 inline JSType
 JSObject::typeOf(JSContext *cx)
 {
     js::TypeOfOp op = getOps()->typeOf;
-    return (op ? op : js_TypeOf)(cx, this);
+    return (op ? op : js::baseops::TypeOf)(cx, js::RootedVarObject(cx, this));
 }
 
 inline JSObject *
 JSObject::thisObject(JSContext *cx)
 {
     JSObjectOp op = getOps()->thisObject;
-    return op ? op(cx, this) : this;
+    return op ? op(cx, js::RootedVarObject(cx, this)) : this;
 }
 
 inline JSBool
-JSObject::setGeneric(JSContext *cx, jsid id, js::Value *vp, JSBool strict)
+JSObject::setGeneric(JSContext *cx, js::HandleId id, js::Value *vp, JSBool strict)
 {
     if (getOps()->setGeneric)
         return nonNativeSetProperty(cx, id, vp, strict);
-    return js_SetPropertyHelper(cx,
-                                js::RootedVarObject(cx, this),
-                                js::RootedVarId(cx, id),
-                                0, vp, strict);
+    return js::baseops::SetPropertyHelper(cx,
+                                          js::RootedVarObject(cx, this),
+                                          id, 0, vp, strict);
 }
 
 inline JSBool
 JSObject::setProperty(JSContext *cx, js::PropertyName *name, js::Value *vp, JSBool strict)
 {
-    return setGeneric(cx, js::NameToId(name), vp, strict);
+    return setGeneric(cx, js::RootedVarId(cx, js::NameToId(name)), vp, strict);
 }
 
 inline JSBool
 JSObject::setElement(JSContext *cx, uint32_t index, js::Value *vp, JSBool strict)
 {
     if (getOps()->setElement)
         return nonNativeSetElement(cx, index, vp, strict);
-    return js_SetElementHelper(cx, js::RootedVarObject(cx, this), index, 0, vp, strict);
+    return js::baseops::SetElementHelper(cx, js::RootedVarObject(cx, this), index, 0, vp, strict);
 }
 
 inline JSBool
 JSObject::setSpecial(JSContext *cx, js::SpecialId sid, js::Value *vp, JSBool strict)
 {
-    return setGeneric(cx, SPECIALID_TO_JSID(sid), vp, strict);
+    return setGeneric(cx, js::RootedVarId(cx, SPECIALID_TO_JSID(sid)), vp, strict);
 }
 
 inline JSBool
-JSObject::setGenericAttributes(JSContext *cx, jsid id, unsigned *attrsp)
+JSObject::setGenericAttributes(JSContext *cx, js::HandleId id, unsigned *attrsp)
 {
     js::types::MarkTypePropertyConfigured(cx, this, id);
     js::GenericAttributesOp op = getOps()->setGenericAttributes;
-    return (op ? op : js_SetAttributes)(cx, this, id, attrsp);
+    return (op ? op : js::baseops::SetAttributes)(cx, js::RootedVarObject(cx, this), id, attrsp);
 }
 
 inline JSBool
 JSObject::setPropertyAttributes(JSContext *cx, js::PropertyName *name, unsigned *attrsp)
 {
-    return setGenericAttributes(cx, js::NameToId(name), attrsp);
+    return setGenericAttributes(cx, js::RootedVarId(cx, js::NameToId(name)), attrsp);
 }
 
 inline JSBool
 JSObject::setElementAttributes(JSContext *cx, uint32_t index, unsigned *attrsp)
 {
     js::ElementAttributesOp op = getOps()->setElementAttributes;
-    return (op ? op : js_SetElementAttributes)(cx, this, index, attrsp);
+    return (op ? op : js::baseops::SetElementAttributes)(cx, js::RootedVarObject(cx, this), index, attrsp);
 }
 
 inline JSBool
 JSObject::setSpecialAttributes(JSContext *cx, js::SpecialId sid, unsigned *attrsp)
 {
-    return setGenericAttributes(cx, SPECIALID_TO_JSID(sid), attrsp);
+    return setGenericAttributes(cx, js::RootedVarId(cx, SPECIALID_TO_JSID(sid)), attrsp);
 }
 
 inline bool
 JSObject::changePropertyAttributes(JSContext *cx, js::Shape *shape, unsigned attrs)
 {
     return !!changeProperty(cx, shape, attrs, 0, shape->getter(), shape->setter());
 }
 
 inline JSBool
-JSObject::getGeneric(JSContext *cx, JSObject *receiver, jsid id, js::Value *vp)
+JSObject::getGeneric(JSContext *cx, js::HandleObject receiver, js::HandleId id, js::Value *vp)
 {
+    js::RootedVarObject self(cx, this);
+
     js::GenericIdOp op = getOps()->getGeneric;
     if (op) {
-        if (!op(cx, this, receiver, id, vp))
+        if (!op(cx, self, receiver, id, vp))
             return false;
     } else {
-        if (!js_GetProperty(cx, js::RootedVarObject(cx, this), js::RootedVarObject(cx, receiver), id, vp))
+        if (!js::baseops::GetProperty(cx, self, receiver, id, vp))
             return false;
     }
     return true;
 }
 
 inline JSBool
-JSObject::getProperty(JSContext *cx, JSObject *receiver, js::PropertyName *name, js::Value *vp)
+JSObject::getProperty(JSContext *cx, js::HandleObject receiver, js::PropertyName *name, js::Value *vp)
 {
-    return getGeneric(cx, receiver, js::NameToId(name), vp);
+    return getGeneric(cx, receiver, js::RootedVarId(cx, js::NameToId(name)), vp);
 }
 
 inline JSBool
-JSObject::getGeneric(JSContext *cx, jsid id, js::Value *vp)
+JSObject::getGeneric(JSContext *cx, js::HandleId id, js::Value *vp)
 {
-    return getGeneric(cx, this, id, vp);
+    return getGeneric(cx, js::RootedVarObject(cx, this), id, vp);
 }
 
 inline JSBool
 JSObject::getProperty(JSContext *cx, js::PropertyName *name, js::Value *vp)
 {
-    return getGeneric(cx, js::NameToId(name), vp);
+    return getGeneric(cx, js::RootedVarId(cx, js::NameToId(name)), vp);
 }
 
 inline bool
-JSObject::deleteProperty(JSContext *cx, js::PropertyName *name, js::Value *rval, bool strict)
+JSObject::deleteProperty(JSContext *cx, js::HandlePropertyName name, js::Value *rval, bool strict)
 {
     jsid id = js::NameToId(name);
     js::types::AddTypePropertyId(cx, this, id, js::types::Type::UndefinedType());
     js::types::MarkTypePropertyConfigured(cx, this, id);
     js::DeletePropertyOp op = getOps()->deleteProperty;
-    return (op ? op : js_DeleteProperty)(cx, this, name, rval, strict);
+    return (op ? op : js::baseops::DeleteProperty)(cx, js::RootedVarObject(cx, this), name, rval, strict);
 }
 
 inline bool
 JSObject::deleteElement(JSContext *cx, uint32_t index, js::Value *rval, bool strict)
 {
     js::RootedVarObject self(cx, this);
 
     jsid id;
     if (!js::IndexToId(cx, index, &id))
         return false;
     js::types::AddTypePropertyId(cx, self, id, js::types::Type::UndefinedType());
     js::types::MarkTypePropertyConfigured(cx, self, id);
     js::DeleteElementOp op = self->getOps()->deleteElement;
-    return (op ? op : js_DeleteElement)(cx, self, index, rval, strict);
+    return (op ? op : js::baseops::DeleteElement)(cx, self, index, rval, strict);
 }
 
 inline bool
-JSObject::deleteSpecial(JSContext *cx, js::SpecialId sid, js::Value *rval, bool strict)
+JSObject::deleteSpecial(JSContext *cx, js::HandleSpecialId sid, js::Value *rval, bool strict)
 {
     jsid id = SPECIALID_TO_JSID(sid);
     js::types::AddTypePropertyId(cx, this, id, js::types::Type::UndefinedType());
     js::types::MarkTypePropertyConfigured(cx, this, id);
     js::DeleteSpecialOp op = getOps()->deleteSpecial;
-    return (op ? op : js_DeleteSpecial)(cx, this, sid, rval, strict);
+    return (op ? op : js::baseops::DeleteSpecial)(cx, js::RootedVarObject(cx, this), sid, rval, strict);
 }
 
 inline void
 JSObject::finalize(js::FreeOp *fop)
 {
     js::Probes::finalizeObject(this);
 
     if (!fop->onBackgroundThread()) {
@@ -928,17 +931,17 @@ JSObject::finish(js::FreeOp *fop)
 {
     if (hasDynamicSlots())
         fop->free_(slots);
     if (hasDynamicElements())
         fop->free_(getElementsHeader());
 }
 
 inline bool
-JSObject::hasProperty(JSContext *cx, jsid id, bool *foundp, unsigned flags)
+JSObject::hasProperty(JSContext *cx, js::HandleId id, bool *foundp, unsigned flags)
 {
     JSObject *pobj;
     JSProperty *prop;
     JSAutoResolveFlags rf(cx, flags);
     if (!lookupGeneric(cx, id, &pobj, &prop))
         return false;
     *foundp = !!prop;
     return true;
@@ -1038,119 +1041,128 @@ JSObject::sizeOfExcludingThis(JSMallocSi
     if (isArguments()) {
         *miscSize += asArguments().sizeOfMisc(mallocSizeOf);
     } else if (isRegExpStatics()) {
         *miscSize += js::SizeOfRegExpStaticsData(this, mallocSizeOf);
     }
 }
 
 inline JSBool
-JSObject::lookupGeneric(JSContext *cx, jsid id, JSObject **objp, JSProperty **propp)
+JSObject::lookupGeneric(JSContext *cx, js::HandleId id, JSObject **objp, JSProperty **propp)
 {
+    js::RootedVarObject self(cx, this);
+
     js::LookupGenericOp op = getOps()->lookupGeneric;
-    return (op ? op : js_LookupProperty)(cx, this, id, objp, propp);
+    if (op)
+        return op(cx, self, id, objp, propp);
+    return js::baseops::LookupProperty(cx, self, id, objp, propp);
 }
 
 inline JSBool
 JSObject::lookupProperty(JSContext *cx, js::PropertyName *name, JSObject **objp, JSProperty **propp)
 {
-    return lookupGeneric(cx, js::NameToId(name), objp, propp);
+    return lookupGeneric(cx, js::RootedVarId(cx, js::NameToId(name)), objp, propp);
 }
 
 inline JSBool
-JSObject::defineGeneric(JSContext *cx, jsid id, const js::Value &value,
+JSObject::defineGeneric(JSContext *cx, js::HandleId id, const js::Value &value,
                         JSPropertyOp getter /* = JS_PropertyStub */,
                         JSStrictPropertyOp setter /* = JS_StrictPropertyStub */,
                         unsigned attrs /* = JSPROP_ENUMERATE */)
 {
+    js::RootedVarObject self(cx, this);
+
     JS_ASSERT(!(attrs & JSPROP_NATIVE_ACCESSORS));
     js::DefineGenericOp op = getOps()->defineGeneric;
-    return (op ? op : js_DefineProperty)(cx, this, id, &value, getter, setter, attrs);
+    return (op ? op : js::baseops::DefineProperty)(cx, self, id, &value, getter, setter, attrs);
 }
 
 inline JSBool
 JSObject::defineProperty(JSContext *cx, js::PropertyName *name, const js::Value &value,
                         JSPropertyOp getter /* = JS_PropertyStub */,
                         JSStrictPropertyOp setter /* = JS_StrictPropertyStub */,
                         unsigned attrs /* = JSPROP_ENUMERATE */)
 {
-    return defineGeneric(cx, js::NameToId(name), value, getter, setter, attrs);
+    return defineGeneric(cx, js::RootedVarId(cx, js::NameToId(name)), value, getter, setter, attrs);
 }
 
 inline JSBool
 JSObject::defineElement(JSContext *cx, uint32_t index, const js::Value &value,
                         JSPropertyOp getter /* = JS_PropertyStub */,
                         JSStrictPropertyOp setter /* = JS_StrictPropertyStub */,
                         unsigned attrs /* = JSPROP_ENUMERATE */)
 {
+    js::RootedVarObject self(cx, this);
+
     js::DefineElementOp op = getOps()->defineElement;
-    return (op ? op : js_DefineElement)(cx, this, index, &value, getter, setter, attrs);
+    return (op ? op : js::baseops::DefineElement)(cx, self, index, &value, getter, setter, attrs);
 }
 
 inline JSBool
 JSObject::defineSpecial(JSContext *cx, js::SpecialId sid, const js::Value &value,
                         JSPropertyOp getter /* = JS_PropertyStub */,
                         JSStrictPropertyOp setter /* = JS_StrictPropertyStub */,
                         unsigned attrs /* = JSPROP_ENUMERATE */)
 {
-    return defineGeneric(cx, SPECIALID_TO_JSID(sid), value, getter, setter, attrs);
+    return defineGeneric(cx, js::RootedVarId(cx, SPECIALID_TO_JSID(sid)), value, getter, setter, attrs);
 }
 
 inline JSBool
 JSObject::lookupElement(JSContext *cx, uint32_t index, JSObject **objp, JSProperty **propp)
 {
+    js::RootedVarObject self(cx, this);
+
     js::LookupElementOp op = getOps()->lookupElement;
-    return (op ? op : js_LookupElement)(cx, this, index, objp, propp);
+    return (op ? op : js::baseops::LookupElement)(cx, self, index, objp, propp);
 }
 
 inline JSBool
 JSObject::lookupSpecial(JSContext *cx, js::SpecialId sid, JSObject **objp, JSProperty **propp)
 {
-    return lookupGeneric(cx, SPECIALID_TO_JSID(sid), objp, propp);
+    return lookupGeneric(cx, js::RootedVarId(cx, SPECIALID_TO_JSID(sid)), objp, propp);
 }
 
 inline JSBool
-JSObject::getElement(JSContext *cx, JSObject *receiver_, uint32_t index, js::Value *vp)
+JSObject::getElement(JSContext *cx, js::HandleObject receiver, uint32_t index, js::Value *vp)
 {
+    js::RootedVarObject self(cx, this);
+
     js::ElementIdOp op = getOps()->getElement;
     if (op)
-        return op(cx, this, receiver_, index, vp);
+        return op(cx, self, receiver, index, vp);
 
-    js::RootedVarObject self(cx, this);
-    js::RootedVarObject receiver(cx, receiver_);
-
-    jsid id;
-    if (!js::IndexToId(cx, index, &id))
+    js::RootedVarId id(cx);
+    if (!js::IndexToId(cx, index, id.address()))
         return false;
     return self->getGeneric(cx, receiver, id, vp);
 }
 
 inline JSBool
 JSObject::getElement(JSContext *cx, uint32_t index, js::Value *vp)
 {
-    return getElement(cx, this, index, vp);
+    return getElement(cx, js::RootedVarObject(cx, this), index, vp);
 }
 
 inline JSBool
-JSObject::getElementIfPresent(JSContext *cx, JSObject *receiver_, uint32_t index, js::Value *vp,
+JSObject::getElementIfPresent(JSContext *cx, js::HandleObject receiver, uint32_t index, js::Value *vp,
                               bool *present)
 {
-    js::RootedVarObject self(cx, this), receiver(cx, receiver_);
+    js::RootedVarObject self(cx, this);
 
     js::ElementIfPresentOp op = getOps()->getElementIfPresent;
     if (op)
-        return op(cx, this, receiver, index, vp, present);
+        return op(cx, self, receiver, index, vp, present);
 
     /*
      * For now, do the index-to-id conversion just once, then use
      * lookupGeneric/getGeneric.  Once lookupElement and getElement stop both
      * doing index-to-id conversions, we can use those here.
      */
-    jsid id;
-    if (!js::IndexToId(cx, index, &id))
+    js::RootedVarId id(cx);
+    if (!js::IndexToId(cx, index, id.address()))
         return false;
 
     JSObject *obj2;
     JSProperty *prop;
     if (!self->lookupGeneric(cx, id, &obj2, &prop))
         return false;
 
     if (!prop) {
@@ -1159,47 +1171,47 @@ JSObject::getElementIfPresent(JSContext 
         return true;
     }
 
     *present = true;
     return self->getGeneric(cx, receiver, id, vp);
 }
 
 inline JSBool
-JSObject::getSpecial(JSContext *cx, JSObject *receiver, js::SpecialId sid, js::Value *vp)
+JSObject::getSpecial(JSContext *cx, js::HandleObject receiver, js::SpecialId sid, js::Value *vp)
 {
-    return getGeneric(cx, receiver, SPECIALID_TO_JSID(sid), vp);
+    return getGeneric(cx, receiver, js::RootedVarId(cx, SPECIALID_TO_JSID(sid)), vp);
 }
 
 inline JSBool
-JSObject::getGenericAttributes(JSContext *cx, jsid id, unsigned *attrsp)
+JSObject::getGenericAttributes(JSContext *cx, js::HandleId id, unsigned *attrsp)
 {
     js::GenericAttributesOp op = getOps()->getGenericAttributes;
-    return (op ? op : js_GetAttributes)(cx, this, id, attrsp);
+    return (op ? op : js::baseops::GetAttributes)(cx, js::RootedVarObject(cx, this), id, attrsp);
 }
 
 inline JSBool
 JSObject::getPropertyAttributes(JSContext *cx, js::PropertyName *name, unsigned *attrsp)
 {
-    return getGenericAttributes(cx, js::NameToId(name), attrsp);
+    return getGenericAttributes(cx, js::RootedVarId(cx, js::NameToId(name)), attrsp);
 }
 
 inline JSBool
 JSObject::getElementAttributes(JSContext *cx, uint32_t index, unsigned *attrsp)
 {
-    jsid id;
-    if (!js::IndexToId(cx, index, &id))
+    js::RootedVarId id(cx);
+    if (!js::IndexToId(cx, index, id.address()))
         return false;
     return getGenericAttributes(cx, id, attrsp);
 }
 
 inline JSBool
 JSObject::getSpecialAttributes(JSContext *cx, js::SpecialId sid, unsigned *attrsp)
 {
-    return getGenericAttributes(cx, SPECIALID_TO_JSID(sid), attrsp);
+    return getGenericAttributes(cx, js::RootedVarId(cx, SPECIALID_TO_JSID(sid)), attrsp);
 }
 
 inline bool
 JSObject::isProxy() const
 {
     return js::IsProxy(this);
 }
 
@@ -1227,28 +1239,30 @@ JSObject::global() const
 static inline bool
 js_IsCallable(const js::Value &v)
 {
     return v.isObject() && v.toObject().isCallable();
 }
 
 namespace js {
 
-inline void
-OBJ_TO_INNER_OBJECT(JSContext *cx, JSObject *&obj)
+inline JSObject *
+GetInnerObject(JSContext *cx, HandleObject obj)
 {
     if (JSObjectOp op = obj->getClass()->ext.innerObject)
-        obj = op(cx, obj);
+        return op(cx, obj);
+    return obj;
 }
 
-inline void
-OBJ_TO_OUTER_OBJECT(JSContext *cx, JSObject *&obj)
+inline JSObject *
+GetOuterObject(JSContext *cx, HandleObject obj)
 {
     if (JSObjectOp op = obj->getClass()->ext.outerObject)
-        obj = op(cx, obj);
+        return op(cx, obj);
+    return obj;
 }
 
 #if JS_HAS_XML_SUPPORT
 /*
  * Methods to test whether an object or a value is of type "xml" (per typeof).
  */
 
 #define VALUE_IS_XML(v)     ((v).isObject() && (v).toObject().isXML())
--- a/js/src/json.cpp
+++ b/js/src/json.cpp
@@ -308,18 +308,18 @@ template<typename KeyType>
 static bool
 PreprocessValue(JSContext *cx, JSObject *holder, KeyType key, Value *vp, StringifyContext *scx)
 {
     JSString *keyStr = NULL;
 
     /* Step 2. */
     if (vp->isObject()) {
         Value toJSON;
-        jsid id = NameToId(cx->runtime->atomState.toJSONAtom);
-        if (!js_GetMethod(cx, RootedVarObject(cx, &vp->toObject()), id, 0, &toJSON))
+        RootedVarId id(cx, NameToId(cx->runtime->atomState.toJSONAtom));
+        if (!GetMethod(cx, RootedVarObject(cx, &vp->toObject()), id, 0, &toJSON))
             return false;
 
         if (js_IsCallable(toJSON)) {
             keyStr = KeyStringifier<KeyType>::toString(cx, key);
             if (!keyStr)
                 return false;
 
             InvokeArgsGuard args;
@@ -430,29 +430,30 @@ JO(JSContext *cx, HandleObject obj, Stri
         props = ids.addr();
     }
 
     /* My kingdom for not-quite-initialized-from-the-start references. */
     const AutoIdVector &propertyList = *props;
 
     /* Steps 8-10, 13. */
     bool wroteMember = false;
+    RootedVarId id(cx);
     for (size_t i = 0, len = propertyList.length(); i < len; i++) {
         /*
          * Steps 8a-8b.  Note that the call to Str is broken up into 1) getting
          * the property; 2) processing for toJSON, calling the replacer, and
          * handling boxed Number/String/Boolean objects; 3) filtering out
          * values which process to |undefined|, and 4) stringifying all values
          * which pass the filter.
          */
-        const jsid &id = propertyList[i];
+        id = propertyList[i];
         Value outputValue;
         if (!obj->getGeneric(cx, id, &outputValue))
             return false;
-        if (!PreprocessValue(cx, obj, id, &outputValue, scx))
+        if (!PreprocessValue(cx, obj, id.reference(), &outputValue, scx))
             return false;
         if (IsFilteredValue(outputValue))
             continue;
 
         /* Output a comma unless this is the first member to write. */
         if (wroteMember && !scx->sb.append(','))
             return false;
         wroteMember = true;
@@ -748,39 +749,39 @@ js_Stringify(JSContext *cx, Value *vp, J
     }
 
     /* Step 9. */
     RootedVarObject wrapper(cx, NewBuiltinClassInstance(cx, &ObjectClass));
     if (!wrapper)
         return false;
 
     /* Step 10. */
-    jsid emptyId = NameToId(cx->runtime->atomState.emptyAtom);
+    RootedVarId emptyId(cx, NameToId(cx->runtime->atomState.emptyAtom));
     if (!DefineNativeProperty(cx, wrapper, emptyId, *vp, JS_PropertyStub, JS_StrictPropertyStub,
                               JSPROP_ENUMERATE, 0, 0))
     {
         return false;
     }
 
     /* Step 11. */
     StringifyContext scx(cx, sb, gap, replacer, propertyList);
     if (!scx.init())
         return false;
 
-    if (!PreprocessValue(cx, wrapper, emptyId, vp, &scx))
+    if (!PreprocessValue(cx, wrapper, emptyId.reference(), vp, &scx))
         return false;
     if (IsFilteredValue(*vp))
         return true;
 
     return Str(cx, *vp, &scx);
 }
 
 /* ES5 15.12.2 Walk. */
 static bool
-Walk(JSContext *cx, JSObject *holder, jsid name, const Value &reviver, Value *vp)
+Walk(JSContext *cx, HandleObject holder, HandleId name, const Value &reviver, Value *vp)
 {
     JS_CHECK_RECURSION(cx, return false);
 
     /* Step 1. */
     Value val;
     if (!holder->getGeneric(cx, name, &val))
         return false;
 
@@ -790,19 +791,19 @@ Walk(JSContext *cx, JSObject *holder, js
 
         /* 'val' must have been produced by the JSON parser, so not a proxy. */
         JS_ASSERT(!obj->isProxy());
         if (obj->isArray()) {
             /* Step 2a(ii). */
             uint32_t length = obj->getArrayLength();
 
             /* Step 2a(i), 2a(iii-iv). */
+            RootedVarId id(cx);
             for (uint32_t i = 0; i < length; i++) {
-                jsid id;
-                if (!IndexToId(cx, i, &id))
+                if (!IndexToId(cx, i, id.address()))
                     return false;
 
                 /* Step 2a(iii)(1). */
                 Value newElement;
                 if (!Walk(cx, obj, id, reviver, &newElement))
                     return false;
 
                 /*
@@ -827,20 +828,21 @@ Walk(JSContext *cx, JSObject *holder, js
             }
         } else {
             /* Step 2b(i). */
             AutoIdVector keys(cx);
             if (!GetPropertyNames(cx, obj, JSITER_OWNONLY, &keys))
                 return false;
 
             /* Step 2b(ii). */
+            RootedVarId id(cx);
             for (size_t i = 0, len = keys.length(); i < len; i++) {
                 /* Step 2b(ii)(1). */
                 Value newElement;
-                jsid id = keys[i];
+                id = keys[i];
                 if (!Walk(cx, obj, id, reviver, &newElement))
                     return false;
 
                 if (newElement.isUndefined()) {
                     /* Step 2b(ii)(2). */
                     if (!obj->deleteByValue(cx, IdToValue(id), &newElement, false))
                         return false;
                 } else {
@@ -874,25 +876,24 @@ Walk(JSContext *cx, JSObject *holder, js
         return false;
     *vp = args.rval();
     return true;
 }
 
 static bool
 Revive(JSContext *cx, const Value &reviver, Value *vp)
 {
-
-    JSObject *obj = NewBuiltinClassInstance(cx, &ObjectClass);
+    RootedVarObject obj(cx, NewBuiltinClassInstance(cx, &ObjectClass));
     if (!obj)
         return false;
 
     if (!obj->defineProperty(cx, cx->runtime->atomState.emptyAtom, *vp))
         return false;
 
-    return Walk(cx, obj, NameToId(cx->runtime->atomState.emptyAtom), reviver, vp);
+    return Walk(cx, obj, RootedVarId(cx, NameToId(cx->runtime->atomState.emptyAtom)), reviver, vp);
 }
 
 namespace js {
 
 JSBool
 ParseJSONWithReviver(JSContext *cx, const jschar *chars, size_t length, const Value &reviver,
                      Value *vp, DecodingMode decodingMode /* = STRICT */)
 {
--- a/js/src/jsonparser.cpp
+++ b/js/src/jsonparser.cpp
@@ -529,17 +529,17 @@ JSONParser::parse(Value *vp)
     *vp = UndefinedValue();
 
     Token token;
     ParserState state = JSONValue;
     while (true) {
         switch (state) {
           case FinishObjectMember: {
             Value v = valueStack.popCopy();
-            jsid propid = AtomToId(&valueStack.popCopy().toString()->asAtom());
+            RootedVarId propid(cx, AtomToId(&valueStack.popCopy().toString()->asAtom()));
             RootedVarObject obj(cx, &valueStack.back().toObject());
             if (!DefineNativeProperty(cx, obj, propid, v,
                                       JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE,
                                       0, 0))
             {
                 return false;
             }
             token = advanceAfterProperty();
@@ -577,17 +577,17 @@ JSONParser::parse(Value *vp)
             if (token == OOM)
                 return false;
             if (token != Error)
                 error("property names must be double-quoted strings");
             return errorReturn();
 
           case FinishArrayElement: {
             Value v = valueStack.popCopy();
-            if (!js_NewbornArrayPush(cx, &valueStack.back().toObject(), v))
+            if (!js_NewbornArrayPush(cx, RootedVarObject(cx, &valueStack.back().toObject()), v))
                 return false;
             token = advanceAfterArrayElement();
             if (token == Comma) {
                 if (!stateStack.append(FinishArrayElement))
                     return false;
                 goto JSONValue;
             }
             if (token == ArrayClose)
--- a/js/src/jsopcode.tbl
+++ b/js/src/jsopcode.tbl
@@ -167,17 +167,17 @@ OPDEF(JSOP_DECPROP,   45, "decprop",    
 OPDEF(JSOP_DECELEM,   46, "decelem",    NULL,         2,  2,  1, 15,  JOF_BYTE |JOF_ELEM|JOF_DEC|JOF_TMPSLOT2|JOF_DECOMPOSE)
 OPDEF(JSOP_NAMEINC,   47, "nameinc",    NULL,         6,  0,  1, 15,  JOF_ATOM|JOF_NAME|JOF_INC|JOF_POST|JOF_TMPSLOT3|JOF_DECOMPOSE)
 OPDEF(JSOP_PROPINC,   48, "propinc",    NULL,         6,  1,  1, 15,  JOF_ATOM|JOF_PROP|JOF_INC|JOF_POST|JOF_TMPSLOT3|JOF_DECOMPOSE)
 OPDEF(JSOP_ELEMINC,   49, "eleminc",    NULL,         2,  2,  1, 15,  JOF_BYTE |JOF_ELEM|JOF_INC|JOF_POST|JOF_TMPSLOT2|JOF_DECOMPOSE)
 OPDEF(JSOP_NAMEDEC,   50, "namedec",    NULL,         6,  0,  1, 15,  JOF_ATOM|JOF_NAME|JOF_DEC|JOF_POST|JOF_TMPSLOT3|JOF_DECOMPOSE)
 OPDEF(JSOP_PROPDEC,   51, "propdec",    NULL,         6,  1,  1, 15,  JOF_ATOM|JOF_PROP|JOF_DEC|JOF_POST|JOF_TMPSLOT3|JOF_DECOMPOSE)
 OPDEF(JSOP_ELEMDEC,   52, "elemdec",    NULL,         2,  2,  1, 15,  JOF_BYTE |JOF_ELEM|JOF_DEC|JOF_POST|JOF_TMPSLOT2|JOF_DECOMPOSE)
 
-OPDEF(JSOP_GETPROP,   53, "getprop",    NULL,         5,  1,  1, 18,  JOF_ATOM|JOF_PROP|JOF_TYPESET)
+OPDEF(JSOP_GETPROP,   53, "getprop",    NULL,         5,  1,  1, 18,  JOF_ATOM|JOF_PROP|JOF_TYPESET|JOF_TMPSLOT3)
 OPDEF(JSOP_SETPROP,   54, "setprop",    NULL,         5,  2,  1,  3,  JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING)
 OPDEF(JSOP_GETELEM,   55, "getelem",    NULL,         1,  2,  1, 18,  JOF_BYTE |JOF_ELEM|JOF_TYPESET|JOF_LEFTASSOC)
 OPDEF(JSOP_SETELEM,   56, "setelem",    NULL,         1,  3,  1,  3,  JOF_BYTE |JOF_ELEM|JOF_SET|JOF_DETECTING)
 OPDEF(JSOP_CALLNAME,  57, "callname",   NULL,         5,  0,  1, 19,  JOF_ATOM|JOF_NAME|JOF_TYPESET)
 OPDEF(JSOP_CALL,      58, "call",       NULL,         3, -1,  1, 18,  JOF_UINT16|JOF_INVOKE|JOF_TYPESET)
 OPDEF(JSOP_NAME,      59, "name",       NULL,         5,  0,  1, 19,  JOF_ATOM|JOF_NAME|JOF_TYPESET)
 OPDEF(JSOP_DOUBLE,    60, "double",     NULL,         5,  0,  1, 16,  JOF_DOUBLE)
 OPDEF(JSOP_STRING,    61, "string",     NULL,         5,  0,  1, 19,  JOF_ATOM)
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -123,18 +123,21 @@ BaseProxyHandler::hasOwn(JSContext *cx, 
     AutoPropertyDescriptorRooter desc(cx);
     if (!getOwnPropertyDescriptor(cx, proxy, id, false, &desc))
         return false;
     *bp = !!desc.obj;
     return true;
 }
 
 bool
-BaseProxyHandler::get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, Value *vp)
+BaseProxyHandler::get(JSContext *cx, JSObject *proxy, JSObject *receiver_, jsid id_, Value *vp)
 {
+    RootedVarObject receiver(cx, receiver_);
+    RootedVarId id(cx, id_);
+
     JS_ASSERT(OperationInProgress(cx, proxy));
     AutoPropertyDescriptorRooter desc(cx);
     if (!getPropertyDescriptor(cx, proxy, id, false, &desc))
         return false;
     if (!desc.obj) {
         vp->setUndefined();
         return true;
     }
@@ -171,19 +174,22 @@ BaseProxyHandler::getElementIfPresent(JS
         Debug_SetValueRangeToCrashOnTouch(vp, 1);
         return true;
     }
 
     return get(cx, proxy, receiver, id, vp);
 }
 
 bool
-BaseProxyHandler::set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, bool strict,
-                  Value *vp)
+BaseProxyHandler::set(JSContext *cx, JSObject *proxy, JSObject *receiver_, jsid id_, bool strict,
+                      Value *vp)
 {
+    RootedVarObject receiver(cx, receiver_);
+    RootedVarId id(cx, id_);
+
     JS_ASSERT(OperationInProgress(cx, proxy));
     AutoPropertyDescriptorRooter desc(cx);
     if (!getOwnPropertyDescriptor(cx, proxy, id, true, &desc))
         return false;
     /* The control-flow here differs from ::get() because of the fall-through case below. */
     if (desc.obj) {
         // Check for read-only properties.
         if (desc.attrs & JSPROP_READONLY)
@@ -566,17 +572,17 @@ IndirectProxyHandler::trace(JSTracer *tr
     MarkSlot(trc, &proxy->getReservedSlotRef(JSSLOT_PROXY_PRIVATE), "targetObject");
 }
 
 static bool
 GetTrap(JSContext *cx, JSObject *handler, PropertyName *name, Value *fvalp)
 {
     JS_CHECK_RECURSION(cx, return false);
 
-    return handler->getGeneric(cx, NameToId(name), fvalp);
+    return handler->getGeneric(cx, RootedVarId(cx, NameToId(name)), fvalp);
 }
 
 static bool
 GetFundamentalTrap(JSContext *cx, JSObject *handler, PropertyName *name, Value *fvalp)
 {
     if (!GetTrap(cx, handler, name, fvalp))
         return false;
 
@@ -1171,273 +1177,255 @@ bool
 Proxy::iteratorNext(JSContext *cx, JSObject *proxy, Value *vp)
 {
     JS_CHECK_RECURSION(cx, return NULL);
     AutoPendingProxyOperation pending(cx, proxy);
     return GetProxyHandler(proxy)->iteratorNext(cx, proxy, vp);
 }
 
 static JSObject *
-proxy_innerObject(JSContext *cx, JSObject *obj)
+proxy_innerObject(JSContext *cx, HandleObject obj)
 {
     return GetProxyPrivate(obj).toObjectOrNull();
 }
 
 static JSBool
-proxy_LookupGeneric(JSContext *cx, JSObject *obj_, jsid id, JSObject **objp,
+proxy_LookupGeneric(JSContext *cx, HandleObject obj, HandleId id, JSObject **objp,
                     JSProperty **propp)
 {
-    RootedVarObject obj(cx, obj_);
-
     bool found;
     if (!Proxy::has(cx, obj, id, &found))
         return false;
 
     if (found) {
         *propp = (JSProperty *)0x1;
         *objp = obj;
     } else {
         *objp = NULL;
         *propp = NULL;
     }
     return true;
 }
 
 static JSBool
-proxy_LookupProperty(JSContext *cx, JSObject *obj, PropertyName *name, JSObject **objp,
+proxy_LookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, JSObject **objp,
                      JSProperty **propp)
 {
-    return proxy_LookupGeneric(cx, obj, NameToId(name), objp, propp);
+    return proxy_LookupGeneric(cx, obj, RootedVarId(cx, NameToId(name)), objp, propp);
 }
 
 static JSBool
-proxy_LookupElement(JSContext *cx, JSObject *obj_, uint32_t index, JSObject **objp,
+proxy_LookupElement(JSContext *cx, HandleObject obj, uint32_t index, JSObject **objp,
                     JSProperty **propp)
 {
-    RootedVarObject obj(cx, obj_);
-
-    jsid id;
-    if (!IndexToId(cx, index, &id))
+    RootedVarId id(cx);
+    if (!IndexToId(cx, index, id.address()))
         return false;
     return proxy_LookupGeneric(cx, obj, id, objp, propp);
 }
 
 static JSBool
-proxy_LookupSpecial(JSContext *cx, JSObject *obj, SpecialId sid, JSObject **objp, JSProperty **propp)
+proxy_LookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, JSObject **objp, JSProperty **propp)
 {
-    return proxy_LookupGeneric(cx, obj, SPECIALID_TO_JSID(sid), objp, propp);
+    return proxy_LookupGeneric(cx, obj, RootedVarId(cx, SPECIALID_TO_JSID(sid)), objp, propp);
 }
 
 static JSBool
-proxy_DefineGeneric(JSContext *cx, JSObject *obj, jsid id, const Value *value,
+proxy_DefineGeneric(JSContext *cx, HandleObject obj, HandleId id, const Value *value,
                     PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
 {
     AutoPropertyDescriptorRooter desc(cx);
     desc.obj = obj;
     desc.value = *value;
     desc.attrs = (attrs & (~JSPROP_SHORTID));
     desc.getter = getter;
     desc.setter = setter;
     desc.shortid = 0;
     return Proxy::defineProperty(cx, obj, id, &desc);
 }
 
 static JSBool
-proxy_DefineProperty(JSContext *cx, JSObject *obj, PropertyName *name, const Value *value,
+proxy_DefineProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, const Value *value,
                      PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
 {
-    return proxy_DefineGeneric(cx, obj, NameToId(name), value, getter, setter, attrs);
+    return proxy_DefineGeneric(cx, obj, RootedVarId(cx, NameToId(name)), value, getter, setter, attrs);
 }
 
 static JSBool
-proxy_DefineElement(JSContext *cx, JSObject *obj_, uint32_t index, const Value *value,
+proxy_DefineElement(JSContext *cx, HandleObject obj, uint32_t index, const Value *value,
                     PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
 {
-    RootedVarObject obj(cx, obj_);
-
-    jsid id;
-    if (!IndexToId(cx, index, &id))
+    RootedVarId id(cx);
+    if (!IndexToId(cx, index, id.address()))
         return false;
     return proxy_DefineGeneric(cx, obj, id, value, getter, setter, attrs);
 }
 
 static JSBool
-proxy_DefineSpecial(JSContext *cx, JSObject *obj, SpecialId sid, const Value *value,
+proxy_DefineSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, const Value *value,
                     PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
 {
-    return proxy_DefineGeneric(cx, obj, SPECIALID_TO_JSID(sid), value, getter, setter, attrs);
+    return proxy_DefineGeneric(cx, obj, RootedVarId(cx, SPECIALID_TO_JSID(sid)),
+                               value, getter, setter, attrs);
 }
 
 static JSBool
-proxy_GetGeneric(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp)
+proxy_GetGeneric(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id, Value *vp)
 {
     return Proxy::get(cx, obj, receiver, id, vp);
 }
 
 static JSBool
-proxy_GetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, PropertyName *name, Value *vp)
+proxy_GetProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandlePropertyName name, Value *vp)
 {
-    return proxy_GetGeneric(cx, obj, receiver, NameToId(name), vp);
+    return proxy_GetGeneric(cx, obj, receiver, RootedVarId(cx, NameToId(name)), vp);
 }
 
 static JSBool
-proxy_GetElement(JSContext *cx, JSObject *obj_, JSObject *receiver_, uint32_t index, Value *vp)
+proxy_GetElement(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index, Value *vp)
 {
-    RootedVarObject obj(cx, obj_);
-    RootedVarObject receiver(cx, receiver_);
-
-    jsid id;
-    if (!IndexToId(cx, index, &id))
+    RootedVarId id(cx);
+    if (!IndexToId(cx, index, id.address()))
         return false;
     return proxy_GetGeneric(cx, obj, receiver, id, vp);
 }
 
 static JSBool
-proxy_GetElementIfPresent(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t index,
+proxy_GetElementIfPresent(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index,
                           Value *vp, bool *present)
 {
     return Proxy::getElementIfPresent(cx, obj, receiver, index, vp, present);
 }
 
 static JSBool
-proxy_GetSpecial(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid, Value *vp)
+proxy_GetSpecial(JSContext *cx, HandleObject obj, HandleObject receiver, HandleSpecialId sid, Value *vp)
 {
-    return proxy_GetGeneric(cx, obj, receiver, SPECIALID_TO_JSID(sid), vp);
+    return proxy_GetGeneric(cx, obj, receiver, RootedVarId(cx, SPECIALID_TO_JSID(sid)), vp);
 }
 
 static JSBool
-proxy_SetGeneric(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
+proxy_SetGeneric(JSContext *cx, HandleObject obj, HandleId id, Value *vp, JSBool strict)
 {
     return Proxy::set(cx, obj, obj, id, strict, vp);
 }
 
 static JSBool
-proxy_SetProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict)
+proxy_SetProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, Value *vp, JSBool strict)
 {
-    return proxy_SetGeneric(cx, obj, NameToId(name), vp, strict);
+    return proxy_SetGeneric(cx, obj, RootedVarId(cx, NameToId(name)), vp, strict);
 }
 
 static JSBool
-proxy_SetElement(JSContext *cx, JSObject *obj_, uint32_t index, Value *vp, JSBool strict)
+proxy_SetElement(JSContext *cx, HandleObject obj, uint32_t index, Value *vp, JSBool strict)
 {
-    RootedVarObject obj(cx, obj_);
-
-    jsid id;
-    if (!IndexToId(cx, index, &id))
+    RootedVarId id(cx);
+    if (!IndexToId(cx, index, id.address()))
         return false;
     return proxy_SetGeneric(cx, obj, id, vp, strict);
 }
 
 static JSBool
-proxy_SetSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict)
+proxy_SetSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, Value *vp, JSBool strict)
 {
-    return proxy_SetGeneric(cx, obj, SPECIALID_TO_JSID(sid), vp, strict);
+    return proxy_SetGeneric(cx, obj, RootedVarId(cx, SPECIALID_TO_JSID(sid)), vp, strict);
 }
 
 static JSBool
-proxy_GetGenericAttributes(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp)
+proxy_GetGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp)
 {
     AutoPropertyDescriptorRooter desc(cx);
     if (!Proxy::getOwnPropertyDescriptor(cx, obj, id, false, &desc))
         return false;
     *attrsp = desc.attrs;
     return true;
 }
 
 static JSBool
-proxy_GetPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, unsigned *attrsp)
+proxy_GetPropertyAttributes(JSContext *cx, HandleObject obj, HandlePropertyName name, unsigned *attrsp)
 {
-    return proxy_GetGenericAttributes(cx, obj, NameToId(name), attrsp);
+    return proxy_GetGenericAttributes(cx, obj, RootedVarId(cx, NameToId(name)), attrsp);
 }
 
 static JSBool
-proxy_GetElementAttributes(JSContext *cx, JSObject *obj_, uint32_t index, unsigned *attrsp)
+proxy_GetElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp)
 {
-    RootedVarObject obj(cx, obj_);
-
-    jsid id;
-    if (!IndexToId(cx, index, &id))
+    RootedVarId id(cx);
+    if (!IndexToId(cx, index, id.address()))
         return false;
     return proxy_GetGenericAttributes(cx, obj, id, attrsp);
 }
 
 static JSBool
-proxy_GetSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, unsigned *attrsp)
+proxy_GetSpecialAttributes(JSContext *cx, HandleObject obj, HandleSpecialId sid, unsigned *attrsp)
 {
-    return proxy_GetGenericAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp);
+    return proxy_GetGenericAttributes(cx, obj, RootedVarId(cx, SPECIALID_TO_JSID(sid)), attrsp);
 }
 
 static JSBool
-proxy_SetGenericAttributes(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp)
+proxy_SetGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp)
 {
     /* Lookup the current property descriptor so we have setter/getter/value. */
     AutoPropertyDescriptorRooter desc(cx);
     if (!Proxy::getOwnPropertyDescriptor(cx, obj, id, true, &desc))
         return false;
     desc.attrs = (*attrsp & (~JSPROP_SHORTID));
     return Proxy::defineProperty(cx, obj, id, &desc);
 }
 
 static JSBool
-proxy_SetPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, unsigned *attrsp)
+proxy_SetPropertyAttributes(JSContext *cx, HandleObject obj, HandlePropertyName name, unsigned *attrsp)
 {
-    return proxy_SetGenericAttributes(cx, obj, NameToId(name), attrsp);
+    return proxy_SetGenericAttributes(cx, obj, RootedVarId(cx, NameToId(name)), attrsp);
 }
 
 static JSBool
-proxy_SetElementAttributes(JSContext *cx, JSObject *obj_, uint32_t index, unsigned *attrsp)
+proxy_SetElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp)
 {
-    RootedVarObject obj(cx, obj_);
-
-    jsid id;
-    if (!IndexToId(cx, index, &id))
+    RootedVarId id(cx);
+    if (!IndexToId(cx, index, id.address()))
         return false;
     return proxy_SetGenericAttributes(cx, obj, id, attrsp);
 }
 
 static JSBool
-proxy_SetSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, unsigned *attrsp)
+proxy_SetSpecialAttributes(JSContext *cx, HandleObject obj, HandleSpecialId sid, unsigned *attrsp)
 {
-    return proxy_SetGenericAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp);
+    return proxy_SetGenericAttributes(cx, obj, RootedVarId(cx, SPECIALID_TO_JSID(sid)), attrsp);
 }
 
 static JSBool
-proxy_DeleteGeneric(JSContext *cx, JSObject *obj_, jsid id, Value *rval, JSBool strict)
+proxy_DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, Value *rval, JSBool strict)
 {
-    RootedVarObject obj(cx, obj_);
-
     // TODO: throwing away strict
     bool deleted;
     if (!Proxy::delete_(cx, obj, id, &deleted) || !js_SuppressDeletedProperty(cx, obj, id))
         return false;
     rval->setBoolean(deleted);
     return true;
 }
 
 static JSBool
-proxy_DeleteProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *rval, JSBool strict)
+proxy_DeleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, Value *rval, JSBool strict)
 {
-    return proxy_DeleteGeneric(cx, obj, NameToId(name), rval, strict);
+    return proxy_DeleteGeneric(cx, obj, RootedVarId(cx, NameToId(name)), rval, strict);
 }
 
 static JSBool
-proxy_DeleteElement(JSContext *cx, JSObject *obj_, uint32_t index, Value *rval, JSBool strict)
+proxy_DeleteElement(JSContext *cx, HandleObject obj, uint32_t index, Value *rval, JSBool strict)
 {
-    RootedVarObject obj(cx, obj_);
-
-    jsid id;
-    if (!IndexToId(cx, index, &id))
+    RootedVarId id(cx);
+    if (!IndexToId(cx, index, id.address()))
         return false;
     return proxy_DeleteGeneric(cx, obj, id, rval, strict);
 }
 
 static JSBool
-proxy_DeleteSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *rval, JSBool strict)
+proxy_DeleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, Value *rval, JSBool strict)
 {
-    return proxy_DeleteGeneric(cx, obj, SPECIALID_TO_JSID(sid), rval, strict);
+    return proxy_DeleteGeneric(cx, obj, RootedVarId(cx, SPECIALID_TO_JSID(sid)), rval, strict);
 }
 
 static void
 proxy_TraceObject(JSTracer *trc, JSObject *obj)
 {
     // NB: If you add new slots here, make sure to change
     // js::NukeChromeCrossCompartmentWrappers to cope.
     GetProxyHandler(obj)->trace(trc, obj);
@@ -1452,43 +1440,43 @@ proxy_TraceFunction(JSTracer *trc, JSObj
     // NB: If you add new slots here, make sure to change
     // js::NukeChromeCrossCompartmentWrappers to cope.
     MarkCrossCompartmentSlot(trc, &GetCall(obj), "call");
     MarkCrossCompartmentSlot(trc, &GetFunctionProxyConstruct(obj), "construct");
     proxy_TraceObject(trc, obj);
 }
 
 static JSBool
-proxy_Convert(JSContext *cx, JSObject *proxy, JSType hint, Value *vp)
+proxy_Convert(JSContext *cx, HandleObject proxy, JSType hint, Value *vp)
 {
     JS_ASSERT(proxy->isProxy());
     return Proxy::defaultValue(cx, proxy, hint, vp);
 }
 
 static void
 proxy_Finalize(FreeOp *fop, JSObject *obj)
 {
     JS_ASSERT(obj->isProxy());
     if (!obj->getSlot(JSSLOT_PROXY_HANDLER).isUndefined())
         GetProxyHandler(obj)->finalize(fop, obj);
 }
 
 static JSBool
-proxy_HasInstance(JSContext *cx, JSObject *proxy, const Value *v, JSBool *bp)
+proxy_HasInstance(JSContext *cx, HandleObject proxy, const Value *v, JSBool *bp)
 {
     AutoPendingProxyOperation pending(cx, proxy);
     bool b;
     if (!Proxy::hasInstance(cx, proxy, v, &b))
         return false;
     *bp = !!b;
     return true;
 }
 
 static JSType
-proxy_TypeOf(JSContext *cx, JSObject *proxy)
+proxy_TypeOf(JSContext *cx, HandleObject proxy)
 {
     JS_ASSERT(proxy->isProxy());
     return Proxy::typeOf(cx, proxy);
 }
 
 JS_FRIEND_DATA(Class) js::ObjectProxyClass = {
     "Proxy",
     Class::NON_NATIVE | JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_HAS_RESERVED_SLOTS(4),
--- a/js/src/jsprvtd.h
+++ b/js/src/jsprvtd.h
@@ -404,50 +404,32 @@ typedef struct JSDebugHooks {
     void                *throwHookData;
     JSDebugErrorHook    debugErrorHook;
     void                *debugErrorHookData;
 } JSDebugHooks;
 
 /* js::ObjectOps function pointer typedefs. */
 
 /*
- * Look for id in obj and its prototype chain, returning false on error or
- * exception, true on success.  On success, return null in *propp if id was
- * not found.  If id was found, return the first object searching from obj
- * along its prototype chain in which id names a direct property in *objp, and
- * return a non-null, opaque property pointer in *propp.
- *
- * If JSLookupPropOp succeeds and returns with *propp non-null, that pointer
- * may be passed as the prop parameter to a JSAttributesOp, as a short-cut
- * that bypasses id re-lookup.
- */
-typedef JSBool
-(* JSLookupPropOp)(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
-                   JSProperty **propp);
-
-/*
- * Get or set attributes of the property obj[id]. Return false on error or
- * exception, true with current attributes in *attrsp.
- */
-typedef JSBool
-(* JSAttributesOp)(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp);
-
-/*
  * A generic type for functions mapping an object to another object, or null
  * if an error or exception was thrown on cx.
  */
 typedef JSObject *
-(* JSObjectOp)(JSContext *cx, JSObject *obj);
+(* JSObjectOp)(JSContext *cx, JSHandleObject obj);
+
+/* Signature for class initialization ops. */
+typedef JSObject *
+(* JSClassInitializerOp)(JSContext *cx, JSObject *obj);
 
 /*
  * Hook that creates an iterator object for a given object. Returns the
  * iterator object or null if an error or exception was thrown on cx.
  */
 typedef JSObject *
-(* JSIteratorOp)(JSContext *cx, JSObject *obj, JSBool keysonly);
+(* JSIteratorOp)(JSContext *cx, JSHandleObject obj, JSBool keysonly);
 
 /*
  * The following determines whether JS_EncodeCharacters and JS_DecodeBytes
  * treat char[] as utf-8 or simply as bytes that need to be inflated/deflated.
  */
 #ifdef JS_C_STRINGS_ARE_UTF8
 # define js_CStringsAreUTF8 JS_TRUE
 #else
--- a/js/src/jsreflect.cpp
+++ b/js/src/jsreflect.cpp
@@ -202,17 +202,17 @@ class NodeBuilder
         for (unsigned i = 0; i < AST_LIMIT; i++) {
             Value funv;
 
             const char *name = callbackNames[i];
             JSAtom *atom = js_Atomize(cx, name, strlen(name));
             if (!atom)
                 return false;
             RootedVarId id(cx, AtomToId(atom));
-            if (!GetPropertyDefault(cx, userobj, id, NullValue(), &funv))
+            if (!baseops::GetPropertyDefault(cx, userobj, id, NullValue(), &funv))
                 return false;
 
             if (funv.isNullOrUndefined()) {
                 callbacks[i].setNull();
                 continue;
             }
 
             if (!funv.isObject() || !funv.toObject().isFunction()) {
@@ -3131,25 +3131,25 @@ reflect_parse(JSContext *cx, uint32_t ar
         }
 
         RootedVarObject config(cx, &arg.toObject());
 
         Value prop;
 
         /* config.loc */
         RootedVarId locId(cx, NameToId(cx->runtime->atomState.locAtom));
-        if (!GetPropertyDefault(cx, config, locId, BooleanValue(true), &prop))
+        if (!baseops::GetPropertyDefault(cx, config, locId, BooleanValue(true), &prop))
             return JS_FALSE;
 
         loc = js_ValueToBoolean(prop);
 
         if (loc) {
             /* config.source */
             RootedVarId sourceId(cx, NameToId(cx->runtime->atomState.sourceAtom));
-            if (!GetPropertyDefault(cx, config, sourceId, NullValue(), &prop))
+            if (!baseops::GetPropertyDefault(cx, config, sourceId, NullValue(), &prop))
                 return JS_FALSE;
 
             if (!prop.isNullOrUndefined()) {
                 JSString *str = ToString(cx, prop);
                 if (!str)
                     return JS_FALSE;
 
                 size_t length = str->length();
@@ -3160,25 +3160,25 @@ reflect_parse(JSContext *cx, uint32_t ar
                 filename = DeflateString(cx, chars, length);
                 if (!filename)
                     return JS_FALSE;
                 filenamep.reset(filename);
             }
 
             /* config.line */
             RootedVarId lineId(cx, NameToId(cx->runtime->atomState.lineAtom));
-            if (!GetPropertyDefault(cx, config, lineId, Int32Value(1), &prop) ||
+            if (!baseops::GetPropertyDefault(cx, config, lineId, Int32Value(1), &prop) ||
                 !ToUint32(cx, prop, &lineno)) {
                 return JS_FALSE;
             }
         }
 
         /* config.builder */
         RootedVarId builderId(cx, NameToId(cx->runtime->atomState.builderAtom));
-        if (!GetPropertyDefault(cx, config, builderId, NullValue(), &prop))
+        if (!baseops::GetPropertyDefault(cx, config, builderId, NullValue(), &prop))
             return JS_FALSE;
 
         if (!prop.isNullOrUndefined()) {
             if (!prop.isObject()) {
                 js_ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_UNEXPECTED_TYPE,
                                          JSDVG_SEARCH_STACK, prop, NULL, "not an object", NULL);
                 return JS_FALSE;
             }
--- a/js/src/jsscope.h
+++ b/js/src/jsscope.h
@@ -699,18 +699,18 @@ struct Shape : public js::gc::Cell
     void update(js::PropertyOp getter, js::StrictPropertyOp setter, uint8_t attrs);
 
     inline bool matches(const Shape *other) const;
     inline bool matches(const StackShape &other) const;
     inline bool matchesParamsAfterId(BaseShape *base,
                                      uint32_t aslot, unsigned aattrs, unsigned aflags,
                                      int ashortid) const;
 
-    bool get(JSContext* cx, JSObject *receiver, JSObject *obj, JSObject *pobj, js::Value* vp) const;
-    bool set(JSContext* cx, JSObject *obj, bool strict, js::Value* vp) const;
+    bool get(JSContext* cx, HandleObject receiver, JSObject *obj, JSObject *pobj, js::Value* vp) const;
+    bool set(JSContext* cx, HandleObject obj, bool strict, js::Value* vp) const;
 
     BaseShape *base() const { return base_; }
 
     bool hasSlot() const { return (attrs & JSPROP_SHARED) == 0; }
     uint32_t slot() const { JS_ASSERT(hasSlot() && !hasMissingSlot()); return maybeSlot(); }
     uint32_t maybeSlot() const { return slotInfo & SLOT_MASK; }
 
     bool isEmptyShape() const {
--- a/js/src/jsscopeinlines.h
+++ b/js/src/jsscopeinlines.h
@@ -293,61 +293,59 @@ Shape::getUserId(JSContext *cx, jsid *id
         *idp = INT_TO_JSID(id);
     } else {
         *idp = propid();
     }
     return true;
 }
 
 inline bool
-Shape::get(JSContext* cx, JSObject *receiver, JSObject* obj, JSObject *pobj, js::Value* vp) const
+Shape::get(JSContext* cx, HandleObject receiver, JSObject* obj, JSObject *pobj, Value* vp) const
 {
     JS_ASSERT(!hasDefaultGetter());
 
     if (hasGetterValue()) {
-        js::Value fval = getterValue();
-        return js::InvokeGetterOrSetter(cx, receiver, fval, 0, 0, vp);
+        Value fval = getterValue();
+        return InvokeGetterOrSetter(cx, receiver, fval, 0, 0, vp);
     }
 
-    /*
-     * |with (it) color;| ends up here, as do XML filter-expressions.
-     * Avoid exposing the With object to native getters.
-     */
-    if (obj->isWith())
-        obj = &obj->asWith().object();
-
-    jsid id;
-    if (!getUserId(cx, &id))
+    RootedVarId id(cx);
+    if (!getUserId(cx, id.address()))
         return false;
 
-    return js::CallJSPropertyOp(cx, getterOp(), receiver, id, vp);
+    return CallJSPropertyOp(cx, getterOp(), receiver, id, vp);
 }
 
 inline bool
-Shape::set(JSContext* cx, JSObject* obj, bool strict, js::Value* vp) const
+Shape::set(JSContext* cx, HandleObject obj, bool strict, Value* vp) const
 {
     JS_ASSERT_IF(hasDefaultSetter(), hasGetterValue());
 
     if (attrs & JSPROP_SETTER) {
-        js::Value fval = setterValue();
-        return js::InvokeGetterOrSetter(cx, obj, fval, 1, vp, vp);
+        Value fval = setterValue();
+        return InvokeGetterOrSetter(cx, obj, fval, 1, vp, vp);
     }
 
     if (attrs & JSPROP_GETTER)
         return js_ReportGetterOnlyAssignment(cx);
 
-    /* See the comment in js::Shape::get as to why we check for With. */
-    if (obj->isWith())
-        obj = &obj->asWith().object();
-
-    jsid id;
-    if (!getUserId(cx, &id))
+    RootedVarId id(cx);
+    if (!getUserId(cx, id.address()))
         return false;
 
-    return js::CallJSPropertyOpSetter(cx, setterOp(), obj, id, strict, vp);
+    /*
+     * |with (it) color;| ends up here, as do XML filter-expressions.
+     * Avoid exposing the With object to native setters.
+     */
+    if (obj->isWith()) {
+        RootedVarObject nobj(cx, &obj->asWith().object());
+        return CallJSPropertyOpSetter(cx, setterOp(), nobj, id, strict, vp);
+    }
+
+    return CallJSPropertyOpSetter(cx, setterOp(), obj, id, strict, vp);
 }
 
 inline void
 Shape::setParent(js::Shape *p)
 {
     JS_ASSERT_IF(p && !p->hasMissingSlot() && !inDictionary(),
                  p->maybeSlot() <= maybeSlot());
     JS_ASSERT_IF(p && !inDictionary(),
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -387,43 +387,40 @@ static JSFunctionSpec string_functions[]
 };
 
 jschar      js_empty_ucstr[]  = {0};
 JSSubString js_EmptySubString = {0, js_empty_ucstr};
 
 static const unsigned STRING_ELEMENT_ATTRS = JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT;
 
 static JSBool
-str_enumerate(JSContext *cx, JSObject *obj_)
+str_enumerate(JSContext *cx, HandleObject obj)
 {
-    RootedVarObject obj(cx, obj_);
     RootedVarString str(cx, obj->asString().unbox());
     for (size_t i = 0, length = str->length(); i < length; i++) {
         JSString *str1 = js_NewDependentString(cx, str, i, 1);
         if (!str1)
             return false;
         if (!obj->defineElement(cx, i, StringValue(str1),
                                 JS_PropertyStub, JS_StrictPropertyStub,
                                 STRING_ELEMENT_ATTRS)) {
             return false;
         }
     }
 
     return true;
 }
 
 static JSBool
-str_resolve(JSContext *cx, JSObject *obj_, jsid id, unsigned flags,
+str_resolve(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
             JSObject **objp)
 {
     if (!JSID_IS_INT(id))
         return JS_TRUE;
 
-    RootedVarObject obj(cx, obj_);
-
     JSString *str = obj->asString().unbox();
 
     int32_t slot = JSID_TO_INT(id);
     if ((size_t)slot < str->length()) {
         JSString *str1 = cx->runtime->staticStrings.getUnitStringForElement(cx, str, size_t(slot));
         if (!str1)
             return JS_FALSE;
         if (!obj->defineElement(cx, uint32_t(slot), StringValue(str1), NULL, NULL,
@@ -3320,18 +3317,18 @@ js_ValueToSource(JSContext *cx, const Va
 
             return js_NewStringCopyN(cx, js_negzero_ucNstr, 2);
         }
         return ToString(cx, v);
     }
 
     Value rval = NullValue();
     Value fval;
-    jsid id = NameToId(cx->runtime->atomState.toSourceAtom);
-    if (!js_GetMethod(cx, RootedVarObject(cx, &v.toObject()), id, 0, &fval))
+    RootedVarId id(cx, NameToId(cx->runtime->atomState.toSourceAtom));
+    if (!GetMethod(cx, RootedVarObject(cx, &v.toObject()), id, 0, &fval))
         return NULL;
     if (js_IsCallable(fval)) {
         if (!Invoke(cx, v, fval, 0, NULL, &rval))
             return NULL;
     }
 
     return ToString(cx, rval);
 }
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -144,17 +144,17 @@ static ArrayBufferObject *
 getArrayBuffer(JSObject *obj)
 {
     while (obj && !obj->isArrayBuffer())
         obj = obj->getProto();
     return obj ? &obj->asArrayBuffer() : NULL;
 }
 
 JSBool
-ArrayBufferObject::prop_getByteLength(JSContext *cx, JSObject *obj, jsid id, Value *vp)
+ArrayBufferObject::prop_getByteLength(JSContext *cx, HandleObject obj, HandleId id, Value *vp)
 {
     ArrayBufferObject *buffer = getArrayBuffer(obj);
     if (!buffer) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                              JSMSG_INCOMPATIBLE_PROTO, "ArrayBuffer", "byteLength", "object");
         return false;
     }
 
@@ -338,22 +338,19 @@ ArrayBufferObject::obj_trace(JSTracer *t
         MarkObjectUnbarriered(trc, &delegate, "arraybuffer.delegate");
         obj->setPrivateUnbarriered(delegate);
     }
 }
 
 static JSProperty * const PROPERTY_FOUND = reinterpret_cast<JSProperty *>(1);
 
 JSBool
-ArrayBufferObject::obj_lookupGeneric(JSContext *cx, JSObject *obj_, jsid id_,
+ArrayBufferObject::obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id,
                                      JSObject **objp, JSProperty **propp)
 {
-    RootedVarObject obj(cx, obj_);
-    RootedVarId id(cx, id_);
-
     if (JSID_IS_ATOM(id, cx->runtime->atomState.byteLengthAtom)) {
         *propp = PROPERTY_FOUND;
         *objp = getArrayBuffer(obj);
         return true;
     }
 
     RootedVarObject delegate(cx, DelegateObject(cx, obj));
     if (!delegate)
@@ -381,28 +378,26 @@ ArrayBufferObject::obj_lookupGeneric(JSC
         *propp = NULL;
         return true;
     }
 
     return proto->lookupGeneric(cx, id, objp, propp);
 }
 
 JSBool
-ArrayBufferObject::obj_lookupProperty(JSContext *cx, JSObject *obj, PropertyName *name,
+ArrayBufferObject::obj_lookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
                                       JSObject **objp, JSProperty **propp)
 {
-    return obj_lookupGeneric(cx, obj, NameToId(name), objp, propp);
+    return obj_lookupGeneric(cx, obj, RootedVarId(cx, NameToId(name)), objp, propp);
 }
 
 JSBool
-ArrayBufferObject::obj_lookupElement(JSContext *cx, JSObject *obj_, uint32_t index,
+ArrayBufferObject::obj_lookupElement(JSContext *cx, HandleObject obj, uint32_t index,
                                      JSObject **objp, JSProperty **propp)
 {
-    RootedVarObject obj(cx, obj_);
-
     RootedVarObject delegate(cx, DelegateObject(cx, obj));
     if (!delegate)
         return false;
 
     /*
      * If false, there was an error, so propagate it.
      * Otherwise, if propp is non-null, the property
      * was found. Otherwise it was not
@@ -421,150 +416,139 @@ ArrayBufferObject::obj_lookupElement(JSC
         return proto->lookupElement(cx, index, objp, propp);
 
     *objp = NULL;
     *propp = NULL;
     return true;
 }
 
 JSBool
-ArrayBufferObject::obj_lookupSpecial(JSContext *cx, JSObject *obj, SpecialId sid,
+ArrayBufferObject::obj_lookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid,
                                      JSObject **objp, JSProperty **propp)
 {
-    return obj_lookupGeneric(cx, obj, SPECIALID_TO_JSID(sid), objp, propp);
-}
-
-JSBool
-ArrayBufferObject::obj_defineGeneric(JSContext *cx, JSObject *obj_, jsid id_, const Value *v,
-                                     PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
-{
-    if (JSID_IS_ATOM(id_, cx->runtime->atomState.byteLengthAtom))
-        return true;
-
-    RootedVarObject obj(cx, obj_);
-    RootedVarId id(cx, id_);
-    RootGetterSetter gsRoot(cx, attrs, &getter, &setter);
-
-    JSObject *delegate = DelegateObject(cx, obj);
-    if (!delegate)
-        return false;
-    return js_DefineProperty(cx, delegate, id, v, getter, setter, attrs);
-}
-
-JSBool
-ArrayBufferObject::obj_defineProperty(JSContext *cx, JSObject *obj,
-                                      PropertyName *name, const Value *v,
-                                      PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
-{
-    return obj_defineGeneric(cx, obj, NameToId(name), v, getter, setter, attrs);
+    return obj_lookupGeneric(cx, obj, RootedVarId(cx, SPECIALID_TO_JSID(sid)), objp, propp);
 }
 
 JSBool
-ArrayBufferObject::obj_defineElement(JSContext *cx, JSObject *obj_, uint32_t index, const Value *v,
-                                     PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
-{
-    RootedVarObject obj(cx, obj_);
-    RootGetterSetter gsRoot(cx, attrs, &getter, &setter);
-
-    JSObject *delegate = DelegateObject(cx, obj);
-    if (!delegate)
-        return false;
-    return js_DefineElement(cx, delegate, index, v, getter, setter, attrs);
-}
-
-JSBool
-ArrayBufferObject::obj_defineSpecial(JSContext *cx, JSObject *obj, SpecialId sid, const Value *v,
+ArrayBufferObject::obj_defineGeneric(JSContext *cx, HandleObject obj, HandleId id, const Value *v,
                                      PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
 {
-    return obj_defineGeneric(cx, obj, SPECIALID_TO_JSID(sid), v, getter, setter, attrs);
-}
-
-JSBool
-ArrayBufferObject::obj_getGeneric(JSContext *cx, JSObject *obj_, JSObject *receiver_, jsid id_, Value *vp)
-{
-    RootedVarObject obj(cx, obj_), receiver(cx, receiver_);
-    RootedVarId id(cx, id_);
-
-    obj = getArrayBuffer(obj);
-    JS_ASSERT(obj);
-    if (JSID_IS_ATOM(id, cx->runtime->atomState.byteLengthAtom)) {
-        vp->setInt32(obj->asArrayBuffer().byteLength());
+    if (JSID_IS_ATOM(id, cx->runtime->atomState.byteLengthAtom))
         return true;
-    }
+
+    RootGetterSetter gsRoot(cx, attrs, &getter, &setter);
 
     RootedVarObject delegate(cx, DelegateObject(cx, obj));
     if (!delegate)
         return false;
-    return js_GetProperty(cx, delegate, receiver, id, vp);
+    return baseops::DefineProperty(cx, delegate, id, v, getter, setter, attrs);
+}
+
+JSBool
+ArrayBufferObject::obj_defineProperty(JSContext *cx, HandleObject obj,
+                                      HandlePropertyName name, const Value *v,
+                                      PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
+{
+    return obj_defineGeneric(cx, obj, RootedVarId(cx, NameToId(name)), v, getter, setter, attrs);
+}
+
+JSBool
+ArrayBufferObject::obj_defineElement(JSContext *cx, HandleObject obj, uint32_t index, const Value *v,
+                                     PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
+{
+    RootGetterSetter gsRoot(cx, attrs, &getter, &setter);
+
+    RootedVarObject delegate(cx, DelegateObject(cx, obj));
+    if (!delegate)
+        return false;
+    return baseops::DefineElement(cx, delegate, index, v, getter, setter, attrs);
 }
 
 JSBool
-ArrayBufferObject::obj_getProperty(JSContext *cx, JSObject *obj_,
-                                   JSObject *receiver_, PropertyName *name_, Value *vp)
+ArrayBufferObject::obj_defineSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, const Value *v,
+                                     PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
+{
+    return obj_defineGeneric(cx, obj, RootedVarId(cx, SPECIALID_TO_JSID(sid)),
+                             v, getter, setter, attrs);
+}
+
+JSBool
+ArrayBufferObject::obj_getGeneric(JSContext *cx, HandleObject obj, HandleObject receiver,
+                                  HandleId id, Value *vp)
 {
-    RootedVarObject obj(cx, obj_), receiver(cx, receiver_);
-    RootedVarPropertyName name(cx, name_);
-
-    if (!(obj = getArrayBuffer(obj))) {
+    RootedVarObject nobj(cx, getArrayBuffer(obj));
+    JS_ASSERT(nobj);
+
+    if (JSID_IS_ATOM(id, cx->runtime->atomState.byteLengthAtom)) {
+        vp->setInt32(nobj->asArrayBuffer().byteLength());
+        return true;
+    }
+
+    nobj = DelegateObject(cx, nobj);
+    if (!nobj)
+        return false;
+    return baseops::GetProperty(cx, nobj, receiver, id, vp);
+}
+
+JSBool
+ArrayBufferObject::obj_getProperty(JSContext *cx, HandleObject obj,
+                                   HandleObject receiver, HandlePropertyName name, Value *vp)
+{
+    RootedVarObject nobj(cx, getArrayBuffer(obj));
+
+    if (!nobj) {
         JSAutoByteString bs(cx, name);
         if (!bs)
             return false;
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                              JSMSG_INCOMPATIBLE_PROTO, "ArrayBuffer", bs.ptr(), "object");
         return false;
     }
 
     if (name == cx->runtime->atomState.byteLengthAtom) {
-        vp->setInt32(obj->asArrayBuffer().byteLength());
+        vp->setInt32(nobj->asArrayBuffer().byteLength());
         return true;
     }
 
-    RootedVarObject delegate(cx, DelegateObject(cx, obj));
-    if (!delegate)
+    nobj = DelegateObject(cx, nobj);
+    if (!nobj)
         return false;
-    return js_GetProperty(cx, delegate, receiver, NameToId(name), vp);
+    return baseops::GetProperty(cx, nobj, receiver, RootedVarId(cx, NameToId(name)), vp);
 }
 
 JSBool
-ArrayBufferObject::obj_getElement(JSContext *cx, JSObject *obj,
-                                  JSObject *receiver_, uint32_t index, Value *vp)
+ArrayBufferObject::obj_getElement(JSContext *cx, HandleObject obj,
+                                  HandleObject receiver, uint32_t index, Value *vp)
 {
-    RootedVarObject receiver(cx, receiver_);
-
     RootedVarObject delegate(cx, DelegateObject(cx, RootedVarObject(cx, getArrayBuffer(obj))));
     if (!delegate)
         return false;
-    return js_GetElement(cx, delegate, receiver, index, vp);
+    return baseops::GetElement(cx, delegate, receiver, index, vp);
 }
 
 JSBool
-ArrayBufferObject::obj_getElementIfPresent(JSContext *cx, JSObject *obj, JSObject *receiver_,
+ArrayBufferObject::obj_getElementIfPresent(JSContext *cx, HandleObject obj, HandleObject receiver,
                                            uint32_t index, Value *vp, bool *present)
 {
-    RootedVarObject receiver(cx, receiver_);
-
     JSObject *delegate = DelegateObject(cx, RootedVarObject(cx, getArrayBuffer(obj)));
     if (!delegate)
         return false;
     return delegate->getElementIfPresent(cx, receiver, index, vp, present);
 }
 
 JSBool
-ArrayBufferObject::obj_getSpecial(JSContext *cx, JSObject *obj,
-                                  JSObject *receiver, SpecialId sid, Value *vp)
+ArrayBufferObject::obj_getSpecial(JSContext *cx, HandleObject obj,
+                                  HandleObject receiver, HandleSpecialId sid, Value *vp)
 {
-    return obj_getGeneric(cx, obj, receiver, SPECIALID_TO_JSID(sid), vp);
+    return obj_getGeneric(cx, obj, receiver, RootedVarId(cx, SPECIALID_TO_JSID(sid)), vp);
 }
 
 JSBool
-ArrayBufferObject::obj_setGeneric(JSContext *cx, JSObject *obj_, jsid id_, Value *vp, JSBool strict)
+ArrayBufferObject::obj_setGeneric(JSContext *cx, HandleObject obj, HandleId id, Value *vp, JSBool strict)
 {
-    RootedVarObject obj(cx, obj_);
-    RootedVarId id(cx, id_);
-
     if (JSID_IS_ATOM(id, cx->runtime->atomState.byteLengthAtom))
         return true;
 
     RootedVarObject delegate(cx, DelegateObject(cx, obj));
     if (!delegate)
         return false;
 
     if (JSID_IS_ATOM(id, cx->runtime->atomState.protoAtom)) {
@@ -584,17 +568,17 @@ ArrayBufferObject::obj_setGeneric(JSCont
         //
         // otherwise __proto__ was a plain property
         // and we don't modify our prototype chain
         // since obj_getProperty will fetch it as a plain
         // property from the delegate.
 
         RootedVarObject oldDelegateProto(cx, delegate->getProto());
 
-        if (!js_SetPropertyHelper(cx, delegate, id, 0, vp, strict))
+        if (!baseops::SetPropertyHelper(cx, delegate, id, 0, vp, strict))
             return false;
 
         if (delegate->getProto() != oldDelegateProto) {
             // actual __proto__ was set and not a plain property called
             // __proto__
             if (!obj->isExtensible()) {
                 obj->reportNotExtensible(cx);
                 return false;
@@ -604,188 +588,168 @@ ArrayBufferObject::obj_setGeneric(JSCont
                 // restore delegate prototype chain
                 SetProto(cx, delegate, oldDelegateProto, true);
                 return false;
             }
         }
         return true;
     }
 
-    return js_SetPropertyHelper(cx, delegate, id, 0, vp, strict);
+    return baseops::SetPropertyHelper(cx, delegate, id, 0, vp, strict);
 }
 
 JSBool
-ArrayBufferObject::obj_setProperty(JSContext *cx, JSObject *obj,
-                                   PropertyName *name, Value *vp, JSBool strict)
+ArrayBufferObject::obj_setProperty(JSContext *cx, HandleObject obj,
+                                   HandlePropertyName name, Value *vp, JSBool strict)
 {
-    return obj_setGeneric(cx, obj, NameToId(name), vp, strict);
+    return obj_setGeneric(cx, obj, RootedVarId(cx, NameToId(name)), vp, strict);
 }
 
 JSBool
-ArrayBufferObject::obj_setElement(JSContext *cx, JSObject *obj_,
+ArrayBufferObject::obj_setElement(JSContext *cx, HandleObject obj,
                                   uint32_t index, Value *vp, JSBool strict)
 {
-    RootedVarObject obj(cx, obj_);
-
     RootedVarObject delegate(cx, DelegateObject(cx, obj));
     if (!delegate)
         return false;
 
-    return js_SetElementHelper(cx, delegate, index, 0, vp, strict);
+    return baseops::SetElementHelper(cx, delegate, index, 0, vp, strict);
 }
 
 JSBool
-ArrayBufferObject::obj_setSpecial(JSContext *cx, JSObject *obj,
-                                  SpecialId sid, Value *vp, JSBool strict)
+ArrayBufferObject::obj_setSpecial(JSContext *cx, HandleObject obj,
+                                  HandleSpecialId sid, Value *vp, JSBool strict)
 {
-    return obj_setGeneric(cx, obj, SPECIALID_TO_JSID(sid), vp, strict);
+    return obj_setGeneric(cx, obj, RootedVarId(cx, SPECIALID_TO_JSID(sid)), vp, strict);
 }
 
 JSBool
-ArrayBufferObject::obj_getGenericAttributes(JSContext *cx, JSObject *obj_,
-                                            jsid id_, unsigned *attrsp)
+ArrayBufferObject::obj_getGenericAttributes(JSContext *cx, HandleObject obj,
+                                            HandleId id, unsigned *attrsp)
 {
-    RootedVarObject obj(cx, obj_);
-    RootedVarId id(cx, id_);
-
     if (JSID_IS_ATOM(id, cx->runtime->atomState.byteLengthAtom)) {
         *attrsp = JSPROP_PERMANENT | JSPROP_READONLY;
         return true;
     }
 
-    JSObject *delegate = DelegateObject(cx, obj);
+    RootedVarObject delegate(cx, DelegateObject(cx, obj));
     if (!delegate)
         return false;
-    return js_GetAttributes(cx, delegate, id, attrsp);
+    return baseops::GetAttributes(cx, delegate, id, attrsp);
 }
 
 JSBool
-ArrayBufferObject::obj_getPropertyAttributes(JSContext *cx, JSObject *obj,
-                                             PropertyName *name, unsigned *attrsp)
+ArrayBufferObject::obj_getPropertyAttributes(JSContext *cx, HandleObject obj,
+                                             HandlePropertyName name, unsigned *attrsp)
 {
-    return obj_getGenericAttributes(cx, obj, NameToId(name), attrsp);
+    return obj_getGenericAttributes(cx, obj, RootedVarId(cx, NameToId(name)), attrsp);
 }
 
 JSBool
-ArrayBufferObject::obj_getElementAttributes(JSContext *cx, JSObject *obj_,
+ArrayBufferObject::obj_getElementAttributes(JSContext *cx, HandleObject obj,
                                             uint32_t index, unsigned *attrsp)
 {
-    RootedVarObject obj(cx, obj_);
-
-    JSObject *delegate = DelegateObject(cx, obj);
+    RootedVarObject delegate(cx, DelegateObject(cx, obj));
     if (!delegate)
         return false;
-    return js_GetElementAttributes(cx, delegate, index, attrsp);
+    return baseops::GetElementAttributes(cx, delegate, index, attrsp);
 }
 
 JSBool
-ArrayBufferObject::obj_getSpecialAttributes(JSContext *cx, JSObject *obj,
-                                            SpecialId sid, unsigned *attrsp)
+ArrayBufferObject::obj_getSpecialAttributes(JSContext *cx, HandleObject obj,
+                                            HandleSpecialId sid, unsigned *attrsp)
 {
-    return obj_getGenericAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp);
+    return obj_getGenericAttributes(cx, obj, RootedVarId(cx, SPECIALID_TO_JSID(sid)), attrsp);
 }
 
 JSBool
-ArrayBufferObject::obj_setGenericAttributes(JSContext *cx, JSObject *obj_,
-                                            jsid id_, unsigned *attrsp)
+ArrayBufferObject::obj_setGenericAttributes(JSContext *cx, HandleObject obj,
+                                            HandleId id, unsigned *attrsp)
 {
-    RootedVarObject obj(cx, obj_);
-    RootedVarId id(cx, id_);
-
     if (JSID_IS_ATOM(id, cx->runtime->atomState.byteLengthAtom)) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                              JSMSG_CANT_SET_ARRAY_ATTRS);
         return false;
     }
 
-    JSObject *delegate = DelegateObject(cx, obj);
+    RootedVarObject delegate(cx, DelegateObject(cx, obj));
     if (!delegate)
         return false;
-    return js_SetAttributes(cx, delegate, id, attrsp);
+    return baseops::SetAttributes(cx, delegate, id, attrsp);
 }
 
 JSBool
-ArrayBufferObject::obj_setPropertyAttributes(JSContext *cx, JSObject *obj,
-                                             PropertyName *name, unsigned *attrsp)
+ArrayBufferObject::obj_setPropertyAttributes(JSContext *cx, HandleObject obj,
+                                             HandlePropertyName name, unsigned *attrsp)
 {
-    return obj_setGenericAttributes(cx, obj, NameToId(name), attrsp);
+    return obj_setGenericAttributes(cx, obj, RootedVarId(cx, NameToId(name)), attrsp);
 }
 
 JSBool
-ArrayBufferObject::obj_setElementAttributes(JSContext *cx, JSObject *obj_,
+ArrayBufferObject::obj_setElementAttributes(JSContext *cx, HandleObject obj,
                                             uint32_t index, unsigned *attrsp)
 {
-    RootedVarObject obj(cx, obj_);
-
-    JSObject *delegate = DelegateObject(cx, obj);
+    RootedVarObject delegate(cx, DelegateObject(cx, obj));
     if (!delegate)
         return false;
-    return js_SetElementAttributes(cx, delegate, index, attrsp);
+    return baseops::SetElementAttributes(cx, delegate, index, attrsp);
 }
 
 JSBool
-ArrayBufferObject::obj_setSpecialAttributes(JSContext *cx, JSObject *obj,
-                                            SpecialId sid, unsigned *attrsp)
+ArrayBufferObject::obj_setSpecialAttributes(JSContext *cx, HandleObject obj,
+                                            HandleSpecialId sid, unsigned *attrsp)
 {
-    return obj_setGenericAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp);
+    return obj_setGenericAttributes(cx, obj, RootedVarId(cx, SPECIALID_TO_JSID(sid)), attrsp);
 }
 
 JSBool
-ArrayBufferObject::obj_deleteProperty(JSContext *cx, JSObject *obj_,
-                                      PropertyName *name_, Value *rval, JSBool strict)
+ArrayBufferObject::obj_deleteProperty(JSContext *cx, HandleObject obj,
+                                      HandlePropertyName name, Value *rval, JSBool strict)
 {
-    RootedVarObject obj(cx, obj_);
-    RootedVarPropertyName name(cx, name_);
-
     if (name == cx->runtime->atomState.byteLengthAtom) {
         rval->setBoolean(false);
         return true;
     }
 
-    JSObject *delegate = DelegateObject(cx, obj);
+    RootedVarObject delegate(cx, DelegateObject(cx, obj));
     if (!delegate)
         return false;
-    return js_DeleteProperty(cx, delegate, name, rval, strict);
+    return baseops::DeleteProperty(cx, delegate, name, rval, strict);
 }
 
 JSBool
-ArrayBufferObject::obj_deleteElement(JSContext *cx, JSObject *obj_,
+ArrayBufferObject::obj_deleteElement(JSContext *cx, HandleObject obj,
                                      uint32_t index, Value *rval, JSBool strict)
 {
-    RootedVarObject obj(cx, obj_);
-
-    JSObject *delegate = DelegateObject(cx, obj);
+    RootedVarObject delegate(cx, DelegateObject(cx, obj));
     if (!delegate)
         return false;
-    return js_DeleteElement(cx, delegate, index, rval, strict);
+    return baseops::DeleteElement(cx, delegate, index, rval, strict);
 }
 
 JSBool
-ArrayBufferObject::obj_deleteSpecial(JSContext *cx, JSObject *obj_,
-                                     SpecialId sid_, Value *rval, JSBool strict)
+ArrayBufferObject::obj_deleteSpecial(JSContext *cx, HandleObject obj,
+                                     HandleSpecialId sid, Value *rval, JSBool strict)
 {
-    RootedVarObject obj(cx, obj_);
-    RootedVar<SpecialId> sid(cx, sid_);
-
-    JSObject *delegate = DelegateObject(cx, obj);
+    RootedVarObject delegate(cx, DelegateObject(cx, obj));
     if (!delegate)
         return false;
-    return js_DeleteSpecial(cx, delegate, sid, rval, strict);
+    return baseops::DeleteSpecial(cx, delegate, sid, rval, strict);
 }
 
 JSBool
-ArrayBufferObject::obj_enumerate(JSContext *cx, JSObject *obj,
+ArrayBufferObject::obj_enumerate(JSContext *cx, HandleObject obj,
                                  JSIterateOp enum_op, Value *statep, jsid *idp)
 {
     statep->setNull();
     return true;
 }
 
 JSType
-ArrayBufferObject::obj_typeOf(JSContext *cx, JSObject *obj)
+ArrayBufferObject::obj_typeOf(JSContext *cx, HandleObject obj)
 {
     return JSTYPE_OBJECT;
 }
 
 /*
  * ArrayBufferViews of various sorts
  */
 
@@ -840,69 +804,77 @@ js::IsDataView(JSObject* obj)
     return obj->isDataView();
 }
 
 /*
  * For now (until slots directly hold data)
  * slots data element points to the JSObject representing the ArrayBuffer.
  */
 JSBool
-TypedArray::prop_getBuffer(JSContext *cx, JSObject *obj, jsid id, Value *vp)
+TypedArray::prop_getBuffer(JSContext *cx, HandleObject obj, HandleId id, Value *vp)
 {
-    if (!(obj = getTypedArray(obj))) {
+    JSObject *tarray = getTypedArray(obj);
+
+    if (!tarray) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                              JSMSG_INCOMPATIBLE_PROTO, "TypedArray", "buffer", "object");
         return false;
     }
 
-    JS_SET_RVAL(cx, vp, ObjectValue(*TypedArray::getBuffer(obj)));
+    JS_SET_RVAL(cx, vp, ObjectValue(*TypedArray::getBuffer(tarray)));
     return true;
 }
 
 JSBool
-TypedArray::prop_getByteOffset(JSContext *cx, JSObject *obj, jsid id, Value *vp)
+TypedArray::prop_getByteOffset(JSContext *cx, HandleObject obj, HandleId id, Value *vp)
 {
-    if (!(obj = getTypedArray(obj))) {
+    JSObject *tarray = getTypedArray(obj);
+
+    if (!tarray) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                              JSMSG_INCOMPATIBLE_PROTO, "TypedArray", "byteOffset", "object");
         return false;
     }
 
-    JS_SET_RVAL(cx, vp, Int32Value(TypedArray::getByteOffset(obj)));
+    JS_SET_RVAL(cx, vp, Int32Value(TypedArray::getByteOffset(tarray)));
     return true;
 }
 
 JSBool
-TypedArray::prop_getByteLength(JSContext *cx, JSObject *obj, jsid id, Value *vp)
+TypedArray::prop_getByteLength(JSContext *cx, HandleObject obj, HandleId id, Value *vp)
 {
-    if (!(obj = getTypedArray(obj))) {
+    JSObject *tarray = getTypedArray(obj);
+
+    if (!tarray) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                              JSMSG_INCOMPATIBLE_PROTO, "TypedArray", "byteLength", "object");
         return false;
     }
 
-    JS_SET_RVAL(cx, vp, Int32Value(TypedArray::getByteLength(obj)));
+    JS_SET_RVAL(cx, vp, Int32Value(TypedArray::getByteLength(tarray)));
     return true;
 }
 
 JSBool
-TypedArray::prop_getLength(JSContext *cx, JSObject *obj, jsid id, Value *vp)
+TypedArray::prop_getLength(JSContext *cx, HandleObject obj, HandleId id, Value *vp)
 {
-    if (!(obj = getTypedArray(obj))) {
+    JSObject *tarray = getTypedArray(obj);
+
+    if (!tarray) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                              JSMSG_INCOMPATIBLE_PROTO, "TypedArray", "length", "object");
         return false;
     }
 
-    JS_SET_RVAL(cx, vp, Int32Value(TypedArray::getLength(obj)));
+    JS_SET_RVAL(cx, vp, Int32Value(TypedArray::getLength(tarray)));
     return true;
 }
 
 JSBool
-TypedArray::obj_lookupGeneric(JSContext *cx, JSObject *obj, jsid id,
+TypedArray::obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id,
                               JSObject **objp, JSProperty **propp)
 {
     JSObject *tarray = getTypedArray(obj);
     JS_ASSERT(tarray);
 
     if (isArrayIndex(cx, tarray, id)) {
         *propp = PROPERTY_FOUND;
         *objp = obj;
@@ -915,24 +887,24 @@ TypedArray::obj_lookupGeneric(JSContext 
         *propp = NULL;
         return true;
     }
 
     return proto->lookupGeneric(cx, id, objp, propp);
 }
 
 JSBool
-TypedArray::obj_lookupProperty(JSContext *cx, JSObject *obj, PropertyName *name,
+TypedArray::obj_lookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
                                JSObject **objp, JSProperty **propp)
 {
-    return obj_lookupGeneric(cx, obj, NameToId(name), objp, propp);
+    return obj_lookupGeneric(cx, obj, RootedVarId(cx, NameToId(name)), objp, propp);
 }
 
 JSBool
-TypedArray::obj_lookupElement(JSContext *cx, JSObject *obj, uint32_t index,
+TypedArray::obj_lookupElement(JSContext *cx, HandleObject obj, uint32_t index,
                               JSObject **objp, JSProperty **propp)
 {
     JSObject *tarray = getTypedArray(obj);
     JS_ASSERT(tarray);
 
     if (index < getLength(tarray)) {
         *propp = PROPERTY_FOUND;
         *objp = obj;
@@ -943,74 +915,74 @@ TypedArray::obj_lookupElement(JSContext 
         return proto->lookupElement(cx, index, objp, propp);
 
     *objp = NULL;
     *propp = NULL;
     return true;
 }
 
 JSBool
-TypedArray::obj_lookupSpecial(JSContext *cx, JSObject *obj, SpecialId sid,
+TypedArray::obj_lookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid,
                               JSObject **objp, JSProperty **propp)
 {
-    return obj_lookupGeneric(cx, obj, SPECIALID_TO_JSID(sid), objp, propp);
+    return obj_lookupGeneric(cx, obj, RootedVarId(cx, SPECIALID_TO_JSID(sid)), objp, propp);
 }
 
 JSBool
-TypedArray::obj_getGenericAttributes(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp)
+TypedArray::obj_getGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp)
 {
     *attrsp = (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom))
               ? JSPROP_PERMANENT | JSPROP_READONLY
               : JSPROP_PERMANENT | JSPROP_ENUMERATE;
     return true;
 }
 
 JSBool
-TypedArray::obj_getPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, unsigned *attrsp)
+TypedArray::obj_getPropertyAttributes(JSContext *cx, HandleObject obj, HandlePropertyName name, unsigned *attrsp)
 {
     *attrsp = JSPROP_PERMANENT | JSPROP_ENUMERATE;
     return true;
 }
 
 JSBool
-TypedArray::obj_getElementAttributes(JSContext *cx, JSObject *obj, uint32_t index, unsigned *attrsp)
+TypedArray::obj_getElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp)
 {
     *attrsp = JSPROP_PERMANENT | JSPROP_ENUMERATE;
     return true;
 }
 
 JSBool
-TypedArray::obj_getSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, unsigned *attrsp)
+TypedArray::obj_getSpecialAttributes(JSContext *cx, HandleObject obj, HandleSpecialId sid, unsigned *attrsp)
 {
-    return obj_getGenericAttributes(cx, obj, SPECIALID_TO_JSID(sid), attrsp);
+    return obj_getGenericAttributes(cx, obj, RootedVarId(cx, SPECIALID_TO_JSID(sid)), attrsp);
 }
 
 JSBool
-TypedArray::obj_setGenericAttributes(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp)
+TypedArray::obj_setGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp)
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_SET_ARRAY_ATTRS);
     return false;
 }
 
 JSBool
-TypedArray::obj_setPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, unsigned *attrsp)
+TypedArray::obj_setPropertyAttributes(JSContext *cx, HandleObject obj, HandlePropertyName name, unsigned *attrsp)
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_SET_ARRAY_ATTRS);
     return false;
 }
 
 JSBool
-TypedArray::obj_setElementAttributes(JSContext *cx, JSObject *obj, uint32_t index, unsigned *attrsp)
+TypedArray::obj_setElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp)
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_SET_ARRAY_ATTRS);
     return false;
 }
 
 JSBool
-TypedArray::obj_setSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, unsigned *attrsp)
+TypedArray::obj_setSpecialAttributes(JSContext *cx, HandleObject obj, HandleSpecialId sid, unsigned *attrsp)
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_SET_ARRAY_ATTRS);
     return false;
 }
 
 /* static */ int
 TypedArray::lengthOffset()
 {
@@ -1106,17 +1078,17 @@ class TypedArrayTemplate
 
     static void
     obj_trace(JSTracer *trc, JSObject *obj)
     {
         MarkSlot(trc, &obj->getFixedSlotRef(FIELD_BUFFER), "typedarray.buffer");
     }
 
     static JSBool
-    obj_getProperty(JSContext *cx, JSObject *obj, JSObject *receiver, PropertyName *name,
+    obj_getProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandlePropertyName name,
                     Value *vp)
     {
         JSObject *tarray = getTypedArray(obj);
 
         if (name == cx->runtime->atomState.lengthAtom) {
             vp->setNumber(getLength(tarray));
             return true;
         }
@@ -1126,17 +1098,17 @@ class TypedArrayTemplate
             vp->setUndefined();
             return true;
         }
 
         return proto->getProperty(cx, receiver, name, vp);
     }
 
     static JSBool
-    obj_getElement(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t index, Value *vp)
+    obj_getElement(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index, Value *vp)
     {
         JSObject *tarray = getTypedArray(obj);
 
         if (index < getLength(tarray)) {
             copyIndexToValue(cx, tarray, index, vp);
             return true;
         }
 
@@ -1145,52 +1117,52 @@ class TypedArrayTemplate
             vp->setUndefined();
             return true;
         }
 
         return proto->getElement(cx, receiver, index, vp);
     }
 
     static JSBool
-    obj_getSpecial(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid, Value *vp)
+    obj_getSpecial(JSContext *cx, HandleObject obj, HandleObject receiver, HandleSpecialId sid, Value *vp)
     {
         JSObject *proto = obj->getProto();
         if (!proto) {
             vp->setUndefined();
             return true;
         }
 
         return proto->getSpecial(cx, receiver, sid, vp);
     }
 
     static JSBool
-    obj_getGeneric(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp)
+    obj_getGeneric(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id, Value *vp)
     {
         Value idval = IdToValue(id);
 
         uint32_t index;
         if (IsDefinitelyIndex(idval, &index))
             return obj_getElement(cx, obj, receiver, index, vp);
 
         SpecialId sid;
         if (ValueIsSpecial(obj, &idval, &sid, cx))
-            return obj_getSpecial(cx, obj, receiver, sid, vp);
+            return obj_getSpecial(cx, obj, receiver, RootedVar<SpecialId>(cx, sid), vp);
 
         JSAtom *atom;
         if (!js_ValueToAtom(cx, idval, &atom))
             return false;
 
         if (atom->isIndex(&index))
             return obj_getElement(cx, obj, receiver, index, vp);
 
-        return obj_getProperty(cx, obj, receiver, atom->asPropertyName(), vp);
+        return obj_getProperty(cx, obj, receiver, RootedVarPropertyName(cx, atom->asPropertyName()), vp);
     }
 
     static JSBool
-    obj_getElementIfPresent(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t index, Value *vp, bool *present)
+    obj_getElementIfPresent(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index, Value *vp, bool *present)
     {
         // Fast-path the common case of index < length
         JSObject *tarray = getTypedArray(obj);
 
         if (index < getLength(tarray)) {
             // this inline function is specialized for each type
             copyIndexToValue(cx, tarray, index, vp);
             *present = true;
@@ -1266,17 +1238,17 @@ class TypedArrayTemplate
             int32_t n = ToInt32(d);
             setIndex(tarray, index, NativeType(n));
         }
 
         return true;
     }
 
     static JSBool
-    obj_setGeneric(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
+    obj_setGeneric(JSContext *cx, HandleObject obj, HandleId id, Value *vp, JSBool strict)
     {
         RootedVarObject tarray(cx, getTypedArray(obj));
         JS_ASSERT(tarray);
 
         if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) {
             vp->setNumber(getLength(tarray));
             return true;
         }
@@ -1292,23 +1264,23 @@ class TypedArrayTemplate
             vp->setUndefined();
             return true;
         }
 
         return setElementTail(cx, tarray, index, vp, strict);
     }
 
     static JSBool
-    obj_setProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict)
+    obj_setProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, Value *vp, JSBool strict)
     {
-        return obj_setGeneric(cx, obj, NameToId(name), vp, strict);
+        return obj_setGeneric(cx, obj, RootedVarId(cx, NameToId(name)), vp, strict);
     }
 
     static JSBool
-    obj_setElement(JSContext *cx, JSObject *obj, uint32_t index, Value *vp, JSBool strict)
+    obj_setElement(JSContext *cx, HandleObject obj, uint32_t index, Value *vp, JSBool strict)
     {
         RootedVarObject tarray(cx, getTypedArray(obj));
         JS_ASSERT(tarray);
 
         if (index >= getLength(tarray)) {
             // Silent ignore is better than an exception here, because
             // at some point we may want to support other properties on
             // these objects.  This is especially true when these arrays
@@ -1317,90 +1289,90 @@ class TypedArrayTemplate
             vp->setUndefined();
             return true;
         }
 
         return setElementTail(cx, tarray, index, vp, strict);
     }
 
     static JSBool
-    obj_setSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict)
+    obj_setSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, Value *vp, JSBool strict)
     {
-        return obj_setGeneric(cx, obj, SPECIALID_TO_JSID(sid), vp, strict);
+        return obj_setGeneric(cx, obj, RootedVarId(cx, SPECIALID_TO_JSID(sid)), vp, strict);
     }
 
     static JSBool
-    obj_defineGeneric(JSContext *cx, JSObject *obj, jsid id, const Value *v,
+    obj_defineGeneric(JSContext *cx, HandleObject obj, HandleId id, const Value *v,
                       PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
     {
         if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom))
             return true;
 
         Value tmp = *v;
         return obj_setGeneric(cx, obj, id, &tmp, false);
     }
 
     static JSBool
-    obj_defineProperty(JSContext *cx, JSObject *obj, PropertyName *name, const Value *v,
+    obj_defineProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, const Value *v,
                        PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
     {
-        return obj_defineGeneric(cx, obj, NameToId(name), v, getter, setter, attrs);
+        return obj_defineGeneric(cx, obj, RootedVarId(cx, NameToId(name)), v, getter, setter, attrs);
     }