bug 493457 - uniform access to private slots. r=mrbkap, sr=jwalden
authorIgor Bukanov <igor@mir2.org>
Tue, 04 Aug 2009 23:06:55 +0200
changeset 31452 c532c2a2448d4779db30943c3696c0baa976c16e
parent 31451 856eda515ea95ad440b6255a844deb11aae1130b
child 31453 64d47298dd872d2f7ff4cf7894194ec3d34ca49d
push idunknown
push userunknown
push dateunknown
reviewersmrbkap, jwalden
bugs493457
milestone1.9.2a1pre
bug 493457 - uniform access to private slots. r=mrbkap, sr=jwalden
js/src/jsapi.cpp
js/src/jsarray.cpp
js/src/jsbool.cpp
js/src/jsdbgapi.cpp
js/src/jsexn.cpp
js/src/jsfun.cpp
js/src/jsfun.h
js/src/jsinterp.cpp
js/src/jsiter.cpp
js/src/jsnum.cpp
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsregexp.cpp
js/src/jsscript.cpp
js/src/jsscript.h
js/src/jsstr.cpp
js/src/jstracer.cpp
js/src/jsxml.cpp
js/src/xpconnect/src/xpcprivate.h
js/src/xpconnect/src/xpcquickstubs.cpp
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -270,17 +270,17 @@ JS_ConvertArgumentsVA(JSContext *cx, uin
             *sp = OBJECT_TO_JSVAL(obj);
             *va_arg(ap, JSObject **) = obj;
             break;
           case 'f':
             obj = js_ValueToFunctionObject(cx, sp, 0);
             if (!obj)
                 return JS_FALSE;
             *sp = OBJECT_TO_JSVAL(obj);
-            *va_arg(ap, JSFunction **) = (JSFunction *) JS_GetPrivate(cx, obj);
+            *va_arg(ap, JSFunction **) = GET_FUNCTION_PRIVATE(cx, obj);
             break;
           case 'v':
             *va_arg(ap, jsval *) = *sp;
             break;
           case '*':
             break;
           default:
             format--;
@@ -2052,23 +2052,19 @@ JS_PrintTraceThingInfo(char *buf, size_t
       case JSTRACE_OBJECT:
       {
         JSObject *obj = (JSObject *)thing;
         JSClass *clasp = STOBJ_GET_CLASS(obj);
 
         name = clasp->name;
 #ifdef HAVE_XPCONNECT
         if (clasp->flags & JSCLASS_PRIVATE_IS_NSISUPPORTS) {
-            jsval privateValue = STOBJ_GET_SLOT(obj, JSSLOT_PRIVATE);
-
-            JS_ASSERT(clasp->flags & JSCLASS_HAS_PRIVATE);
-            if (!JSVAL_IS_VOID(privateValue)) {
-                void  *privateThing = JSVAL_TO_PRIVATE(privateValue);
+            void *privateThing = obj->getPrivate();
+            if (privateThing) {
                 const char *xpcClassName = GetXPCObjectClassName(privateThing);
-
                 if (xpcClassName)
                     name = xpcClassName;
             }
         }
 #endif
         break;
       }
 
@@ -2105,35 +2101,28 @@ JS_PrintTraceThingInfo(char *buf, size_t
         bufsize--;
 
         switch (kind) {
           case JSTRACE_OBJECT:
           {
             JSObject  *obj = (JSObject *)thing;
             JSClass *clasp = STOBJ_GET_CLASS(obj);
             if (clasp == &js_FunctionClass) {
-                JSFunction *fun = (JSFunction *)
-                                  JS_GetPrivate(trc->context, obj);
-
+                JSFunction *fun = GET_FUNCTION_PRIVATE(trc->context, obj);
                 if (!fun) {
                     JS_snprintf(buf, bufsize, "<newborn>");
                 } else if (FUN_OBJECT(fun) != obj) {
                     JS_snprintf(buf, bufsize, "%p", fun);
                 } else {
                     if (fun->atom && ATOM_IS_STRING(fun->atom))
                         js_PutEscapedString(buf, bufsize,
                                             ATOM_TO_STRING(fun->atom), 0);
                 }
             } else if (clasp->flags & JSCLASS_HAS_PRIVATE) {
-                jsval     privateValue = STOBJ_GET_SLOT(obj, JSSLOT_PRIVATE);
-                void      *privateThing = JSVAL_IS_VOID(privateValue)
-                                          ? NULL
-                                          : JSVAL_TO_PRIVATE(privateValue);
-
-                JS_snprintf(buf, bufsize, "%p", privateThing);
+                JS_snprintf(buf, bufsize, "%p", obj->getPrivate());
             } else {
                 JS_snprintf(buf, bufsize, "<no private>");
             }
             break;
           }
 
           case JSTRACE_STRING:
             js_PutEscapedString(buf, bufsize, (JSString *)thing, 0);
@@ -2771,23 +2760,17 @@ JS_PUBLIC_API(JSBool)
 JS_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
 {
     return js_HasInstance(cx, obj, v, bp);
 }
 
 JS_PUBLIC_API(void *)
 JS_GetPrivate(JSContext *cx, JSObject *obj)
 {
-    jsval v;
-
-    JS_ASSERT(OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_HAS_PRIVATE);
-    v = obj->fslots[JSSLOT_PRIVATE];
-    if (!JSVAL_IS_INT(v))
-        return NULL;
-    return JSVAL_TO_PRIVATE(v);
+    return obj->getPrivate();
 }
 
 JS_PUBLIC_API(JSBool)
 JS_SetPrivate(JSContext *cx, JSObject *obj, void *data)
 {
     JS_ASSERT(OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_HAS_PRIVATE);
     obj->fslots[JSSLOT_PRIVATE] = PRIVATE_TO_JSVAL(data);
     return JS_TRUE;
@@ -4010,67 +3993,48 @@ error:
 
 /*
  * XXX reverse iterator for properties, unreverse and meld with jsinterp.c's
  *     prop_iterator_class somehow...
  * + preserve the OBJ_ENUMERATE API while optimizing the native object case
  * + native case here uses a JSScopeProperty *, but that iterates in reverse!
  * + so we make non-native match, by reverse-iterating after JS_Enumerating
  */
-#define JSSLOT_ITER_INDEX       (JSSLOT_PRIVATE + 1)
-
-#if JSSLOT_ITER_INDEX >= JS_INITIAL_NSLOTS
-# error "JSSLOT_ITER_INDEX botch!"
-#endif
+const uint32 JSSLOT_ITER_INDEX = JSSLOT_PRIVATE + 1;
+JS_STATIC_ASSERT(JSSLOT_ITER_INDEX < JS_INITIAL_NSLOTS);
 
 static void
 prop_iter_finalize(JSContext *cx, JSObject *obj)
 {
-    jsval v;
-    jsint i;
-    JSIdArray *ida;
-
-    v = obj->fslots[JSSLOT_ITER_INDEX];
-    if (JSVAL_IS_VOID(v))
+    void *pdata = obj->getPrivate();
+    if (!pdata)
         return;
 
-    i = JSVAL_TO_INT(v);
-    if (i >= 0) {
+    if (JSVAL_TO_INT(obj->fslots[JSSLOT_ITER_INDEX]) >= 0) {
         /* Non-native case: destroy the ida enumerated when obj was created. */
-        ida = (JSIdArray *) JS_GetPrivate(cx, obj);
-        if (ida)
-            JS_DestroyIdArray(cx, ida);
+        JSIdArray *ida = (JSIdArray *) pdata;
+        JS_DestroyIdArray(cx, ida);
     }
 }
 
 static void
 prop_iter_trace(JSTracer *trc, JSObject *obj)
 {
-    jsval v;
-    jsint i, n;
-    JSScopeProperty *sprop;
-    JSIdArray *ida;
-    jsid id;
-
-    v = obj->fslots[JSSLOT_PRIVATE];
-    JS_ASSERT(!JSVAL_IS_VOID(v));
-
-    i = JSVAL_TO_INT(obj->fslots[JSSLOT_ITER_INDEX]);
-    if (i < 0) {
+    void *pdata = obj->getPrivate();
+    if (!pdata)
+        return;
+
+    if (JSVAL_TO_INT(obj->fslots[JSSLOT_ITER_INDEX]) < 0) {
         /* Native case: just mark the next property to visit. */
-        sprop = (JSScopeProperty *) JSVAL_TO_PRIVATE(v);
-        if (sprop)
-            sprop->trace(trc);
+        ((JSScopeProperty *) pdata)->trace(trc);
     } else {
         /* Non-native case: mark each id in the JSIdArray private. */
-        ida = (JSIdArray *) JSVAL_TO_PRIVATE(v);
-        for (i = 0, n = ida->length; i < n; i++) {
-            id = ida->vector[i];
-            js_TraceId(trc, id);
-        }
+        JSIdArray *ida = (JSIdArray *) pdata;
+        for (jsint i = 0, n = ida->length; i < n; i++)
+            js_TraceId(trc, ida->vector[i]);
     }
 }
 
 static JSClass prop_iter_class = {
     "PropertyIterator",
     JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1) |
     JSCLASS_MARK_IS_TRACE,
     JS_PropertyStub,  JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
@@ -4094,60 +4058,53 @@ JS_NewPropertyIterator(JSContext *cx, JS
         return NULL;
 
     if (OBJ_IS_NATIVE(obj)) {
         /* Native case: start with the last property in obj's own scope. */
         scope = OBJ_SCOPE(obj);
         pdata = scope->lastProp;
         index = -1;
     } else {
-        JSTempValueRooter tvr;
-
         /*
          * Non-native case: enumerate a JSIdArray and keep it via private.
          *
          * Note: we have to make sure that we root obj around the call to
          * JS_Enumerate to protect against multiple allocations under it.
          */
-        JS_PUSH_SINGLE_TEMP_ROOT(cx, OBJECT_TO_JSVAL(iterobj), &tvr);
+        JSAutoTempValueRooter tvr(cx, iterobj);
         ida = JS_Enumerate(cx, obj);
-        JS_POP_TEMP_ROOT(cx, &tvr);
         if (!ida)
-            goto bad;
+            return NULL;
         pdata = ida;
         index = ida->length;
     }
 
     /* iterobj cannot escape to other threads here. */
-    STOBJ_SET_SLOT(iterobj, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(pdata));
-    STOBJ_SET_SLOT(iterobj, JSSLOT_ITER_INDEX, INT_TO_JSVAL(index));
+    iterobj->setPrivate(pdata);
+    iterobj->fslots[JSSLOT_ITER_INDEX] = INT_TO_JSVAL(index);
     return iterobj;
-
-bad:
-    cx->weakRoots.newborn[GCX_OBJECT] = NULL;
-    return NULL;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp)
 {
     jsint i;
     JSObject *obj;
     JSScope *scope;
     JSScopeProperty *sprop;
     JSIdArray *ida;
 
     CHECK_REQUEST(cx);
-    i = JSVAL_TO_INT(OBJ_GET_SLOT(cx, iterobj, JSSLOT_ITER_INDEX));
+    i = JSVAL_TO_INT(iterobj->fslots[JSSLOT_ITER_INDEX]);
     if (i < 0) {
         /* Native case: private data is a property tree node pointer. */
         obj = OBJ_GET_PARENT(cx, iterobj);
         JS_ASSERT(OBJ_IS_NATIVE(obj));
         scope = OBJ_SCOPE(obj);
-        sprop = (JSScopeProperty *) JS_GetPrivate(cx, iterobj);
+        sprop = (JSScopeProperty *) iterobj->getAssignedPrivate();
 
         /*
          * If the next property mapped by scope in the property tree ancestor
          * line is not enumerable, or it's an alias, or one or more properties
          * were deleted from the "middle" of the scope-mapped ancestor line
          * and the next property was among those deleted, skip it and keep on
          * trying to find an enumerable property that is still in scope.
          */
@@ -4156,23 +4113,22 @@ JS_NextProperty(JSContext *cx, JSObject 
                 (sprop->flags & SPROP_IS_ALIAS) ||
                 (scope->hadMiddleDelete() && !scope->has(sprop)))) {
             sprop = sprop->parent;
         }
 
         if (!sprop) {
             *idp = JSVAL_VOID;
         } else {
-            if (!JS_SetPrivate(cx, iterobj, sprop->parent))
-                return JS_FALSE;
+            iterobj->setPrivate(sprop->parent);
             *idp = sprop->id;
         }
     } else {
         /* Non-native case: use the ida enumerated when iterobj was created. */
-        ida = (JSIdArray *) JS_GetPrivate(cx, iterobj);
+        ida = (JSIdArray *) iterobj->getAssignedPrivate();
         JS_ASSERT(i <= ida->length);
         if (i == 0) {
             *idp = JSVAL_VOID;
         } else {
             *idp = ida->vector[--i];
             STOBJ_SET_SLOT(iterobj, JSSLOT_ITER_INDEX, INT_TO_JSVAL(i));
         }
     }
@@ -4800,17 +4756,17 @@ JS_NewScriptObject(JSContext *cx, JSScri
     if (!script)
         return js_NewObject(cx, &js_ScriptClass, NULL, NULL);
 
     JS_ASSERT(!script->u.object);
 
     JS_PUSH_TEMP_ROOT_SCRIPT(cx, script, &tvr);
     obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL);
     if (obj) {
-        JS_SetPrivate(cx, obj, script);
+        obj->setPrivate(script);
         script->u.object = obj;
 #ifdef CHECK_SCRIPT_OWNER
         script->owner = NULL;
 #endif
     }
     JS_POP_TEMP_ROOT(cx, &tvr);
     return obj;
 }
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -1240,27 +1240,29 @@ JSObjectOps js_ArrayObjectOps = {
 static JSObjectOps *
 array_getObjectOps(JSContext *cx, JSClass *clasp)
 {
     return &js_ArrayObjectOps;
 }
 
 JSClass js_ArrayClass = {
     "Array",
-    JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Array) |
-    JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_NEW_ENUMERATE,
+    JSCLASS_HAS_RESERVED_SLOTS(2) |
+    JSCLASS_HAS_CACHED_PROTO(JSProto_Array) |
+    JSCLASS_NEW_ENUMERATE,
     JS_PropertyStub,    JS_PropertyStub,   JS_PropertyStub,   JS_PropertyStub,
     JS_EnumerateStub,   JS_ResolveStub,    js_TryValueOf,     array_finalize,
     array_getObjectOps, NULL,              NULL,              NULL,
     NULL,               NULL,              NULL,              NULL
 };
 
 JSClass js_SlowArrayClass = {
     "Array",
-    JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Array),
+    JSCLASS_HAS_RESERVED_SLOTS(1) |
+    JSCLASS_HAS_CACHED_PROTO(JSProto_Array),
     slowarray_addProperty, JS_PropertyStub, JS_PropertyStub,  JS_PropertyStub,
     JS_EnumerateStub,      JS_ResolveStub,  js_TryValueOf,    NULL,
     slowarray_getObjectOps, NULL,           NULL,             NULL,
     NULL,                  NULL,            NULL,             NULL
 };
 
 /*
  * Convert an array object from fast-and-dense to slow-and-flexible.
--- a/js/src/jsbool.cpp
+++ b/js/src/jsbool.cpp
@@ -59,17 +59,17 @@ JS_STATIC_ASSERT(!(JSVAL_TRUE & JSVAL_HO
 JS_STATIC_ASSERT(!(JSVAL_FALSE & JSVAL_HOLE_FLAG));
 JS_STATIC_ASSERT(!(JSVAL_VOID & JSVAL_HOLE_FLAG));
 JS_STATIC_ASSERT((JSVAL_HOLE & JSVAL_HOLE_FLAG));
 JS_STATIC_ASSERT((JSVAL_HOLE & ~JSVAL_HOLE_FLAG) == JSVAL_VOID);
 JS_STATIC_ASSERT(!(JSVAL_ARETURN & JSVAL_HOLE_FLAG));
 
 JSClass js_BooleanClass = {
     "Boolean",
-    JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Boolean),
+    JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_HAS_CACHED_PROTO(JSProto_Boolean),
     JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,
     JS_EnumerateStub, JS_ResolveStub,   JS_ConvertStub,   NULL,
     JSCLASS_NO_OPTIONAL_MEMBERS
 };
 
 #if JS_HAS_TOSOURCE
 #include "jsprf.h"
 
@@ -131,34 +131,33 @@ static JSFunctionSpec boolean_methods[] 
 static JSBool
 Boolean(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 {
     jsval bval;
 
     bval = (argc != 0)
            ? BOOLEAN_TO_JSVAL(js_ValueToBoolean(argv[0]))
            : JSVAL_FALSE;
-    if (!JS_IsConstructing(cx)) {
+    if (!JS_IsConstructing(cx))
         *rval = bval;
-        return JS_TRUE;
-    }
-    STOBJ_SET_SLOT(obj, JSSLOT_PRIVATE, bval);
-    return JS_TRUE;
+    else
+        obj->fslots[JSSLOT_PRIVATE] = bval;
+    return true;
 }
 
 JSObject *
 js_InitBooleanClass(JSContext *cx, JSObject *obj)
 {
     JSObject *proto;
 
     proto = JS_InitClass(cx, obj, NULL, &js_BooleanClass, Boolean, 1,
                         NULL, boolean_methods, NULL, NULL);
     if (!proto)
         return NULL;
-    STOBJ_SET_SLOT(proto, JSSLOT_PRIVATE, JSVAL_FALSE);
+    proto->fslots[JSSLOT_PRIVATE] = JSVAL_FALSE;
     return proto;
 }
 
 JSString *
 js_BooleanToString(JSContext *cx, JSBool b)
 {
     return ATOM_TO_STRING(cx->runtime->atomState.booleanAtoms[b ? 1 : 0]);
 }
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -590,17 +590,17 @@ js_watch_set(JSContext *cx, JSObject *ob
 
                 closure = (JSObject *) wp->closure;
                 clasp = OBJ_GET_CLASS(cx, closure);
                 if (clasp == &js_FunctionClass) {
                     fun = GET_FUNCTION_PRIVATE(cx, closure);
                     script = FUN_SCRIPT(fun);
                 } else if (clasp == &js_ScriptClass) {
                     fun = NULL;
-                    script = (JSScript *) JS_GetPrivate(cx, closure);
+                    script = (JSScript *) closure->getAssignedPrivate();
                 } else {
                     fun = NULL;
                     script = NULL;
                 }
 
                 slotsStart = nslots = 2;
                 injectFrame = JS_TRUE;
                 if (fun) {
@@ -1162,17 +1162,17 @@ JS_GetFrameFunction(JSContext *cx, JSSta
 
 JS_PUBLIC_API(JSObject *)
 JS_GetFrameFunctionObject(JSContext *cx, JSStackFrame *fp)
 {
     if (!fp->fun)
         return NULL;
 
     JS_ASSERT(HAS_FUNCTION_CLASS(fp->callee));
-    JS_ASSERT(OBJ_GET_PRIVATE(cx, fp->callee) == fp->fun);
+    JS_ASSERT(fp->callee->getAssignedPrivate() == fp->fun);
     return fp->callee;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_IsConstructorFrame(JSContext *cx, JSStackFrame *fp)
 {
     return (fp->flags & JSFRAME_CONSTRUCTING) != 0;
 }
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -337,17 +337,17 @@ InitExnPrivate(JSContext *cx, JSObject *
             if (fp->regs)
                 elem->ulineno = js_FramePCToLineNumber(cx, fp);
         }
         ++elem;
     }
     JS_ASSERT(priv->stackElems + stackDepth == elem);
     JS_ASSERT(GetStackTraceValueBuffer(priv) + valueCount == values);
 
-    STOBJ_SET_SLOT(exnObject, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(priv));
+    exnObject->setPrivate(priv);
 
     if (report) {
         /*
          * Construct a new copy of the error report struct. We can't use the
          * error report struct that was passed in, because it's allocated on
          * the stack, and also because it may point to transient data in the
          * JSTokenStream.
          */
@@ -356,29 +356,20 @@ InitExnPrivate(JSContext *cx, JSObject *
             /* The finalizer realeases priv since it is in the private slot. */
             return JS_FALSE;
         }
     }
 
     return JS_TRUE;
 }
 
-static JSExnPrivate *
+static inline JSExnPrivate *
 GetExnPrivate(JSContext *cx, JSObject *obj)
 {
-    jsval privateValue;
-    JSExnPrivate *priv;
-
-    JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_ErrorClass);
-    privateValue = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
-    if (JSVAL_IS_VOID(privateValue))
-        return NULL;
-    priv = (JSExnPrivate *)JSVAL_TO_PRIVATE(privateValue);
-    JS_ASSERT(priv);
-    return priv;
+    return (JSExnPrivate *) obj->getPrivate();
 }
 
 static void
 exn_trace(JSTracer *trc, JSObject *obj)
 {
     JSExnPrivate *priv;
     JSStackTraceElem *elem;
     size_t vcount, i;
@@ -715,17 +706,17 @@ Exception(JSContext *cx, JSObject *obj, 
         *rval = OBJECT_TO_JSVAL(obj);
     }
 
     /*
      * If it's a new object of class Exception, then null out the private
      * data so that the finalizer doesn't attempt to free it.
      */
     if (OBJ_GET_CLASS(cx, obj) == &js_ErrorClass)
-        STOBJ_SET_SLOT(obj, JSSLOT_PRIVATE, JSVAL_VOID);
+        obj->setPrivate(NULL);
 
     /* Set the 'message' property. */
     if (argc != 0) {
         message = js_ValueToString(cx, argv[0]);
         if (!message)
             return JS_FALSE;
         argv[0] = STRING_TO_JSVAL(message);
     } else {
@@ -1041,17 +1032,17 @@ js_InitExceptionClasses(JSContext *cx, J
             roots[0] = OBJECT_TO_JSVAL(proto);
         } else {
             // We cannot share the root for error_proto and other prototypes
             // as error_proto must be rooted until the function returns.
             roots[1] = OBJECT_TO_JSVAL(proto);
         }
 
         /* So exn_finalize knows whether to destroy private data. */
-        STOBJ_SET_SLOT(proto, JSSLOT_PRIVATE, JSVAL_VOID);
+        proto->setPrivate(NULL);
 
         /* Make a constructor function for the current name. */
         protoKey = GetExceptionProtoKey(i);
         atom = cx->runtime->atomState.classAtoms[protoKey];
         fun = js_DefineFunction(cx, obj, atom, Exception, 3, 0);
         if (!fun)
             return NULL;
         roots[2] = OBJECT_TO_JSVAL(FUN_OBJECT(fun));
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -270,17 +270,17 @@ js_GetArgsObject(JSContext *cx, JSStackF
     JSObject *parent, *global = fp->scopeChain;
     while ((parent = OBJ_GET_PARENT(cx, global)) != NULL)
         global = parent;
     argsobj = js_NewObject(cx, &js_ArgumentsClass, NULL, global, 0);
     if (!argsobj)
         return NULL;
 
     /* Link the new object to fp so it can get actual argument values. */
-    JS_SetPrivate(cx, argsobj, fp);
+    argsobj->setPrivate(fp);
     fp->argsobj = OBJECT_TO_JSVAL(argsobj);
     return argsobj;
 }
 
 static JSBool
 args_enumerate(JSContext *cx, JSObject *obj);
 
 JSBool
@@ -324,25 +324,25 @@ js_PutArgsObject(JSContext *cx, JSStackF
     ok &= js_SetProperty(cx, argsobj, ATOM_TO_JSID(rt->atomState.lengthAtom),
                          &rval);
 
     /*
      * Clear the private pointer to fp, which is about to go away (js_Invoke).
      * Do this last because the args_enumerate and js_GetProperty calls above
      * need to follow the private slot to find fp.
      */
-    ok &= JS_SetPrivate(cx, argsobj, NULL);
+    argsobj->setPrivate(NULL);
     fp->argsobj = NULL;
     return ok;
 }
 
 static JSBool
 args_delProperty(JSContext *cx, JSObject *obj, jsval idval, jsval *vp)
 {
-    JSStackFrame *fp = (JSStackFrame *) JS_GetPrivate(cx, obj);
+    JSStackFrame *fp = (JSStackFrame *) obj->getPrivate();
     if (!fp)
         return JS_TRUE;
     JS_ASSERT(fp->argsobj);
 
     if (JSVAL_IS_INT(idval)) {
         uintN arg = uintN(JSVAL_TO_INT(idval));
         if (arg < fp->argc && !MarkArgDeleted(cx, fp, arg))
             return false;
@@ -811,17 +811,17 @@ js_GetCallObject(JSContext *cx, JSStackF
     callobj = fp->callobj;
     if (callobj)
         return callobj;
 
 #ifdef DEBUG
     /* A call object should be a frame's outermost scope chain element.  */
     JSClass *classp = OBJ_GET_CLASS(cx, fp->scopeChain);
     if (classp == &js_WithClass || classp == &js_BlockClass || classp == &js_CallClass)
-        JS_ASSERT(OBJ_GET_PRIVATE(cx, fp->scopeChain) != fp);
+        JS_ASSERT(fp->scopeChain->getAssignedPrivate() != fp);
 #endif
 
     /*
      * Create the call object, using the frame's enclosing scope as its
      * parent, and link the call to its stack frame. For a named function
      * expression Call's parent points to an environment object holding
      * function's name.
      */
@@ -845,17 +845,17 @@ js_GetCallObject(JSContext *cx, JSStackF
     }
 
     callobj = js_NewObjectWithGivenProto(cx, &js_CallClass, NULL, fp->scopeChain);
     if (!callobj ||
         !js_EnsureReservedSlots(cx, callobj, fp->fun->countArgsAndVars())) {
         return NULL;
     }
 
-    JS_SetPrivate(cx, callobj, fp);
+    callobj->setPrivate(fp);
     JS_ASSERT(fp->fun == GET_FUNCTION_PRIVATE(cx, fp->callee));
     STOBJ_SET_SLOT(callobj, JSSLOT_CALLEE, OBJECT_TO_JSVAL(fp->callee));
     fp->callobj = callobj;
 
     /*
      * Push callobj on the top of the scope chain, and make it the
      * variables object.
      */
@@ -914,21 +914,21 @@ js_PutCallObject(JSContext *cx, JSStackF
         JS_UNLOCK_OBJ(cx, callobj);
     }
 
     /* Clear private pointers to fp, which is about to go away (js_Invoke). */
     if ((fun->flags & JSFUN_LAMBDA) && fun->atom) {
         JSObject *env = STOBJ_GET_PARENT(callobj);
 
         JS_ASSERT(STOBJ_GET_CLASS(env) == &js_DeclEnvClass);
-        JS_ASSERT(STOBJ_GET_PRIVATE(env) == fp);
-        JS_SetPrivate(cx, env, NULL);
+        JS_ASSERT(env->getAssignedPrivate() == fp);
+        env->setPrivate(NULL);
     }
 
-    JS_SetPrivate(cx, callobj, NULL);
+    callobj->setPrivate(NULL);
     fp->callobj = NULL;
     return ok;
 }
 
 static JSBool
 call_enumerate(JSContext *cx, JSObject *obj)
 {
     JSFunction *fun;
@@ -997,17 +997,17 @@ CallPropertyOp(JSContext *cx, JSObject *
     JSStackFrame *fp;
     uintN i;
     jsval *array;
 
     if (STOBJ_GET_CLASS(obj) != &js_CallClass)
         return JS_TRUE;
 
     fun = GetCallObjectFunction(obj);
-    fp = (JSStackFrame *) JS_GetPrivate(cx, obj);
+    fp = (JSStackFrame *) obj->getPrivate();
 
     if (kind == JSCPK_ARGUMENTS) {
         if (setter) {
             if (fp)
                 SET_OVERRIDE_BIT(fp, CALL_ARGUMENTS);
             STOBJ_SET_SLOT(obj, JSSLOT_CALL_ARGUMENTS, *vp);
         } else {
             if (fp && !TEST_OVERRIDE_BIT(fp, CALL_ARGUMENTS)) {
@@ -1211,20 +1211,18 @@ call_resolve(JSContext *cx, JSObject *ob
 
     /* Control flow reaches here only if id was not resolved. */
     return JS_TRUE;
 }
 
 static JSBool
 call_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
 {
-    JSStackFrame *fp;
-
     if (type == JSTYPE_FUNCTION) {
-        fp = (JSStackFrame *) JS_GetPrivate(cx, obj);
+        JSStackFrame *fp = (JSStackFrame *) obj->getPrivate();
         if (fp) {
             JS_ASSERT(fp->fun);
             *vp = OBJECT_TO_JSVAL(fp->callee);
         }
     }
     return JS_TRUE;
 }
 
@@ -1745,20 +1743,18 @@ static void
 TraceLocalNames(JSTracer *trc, JSFunction *fun);
 
 static void
 DestroyLocalNames(JSContext *cx, JSFunction *fun);
 
 static void
 fun_trace(JSTracer *trc, JSObject *obj)
 {
-    JSFunction *fun;
-
     /* A newborn function object may have a not yet initialized private slot. */
-    fun = (JSFunction *) JS_GetPrivate(trc->context, obj);
+    JSFunction *fun = (JSFunction *) obj->getPrivate();
     if (!fun)
         return;
 
     if (FUN_OBJECT(fun) != obj) {
         /* obj is cloned function object, trace the original. */
         JS_CALL_TRACER(trc, FUN_OBJECT(fun), JSTRACE_OBJECT, "private");
         return;
     }
@@ -1804,21 +1800,21 @@ JSFunction::countInterpretedReservedSlot
         nslots += JS_SCRIPT_REGEXPS(u.i.script)->length;
     return nslots;
 }
 
 static uint32
 fun_reserveSlots(JSContext *cx, JSObject *obj)
 {
     /*
-     * We use JS_GetPrivate and not GET_FUNCTION_PRIVATE because during
+     * We use getPrivate and not GET_FUNCTION_PRIVATE because during
      * js_InitFunctionClass invocation the function is called before the
      * private slot of the function object is set.
      */
-    JSFunction *fun = (JSFunction *) JS_GetPrivate(cx, obj);
+    JSFunction *fun = (JSFunction *) obj->getPrivate();
     return (fun && FUN_INTERPRETED(fun))
            ? fun->countInterpretedReservedSlots()
            : 0;
 }
 
 /*
  * Reserve two slots in all function objects for XPConnect.  Note that this
  * does not bloat every instance, only those on which reserved slots are set,
@@ -2137,19 +2133,19 @@ Function(JSContext *cx, JSObject *obj, u
     if (!JS_IsConstructing(cx)) {
         obj = js_NewObject(cx, &js_FunctionClass, NULL, NULL);
         if (!obj)
             return JS_FALSE;
         *rval = OBJECT_TO_JSVAL(obj);
     } else {
         /*
          * The constructor is called before the private slot is initialized so
-         * we must use JS_GetPrivate, not GET_FUNCTION_PRIVATE here.
+         * we must use getPrivate, not GET_FUNCTION_PRIVATE here.
          */
-        if (JS_GetPrivate(cx, obj))
+        if (obj->getPrivate())
             return JS_TRUE;
     }
 
     /*
      * NB: (new Function) is not lexically closed by its caller, it's just an
      * anonymous function in the top-level scope that its constructor inhabits.
      * Thus 'var x = 42; f = new Function("return x"); print(f())' prints 42,
      * and so would a call to f from another top-level's script or function.
@@ -2384,17 +2380,17 @@ js_NewFunction(JSContext *cx, JSObject *
     if (funobj) {
         JS_ASSERT(HAS_FUNCTION_CLASS(funobj));
         OBJ_SET_PARENT(cx, funobj, parent);
     } else {
         funobj = js_NewObject(cx, &js_FunctionClass, NULL, parent);
         if (!funobj)
             return NULL;
     }
-    JS_ASSERT(JSVAL_IS_VOID(funobj->fslots[JSSLOT_PRIVATE]));
+    JS_ASSERT(!funobj->getPrivate());
     fun = (JSFunction *) funobj;
 
     /* Initialize all function members. */
     fun->nargs = nargs;
     fun->flags = flags & (JSFUN_FLAGS_MASK | JSFUN_KINDMASK | JSFUN_TRACEABLE);
     if ((flags & JSFUN_KINDMASK) >= JSFUN_INTERPRETED) {
         JS_ASSERT(!native);
         JS_ASSERT(nargs == 0);
@@ -2423,31 +2419,31 @@ js_NewFunction(JSContext *cx, JSObject *
             fun->u.n.native = native;
             fun->u.n.trcinfo = NULL;
         }
         JS_ASSERT(fun->u.n.native);
     }
     fun->atom = atom;
 
     /* Set private to self to indicate non-cloned fully initialized function. */
-    FUN_OBJECT(fun)->fslots[JSSLOT_PRIVATE] = PRIVATE_TO_JSVAL(fun);
+    FUN_OBJECT(fun)->setPrivate(fun);
     return fun;
 }
 
 JSObject *
 js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent)
 {
     /*
      * The cloned function object does not need the extra JSFunction members
      * beyond JSObject as it points to fun via the private slot.
      */
     JSObject *clone = js_NewObject(cx, &js_FunctionClass, NULL, parent, sizeof(JSObject));
     if (!clone)
         return NULL;
-    clone->fslots[JSSLOT_PRIVATE] = PRIVATE_TO_JSVAL(fun);
+    clone->setPrivate(fun);
     return clone;
 }
 
 /*
  * Create a new flat closure, but don't initialize the imported upvar
  * values. The tracer calls this function and then initializes the upvar
  * slots on trace.
  */
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -213,17 +213,17 @@ extern JS_FRIEND_DATA(JSClass) js_Functi
     (!JSVAL_IS_PRIMITIVE(v) && HAS_FUNCTION_CLASS(JSVAL_TO_OBJECT(v)))
 
 /*
  * Macro to access the private slot of the function object after the slot is
  * initialized.
  */
 #define GET_FUNCTION_PRIVATE(cx, funobj)                                      \
     (JS_ASSERT(HAS_FUNCTION_CLASS(funobj)),                                   \
-     (JSFunction *) OBJ_GET_PRIVATE(cx, funobj))
+     (JSFunction *) (funobj)->getAssignedPrivate())
 
 extern JSObject *
 js_InitFunctionClass(JSContext *cx, JSObject *obj);
 
 extern JSObject *
 js_InitArgumentsClass(JSContext *cx, JSObject *obj);
 
 extern JSFunction *
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -717,17 +717,17 @@ js_GetScopeChain(JSContext *cx, JSStackF
      * make sure there's a call object at the current head of the scope chain,
      * if this frame is a call frame.
      *
      * Also, identify the innermost compiler-allocated block we needn't clone.
      */
     JSObject *limitBlock, *limitClone;
     if (fp->fun && !fp->callobj) {
         JS_ASSERT(OBJ_GET_CLASS(cx, fp->scopeChain) != &js_BlockClass ||
-                  OBJ_GET_PRIVATE(cx, fp->scopeChain) != fp);
+                  fp->scopeChain->getAssignedPrivate() != fp);
         if (!js_GetCallObject(cx, fp))
             return NULL;
 
         /* We know we must clone everything on blockChain. */
         limitBlock = limitClone = NULL;
     } else {
         /*
          * scopeChain includes all blocks whose static scope we're within that
@@ -807,17 +807,17 @@ js_GetScopeChain(JSContext *cx, JSStackF
 
 
     /*
      * If we found a limit block belonging to this frame, then we should have
      * found it in blockChain.
      */
     JS_ASSERT_IF(limitBlock &&
                  OBJ_GET_CLASS(cx, limitBlock) == &js_BlockClass &&
-                 OBJ_GET_PRIVATE(cx, limitClone) == fp,
+                 limitClone->getAssignedPrivate() == fp,
                  sharedBlock);
 
     /* Place our newly cloned blocks at the head of the scope chain.  */
     fp->scopeChain = innermostNewChild;
     return fp->scopeChain;
 }
 
 JSBool
@@ -826,17 +826,17 @@ js_GetPrimitiveThis(JSContext *cx, jsval
     jsval v;
     JSObject *obj;
 
     v = vp[1];
     if (JSVAL_IS_OBJECT(v)) {
         obj = JS_THIS_OBJECT(cx, vp);
         if (!JS_InstanceOf(cx, obj, clasp, vp + 2))
             return JS_FALSE;
-        v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
+        v = obj->fslots[JSSLOT_PRIVATE];
     }
     *thisvp = v;
     return JS_TRUE;
 }
 
 /*
  * ECMA requires "the global object", but in embeddings such as the browser,
  * which have multiple top-level objects (windows, frames, etc. in the DOM),
@@ -1973,30 +1973,30 @@ js_EnterWith(JSContext *cx, jsint stackI
 
 JS_STATIC_INTERPRET JS_REQUIRES_STACK void
 js_LeaveWith(JSContext *cx)
 {
     JSObject *withobj;
 
     withobj = cx->fp->scopeChain;
     JS_ASSERT(OBJ_GET_CLASS(cx, withobj) == &js_WithClass);
-    JS_ASSERT(OBJ_GET_PRIVATE(cx, withobj) == cx->fp);
+    JS_ASSERT(withobj->getAssignedPrivate() == cx->fp);
     JS_ASSERT(OBJ_BLOCK_DEPTH(cx, withobj) >= 0);
     cx->fp->scopeChain = OBJ_GET_PARENT(cx, withobj);
-    JS_SetPrivate(cx, withobj, NULL);
+    withobj->setPrivate(NULL);
 }
 
 JS_REQUIRES_STACK JSClass *
 js_IsActiveWithOrBlock(JSContext *cx, JSObject *obj, int stackDepth)
 {
     JSClass *clasp;
 
     clasp = OBJ_GET_CLASS(cx, obj);
     if ((clasp == &js_WithClass || clasp == &js_BlockClass) &&
-        OBJ_GET_PRIVATE(cx, obj) == cx->fp &&
+        obj->getAssignedPrivate() == cx->fp &&
         OBJ_BLOCK_DEPTH(cx, obj) >= stackDepth) {
         return clasp;
     }
     return NULL;
 }
 
 /*
  * Unwind block and scope chains to match the given depth. The function sets
@@ -3156,17 +3156,17 @@ js_Interpret(JSContext *cx)
             obj = fp->blockChain;
             JS_ASSERT_IF(obj,
                          OBJ_BLOCK_DEPTH(cx, obj) + OBJ_BLOCK_COUNT(cx, obj)
                          <= (size_t) (regs.sp - StackBase(fp)));
             for (obj = fp->scopeChain; obj; obj = OBJ_GET_PARENT(cx, obj)) {
                 clasp = OBJ_GET_CLASS(cx, obj);
                 if (clasp != &js_BlockClass && clasp != &js_WithClass)
                     continue;
-                if (OBJ_GET_PRIVATE(cx, obj) != fp)
+                if (obj->getAssignedPrivate() != fp)
                     break;
                 JS_ASSERT(StackBase(fp) + OBJ_BLOCK_DEPTH(cx, obj)
                                      + ((clasp == &js_BlockClass)
                                         ? OBJ_BLOCK_COUNT(cx, obj)
                                         : 1)
                           <= regs.sp);
             }
 #endif
@@ -7029,17 +7029,17 @@ js_Interpret(JSContext *cx)
              * ancestors of the block we're entering now; anything
              * else we should have popped off fp->scopeChain when we
              * left its static scope.
              */
             obj2 = fp->scopeChain;
             while ((clasp = OBJ_GET_CLASS(cx, obj2)) == &js_WithClass)
                 obj2 = OBJ_GET_PARENT(cx, obj2);
             if (clasp == &js_BlockClass &&
-                OBJ_GET_PRIVATE(cx, obj2) == fp) {
+                obj2->getAssignedPrivate() == fp) {
                 JSObject *youngestProto = OBJ_GET_PROTO(cx, obj2);
                 JS_ASSERT(!OBJ_IS_CLONED_BLOCK(youngestProto));
                 parent = obj;
                 while ((parent = OBJ_GET_PARENT(cx, parent)) != youngestProto)
                     JS_ASSERT(parent);
             }
 #endif
 
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -67,19 +67,17 @@
 #include "jsscript.h"
 #include "jsstaticcheck.h"
 #include "jstracer.h"
 
 #if JS_HAS_XML_SUPPORT
 #include "jsxml.h"
 #endif
 
-#if JSSLOT_ITER_FLAGS >= JS_INITIAL_NSLOTS
-#error JS_INITIAL_NSLOTS must be greater than JSSLOT_ITER_FLAGS.
-#endif
+JS_STATIC_ASSERT(JSSLOT_ITER_FLAGS < JS_INITIAL_NSLOTS);
 
 #if JS_HAS_GENERATORS
 
 static JS_REQUIRES_STACK JSBool
 CloseGenerator(JSContext *cx, JSObject *genobj);
 
 #endif
 
@@ -634,36 +632,34 @@ JSClass js_StopIterationClass = {
     NULL,             NULL
 };
 
 #if JS_HAS_GENERATORS
 
 static void
 generator_finalize(JSContext *cx, JSObject *obj)
 {
-    JSGenerator *gen;
+    JSGenerator *gen = (JSGenerator *) obj->getPrivate();
+    if (!gen)
+        return;
 
-    gen = (JSGenerator *) JS_GetPrivate(cx, obj);
-    if (gen) {
-        /*
-         * gen can be open on shutdown when close hooks are ignored or when
-         * the embedding cancels scheduled close hooks.
-         */
-        JS_ASSERT(gen->state == JSGEN_NEWBORN || gen->state == JSGEN_CLOSED ||
-                  gen->state == JSGEN_OPEN);
-        cx->free(gen);
-    }
+    /*
+     * gen is open when a script has not called its close method while
+     * explicitly manipulating it.
+     */
+    JS_ASSERT(gen->state == JSGEN_NEWBORN ||
+              gen->state == JSGEN_CLOSED ||
+              gen->state == JSGEN_OPEN);
+    cx->free(gen);
 }
 
 static void
 generator_trace(JSTracer *trc, JSObject *obj)
 {
-    JSGenerator *gen;
-
-    gen = (JSGenerator *) JS_GetPrivate(trc->context, obj);
+    JSGenerator *gen = (JSGenerator *) obj->getPrivate();
     if (!gen)
         return;
 
     /*
      * js_TraceStackFrame does not recursively trace the down-linked frame
      * chain, so we insist that gen->frame has no parent to trace when the
      * generator is not running.
      */
@@ -699,43 +695,42 @@ JS_FRIEND_DATA(JSClass) js_GeneratorClas
 JSObject *
 js_NewGenerator(JSContext *cx, JSStackFrame *fp)
 {
     JSObject *obj;
     uintN argc, nargs, nslots;
     JSGenerator *gen;
     jsval *slots;
 
-    /* After the following return, failing control flow must goto bad. */
     obj = js_NewObject(cx, &js_GeneratorClass, NULL, NULL);
     if (!obj)
         return NULL;
 
     /* Load and compute stack slot counts. */
     argc = fp->argc;
     nargs = JS_MAX(argc, fp->fun->nargs);
     nslots = 2 + nargs + fp->script->nslots;
 
     /* Allocate obj's private data struct. */
     gen = (JSGenerator *)
         cx->malloc(sizeof(JSGenerator) + (nslots - 1) * sizeof(jsval));
     if (!gen)
-        goto bad;
+        return NULL;
 
     gen->obj = obj;
 
     /* Steal away objects reflecting fp and point them at gen->frame. */
     gen->frame.callobj = fp->callobj;
     if (fp->callobj) {
-        JS_SetPrivate(cx, fp->callobj, &gen->frame);
+        fp->callobj->setPrivate(&gen->frame);
         fp->callobj = NULL;
     }
     gen->frame.argsobj = fp->argsobj;
     if (fp->argsobj) {
-        JS_SetPrivate(cx, JSVAL_TO_OBJECT(fp->argsobj), &gen->frame);
+        JSVAL_TO_OBJECT(fp->argsobj)->setPrivate(&gen->frame);
         fp->argsobj = NULL;
     }
 
     /* These two references can be shared with fp until it goes away. */
     gen->frame.varobj = fp->varobj;
     gen->frame.thisp = fp->thisp;
 
     /* Copy call-invariant script and function references. */
@@ -777,25 +772,18 @@ js_NewGenerator(JSContext *cx, JSStackFr
     gen->frame.xmlNamespace = NULL;
     /* JSOP_GENERATOR appears in the prologue, outside all blocks.  */
     JS_ASSERT(!fp->blockChain);
     gen->frame.blockChain = NULL;
 
     /* Note that gen is newborn. */
     gen->state = JSGEN_NEWBORN;
 
-    if (!JS_SetPrivate(cx, obj, gen)) {
-        cx->free(gen);
-        goto bad;
-    }
+    obj->setPrivate(gen);
     return obj;
-
-  bad:
-    cx->weakRoots.newborn[GCX_OBJECT] = NULL;
-    return NULL;
 }
 
 typedef enum JSGeneratorOp {
     JSGENOP_NEXT,
     JSGENOP_SEND,
     JSGENOP_THROW,
     JSGENOP_CLOSE
 } JSGeneratorOp;
@@ -892,20 +880,19 @@ SendToGenerator(JSContext *cx, JSGenerat
      * Propagate the condition to the caller.
      */
     return JS_FALSE;
 }
 
 static JS_REQUIRES_STACK JSBool
 CloseGenerator(JSContext *cx, JSObject *obj)
 {
-    JSGenerator *gen;
+    JS_ASSERT(STOBJ_GET_CLASS(obj) == &js_GeneratorClass);
 
-    JS_ASSERT(STOBJ_GET_CLASS(obj) == &js_GeneratorClass);
-    gen = (JSGenerator *) JS_GetPrivate(cx, obj);
+    JSGenerator *gen = (JSGenerator *) obj->getPrivate();
     if (!gen) {
         /* Generator prototype object. */
         return JS_TRUE;
     }
 
     if (gen->state == JSGEN_CLOSED)
         return JS_TRUE;
 
@@ -914,27 +901,26 @@ CloseGenerator(JSContext *cx, JSObject *
 
 /*
  * Common subroutine of generator_(next|send|throw|close) methods.
  */
 static JSBool
 generator_op(JSContext *cx, JSGeneratorOp op, jsval *vp, uintN argc)
 {
     JSObject *obj;
-    JSGenerator *gen;
     jsval arg;
 
     js_LeaveTrace(cx);
 
     obj = JS_THIS_OBJECT(cx, vp);
     if (!JS_InstanceOf(cx, obj, &js_GeneratorClass, vp + 2))
         return JS_FALSE;
 
-    gen = (JSGenerator *) JS_GetPrivate(cx, obj);
-    if (gen == NULL) {
+    JSGenerator *gen = (JSGenerator *) obj->getPrivate();
+    if (!gen) {
         /* This happens when obj is the generator prototype. See bug 352885. */
         goto closed_generator;
     }
 
     if (gen->state == JSGEN_NEWBORN) {
         switch (op) {
           case JSGENOP_NEXT:
           case JSGENOP_THROW:
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -235,17 +235,17 @@ static JSFunctionSpec number_functions[]
     JS_FN(js_isFinite_str,      num_isFinite,        1,0),
     JS_TN(js_parseFloat_str,    num_parseFloat,      1,0, num_parseFloat_trcinfo),
     JS_TN(js_parseInt_str,      num_parseInt,        2,0, num_parseInt_trcinfo),
     JS_FS_END
 };
 
 JSClass js_NumberClass = {
     js_Number_str,
-    JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Number),
+    JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_HAS_CACHED_PROTO(JSProto_Number),
     JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,
     JS_EnumerateStub, JS_ResolveStub,   JS_ConvertStub,   NULL,
     JSCLASS_NO_OPTIONAL_MEMBERS
 };
 
 static JSBool
 Number(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 {
@@ -262,22 +262,21 @@ Number(JSContext *cx, JSObject *obj, uin
         } else {
             if (!js_NewNumberInRootedValue(cx, d, &argv[0]))
                 return JS_FALSE;
             v = argv[0];
         }
     } else {
         v = JSVAL_ZERO;
     }
-    if (!JS_IsConstructing(cx)) {
+    if (!JS_IsConstructing(cx))
         *rval = v;
-        return JS_TRUE;
-    }
-    STOBJ_SET_SLOT(obj, JSSLOT_PRIVATE, v);
-    return JS_TRUE;
+    else
+        obj->fslots[JSSLOT_PRIVATE] = v;
+    return true;
 }
 
 #if JS_HAS_TOSOURCE
 static JSBool
 num_toSource(JSContext *cx, uintN argc, jsval *vp)
 {
     jsval v;
     jsdouble d;
@@ -509,17 +508,17 @@ num_valueOf(JSContext *cx, uintN argc, j
     v = vp[1];
     if (JSVAL_IS_NUMBER(v)) {
         *vp = v;
         return JS_TRUE;
     }
     obj = JS_THIS_OBJECT(cx, vp);
     if (!JS_InstanceOf(cx, obj, &js_NumberClass, vp + 2))
         return JS_FALSE;
-    *vp = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
+    *vp = obj->fslots[JSSLOT_PRIVATE];
     return JS_TRUE;
 }
 
 
 #define MAX_PRECISION 100
 
 static JSBool
 num_to(JSContext *cx, JSDToStrMode zeroArgMode, JSDToStrMode oneArgMode,
@@ -756,17 +755,17 @@ js_InitNumberClass(JSContext *cx, JSObje
 
     if (!JS_DefineFunctions(cx, obj, number_functions))
         return NULL;
 
     proto = JS_InitClass(cx, obj, NULL, &js_NumberClass, Number, 1,
                          NULL, number_methods, NULL, NULL);
     if (!proto || !(ctor = JS_GetConstructor(cx, proto)))
         return NULL;
-    STOBJ_SET_SLOT(proto, JSSLOT_PRIVATE, JSVAL_ZERO);
+    proto->fslots[JSSLOT_PRIVATE] = JSVAL_ZERO;
     if (!JS_DefineConstDoubles(cx, ctor, number_constants))
         return NULL;
 
     /* ECMA 15.1.1.1 */
     rt = cx->runtime;
     if (!JS_DefineProperty(cx, obj, js_NaN_str, DOUBLE_TO_JSVAL(rt->jsNaN),
                            NULL, NULL, JSPROP_PERMANENT)) {
         return NULL;
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -1508,17 +1508,17 @@ obj_eval(JSContext *cx, JSObject *obj, u
 #endif
 
 out:
 #if JS_HAS_EVAL_THIS_SCOPE
     /* Restore OBJ_GET_PARENT(scopeobj) not callerScopeChain in case of Call. */
     if (setCallerScopeChain) {
         caller->scopeChain = callerScopeChain;
         JS_ASSERT(OBJ_GET_CLASS(cx, setCallerScopeChain) == &js_WithClass);
-        JS_SetPrivate(cx, setCallerScopeChain, NULL);
+        setCallerScopeChain->setPrivate(NULL);
     }
     if (setCallerVarObj)
         caller->varobj = callerVarObj;
 #endif
     return ok;
 }
 
 #if JS_HAS_OBJ_WATCHPOINT
@@ -2513,17 +2513,17 @@ JSClass js_WithClass = {
 JS_REQUIRES_STACK JSObject *
 js_NewWithObject(JSContext *cx, JSObject *proto, JSObject *parent, jsint depth)
 {
     JSObject *obj;
 
     obj = js_NewObject(cx, &js_WithClass, proto, parent);
     if (!obj)
         return NULL;
-    STOBJ_SET_SLOT(obj, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(cx->fp));
+    obj->setPrivate(cx->fp);
     OBJ_SET_BLOCK_DEPTH(cx, obj, depth);
     return obj;
 }
 
 JSObject *
 js_NewBlockObject(JSContext *cx)
 {
     /*
@@ -2547,17 +2547,17 @@ js_CloneBlockObject(JSContext *cx, JSObj
 
     JSScope *scope = OBJ_SCOPE(proto);
     scope->hold();
     clone->map = &scope->map;
 
     clone->classword = jsuword(&js_BlockClass);
     clone->fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto);
     clone->fslots[JSSLOT_PARENT] = JSVAL_NULL;  // caller's responsibility
-    clone->fslots[JSSLOT_PRIVATE] = PRIVATE_TO_JSVAL(fp);
+    clone->setPrivate(fp);
     clone->fslots[JSSLOT_BLOCK_DEPTH] = proto->fslots[JSSLOT_BLOCK_DEPTH];
     JS_ASSERT(scope->freeslot == JSSLOT_BLOCK_DEPTH + 1);
     for (uint32 i = JSSLOT_BLOCK_DEPTH + 1; i < JS_INITIAL_NSLOTS; ++i)
         clone->fslots[i] = JSVAL_VOID;
     clone->dslots = NULL;
     JS_ASSERT(OBJ_IS_CLONED_BLOCK(clone));
     return clone;
 }
@@ -2570,17 +2570,17 @@ js_PutBlockObject(JSContext *cx, JSBool 
     uintN depth, count;
 
     /* Blocks have one fixed slot available for the first local.*/
     JS_STATIC_ASSERT(JS_INITIAL_NSLOTS == JSSLOT_BLOCK_DEPTH + 2);
 
     fp = cx->fp;
     obj = fp->scopeChain;
     JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_BlockClass);
-    JS_ASSERT(OBJ_GET_PRIVATE(cx, obj) == cx->fp);
+    JS_ASSERT(obj->getAssignedPrivate() == cx->fp);
     JS_ASSERT(OBJ_IS_CLONED_BLOCK(obj));
 
     /*
      * Block objects should never be exposed to scripts. Thus the clone should
      * not own the property map and rather always share it with the prototype
      * object. This allows us to skip updating OBJ_SCOPE(obj)->freeslot after
      * we copy the stack slots into reserved slots.
      */
@@ -2606,58 +2606,52 @@ js_PutBlockObject(JSContext *cx, JSBool 
         if (!AllocSlots(cx, obj, JS_INITIAL_NSLOTS + count))
             normalUnwind = JS_FALSE;
         else
             memcpy(obj->dslots, fp->slots + depth + 1, count * sizeof(jsval));
         JS_UNLOCK_OBJ(cx, obj);
     }
 
     /* We must clear the private slot even with errors. */
-    JS_SetPrivate(cx, obj, NULL);
+    obj->setPrivate(NULL);
     fp->scopeChain = OBJ_GET_PARENT(cx, obj);
     return normalUnwind;
 }
 
 static JSBool
 block_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
 {
-    uintN index;
-    JSStackFrame *fp;
-
     JS_ASSERT(JS_InstanceOf(cx, obj, &js_BlockClass, NULL));
     JS_ASSERT(OBJ_IS_CLONED_BLOCK(obj));
     if (!JSVAL_IS_INT(id))
         return JS_TRUE;
 
-    index = (uint16) JSVAL_TO_INT(id);
-    fp = (JSStackFrame *) JS_GetPrivate(cx, obj);
+    uintN index = (uint16) JSVAL_TO_INT(id);
+    JSStackFrame *fp = (JSStackFrame *) obj->getPrivate();
     if (fp) {
         index += fp->script->nfixed + OBJ_BLOCK_DEPTH(cx, obj);
         JS_ASSERT(index < fp->script->nslots);
         *vp = fp->slots[index];
         return JS_TRUE;
     }
 
     /* Reserve slots start with the first slot after the private. */
     index += JSSLOT_BLOCK_DEPTH - JSSLOT_PRIVATE;
     return JS_GetReservedSlot(cx, obj, index, vp);
 }
 
 static JSBool
 block_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
 {
-    uintN index;
-    JSStackFrame *fp;
-
     JS_ASSERT(JS_InstanceOf(cx, obj, &js_BlockClass, NULL));
     if (!JSVAL_IS_INT(id))
         return JS_TRUE;
 
-    index = (uint16) JSVAL_TO_INT(id);
-    fp = (JSStackFrame *) JS_GetPrivate(cx, obj);
+    uintN index = (uint16) JSVAL_TO_INT(id);
+    JSStackFrame *fp = (JSStackFrame *) obj->getPrivate();
     if (fp) {
         index += fp->script->nfixed + OBJ_BLOCK_DEPTH(cx, obj);
         JS_ASSERT(index < fp->script->nslots);
         fp->slots[index] = *vp;
         return JS_TRUE;
     }
 
     /* Reserve slots start with the first slot after the private. */
@@ -3371,17 +3365,17 @@ js_ConstructObject(JSContext *cx, JSClas
      * error.  If the given class has both the JSCLASS_HAS_PRIVATE and the
      * JSCLASS_CONSTRUCT_PROTOTYPE flags, and the instance does not have its
      * private data set at this point, then the constructor was replaced and
      * we should throw a type error.
      */
     if (OBJ_GET_CLASS(cx, obj) != clasp ||
         (!(~clasp->flags & (JSCLASS_HAS_PRIVATE |
                             JSCLASS_CONSTRUCT_PROTOTYPE)) &&
-         !JS_GetPrivate(cx, obj))) {
+         !obj->getPrivate())) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                              JSMSG_WRONG_CONSTRUCTOR, clasp->name);
         goto bad;
     }
 
 out:
     JS_POP_TEMP_ROOT(cx, &tvr);
     JS_POP_TEMP_ROOT(cx, &argtvr);
@@ -5475,17 +5469,17 @@ js_PrimitiveToObject(JSContext *cx, jsva
     };
 
     JS_ASSERT(!JSVAL_IS_OBJECT(*vp));
     JS_ASSERT(!JSVAL_IS_VOID(*vp));
     clasp = PrimitiveClasses[JSVAL_TAG(*vp) - 1];
     obj = js_NewObject(cx, clasp, NULL, NULL);
     if (!obj)
         return JS_FALSE;
-    STOBJ_SET_SLOT(obj, JSSLOT_PRIVATE, *vp);
+    obj->fslots[JSSLOT_PRIVATE] = *vp;
     *vp = OBJECT_TO_JSVAL(obj);
     return JS_TRUE;
 }
 
 JSBool
 js_ValueToObject(JSContext *cx, jsval v, JSObject **objp)
 {
     JSObject *obj;
@@ -6002,17 +5996,17 @@ dumpValue(jsval val)
 {
     if (JSVAL_IS_NULL(val)) {
         fprintf(stderr, "null");
     } else if (JSVAL_IS_VOID(val)) {
         fprintf(stderr, "undefined");
     } else if (JSVAL_IS_OBJECT(val) &&
                HAS_FUNCTION_CLASS(JSVAL_TO_OBJECT(val))) {
         JSObject *funobj = JSVAL_TO_OBJECT(val);
-        JSFunction *fun = (JSFunction *) STOBJ_GET_PRIVATE(funobj);
+        JSFunction *fun = GET_FUNCTION_PRIVATE(cx, funobj);
         fprintf(stderr, "<%s %s at %p (JSFunction at %p)>",
                 fun->atom ? "function" : "unnamed",
                 fun->atom ? JS_GetStringBytes(ATOM_TO_STRING(fun->atom)) : "function",
                 (void *) funobj,
                 (void *) fun);
     } else if (JSVAL_IS_OBJECT(val)) {
         JSObject *obj = JSVAL_TO_OBJECT(val);
         JSClass *cls = STOBJ_GET_CLASS(obj);
@@ -6115,36 +6109,38 @@ js_DumpObject(JSObject *obj)
             if (!scope->hadMiddleDelete() || scope->has(sprop))
                 dumpScopeProp(sprop);
         }
     } else {
         if (!OBJ_IS_NATIVE(obj))
             fprintf(stderr, "not native\n");
     }
 
+    fprintf(stderr, "proto ");
+    dumpValue(OBJECT_TO_JSVAL(STOBJ_GET_PROTO(obj)));
+    fputc('\n', stderr);
+
+    fprintf(stderr, "parent ");
+    dumpValue(OBJECT_TO_JSVAL(STOBJ_GET_PARENT(obj)));
+    fputc('\n', stderr);
+
+    i = JSSLOT_PRIVATE;
+    if (clasp->flags & JSCLASS_HAS_PRIVATE) {
+        i = JSSLOT_PRIVATE + 1;
+        fprintf(stderr, "private %p\n", obj->getPrivate());
+    }
+
     fprintf(stderr, "slots:\n");
-    reservedEnd = JSSLOT_PRIVATE;
-    if (clasp->flags & JSCLASS_HAS_PRIVATE)
-        reservedEnd++;
-    reservedEnd += JSCLASS_RESERVED_SLOTS(clasp);
+    reservedEnd = i + JSCLASS_RESERVED_SLOTS(clasp);
     slots = (OBJ_IS_NATIVE(obj) && !sharesScope)
             ? OBJ_SCOPE(obj)->freeslot
             : STOBJ_NSLOTS(obj);
-    for (i = 0; i < slots; i++) {
+    for (; i < slots; i++) {
         fprintf(stderr, " %3d ", i);
-        if (i == JSSLOT_PRIVATE && (clasp->flags & JSCLASS_HAS_PRIVATE)) {
-            fprintf(stderr, "(private) = %p\n",
-                    JSVAL_TO_PRIVATE(STOBJ_GET_SLOT(obj, i)));
-            continue;
-        }
-        if (i == JSSLOT_PROTO)
-            fprintf(stderr, "(proto) ");
-        else if (i == JSSLOT_PARENT)
-            fprintf(stderr, "(parent) ");
-        else if (i < reservedEnd)
+        if (i < reservedEnd)
             fprintf(stderr, "(reserved) ");
         fprintf(stderr, "= ");
         dumpValue(STOBJ_GET_SLOT(obj, i));
         fputc('\n', stderr);
     }
     fputc('\n', stderr);
 }
 
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -151,17 +151,23 @@ struct JSObjectMap {
         JSClass *clasp_ = OBJ_GET_CLASS(cx, obj);                             \
         if (clasp_->flags & JSCLASS_IS_EXTENDED) {                            \
             JSExtendedClass *xclasp_ = (JSExtendedClass*)clasp_;              \
             if (xclasp_->outerObject)                                         \
                 obj = xclasp_->outerObject(cx, obj);                          \
         }                                                                     \
     JS_END_MACRO
 
-#define JS_INITIAL_NSLOTS   5
+const uint32 JS_INITIAL_NSLOTS = 5;
+
+const uint32 JSSLOT_PROTO   = 0;
+const uint32 JSSLOT_PARENT  = 1;
+const uint32 JSSLOT_PRIVATE = 2;
+
+const uint32 JSSLOT_CLASS_MASK_BITS = 3;
 
 /*
  * JSObject struct, with members sized to fit in 32 bytes on 32-bit targets,
  * 64 bytes on 64-bit systems. The JSFunction struct is an extension of this
  * struct allocated from a larger GC size-class.
  *
  * The classword member stores the JSClass pointer for this object, with the
  * least two bits encoding whether this object is a "delegate" or a "system"
@@ -189,21 +195,51 @@ struct JSObjectMap {
  * of jsvals for reserved and dynamic slots. If dslots is not null, dslots[-1]
  * records the number of available slots.
  */
 struct JSObject {
     JSObjectMap *map;                       /* propery map, see jsscope.h */
     jsuword     classword;                  /* classword, see above */
     jsval       fslots[JS_INITIAL_NSLOTS];  /* small number of fixed slots */
     jsval       *dslots;                    /* dynamically allocated slots */
+
+    JSClass *getClass() const {
+        return (JSClass *) (classword & ~JSSLOT_CLASS_MASK_BITS);
+    }
+
+    /*
+     * Get private value previously assigned with setPrivate.
+     */
+    void *getAssignedPrivate() const {
+        JS_ASSERT(getClass()->flags & JSCLASS_HAS_PRIVATE);
+
+        jsval v = fslots[JSSLOT_PRIVATE];
+        JS_ASSERT(JSVAL_IS_INT(v));
+        return JSVAL_TO_PRIVATE(v);
+    }
+
+    /*
+     * Get private value or null if the value has not yet been assigned.
+     */
+    void *getPrivate() const {
+        JS_ASSERT(getClass()->flags & JSCLASS_HAS_PRIVATE);
+
+        jsval v = fslots[JSSLOT_PRIVATE];
+        if (JSVAL_IS_INT(v))
+            return JSVAL_TO_PRIVATE(v);
+        JS_ASSERT(JSVAL_IS_VOID(v));
+        return NULL;
+    }
+
+    void setPrivate(void *data) {
+        JS_ASSERT(getClass()->flags & JSCLASS_HAS_PRIVATE);
+        fslots[JSSLOT_PRIVATE] = PRIVATE_TO_JSVAL(data);
+    }
 };
 
-#define JSSLOT_PROTO        0
-#define JSSLOT_PARENT       1
-#define JSSLOT_PRIVATE      2
 #define JSSLOT_START(clasp) (((clasp)->flags & JSCLASS_HAS_PRIVATE)           \
                              ? JSSLOT_PRIVATE + 1                             \
                              : JSSLOT_PARENT + 1)
 
 #define JSSLOT_FREE(clasp)  (JSSLOT_START(clasp)                              \
                              + JSCLASS_RESERVED_SLOTS(clasp))
 
 /*
@@ -254,30 +290,26 @@ struct JSObject {
  * flags in the two least significant bits. We do *not* synchronize updates of
  * obj->classword -- API clients must take care.
  */
 #define JSSLOT_CLASS_MASK_BITS 3
 
 JS_ALWAYS_INLINE JSClass*
 STOBJ_GET_CLASS(const JSObject* obj)
 {
-    return (JSClass *) (obj->classword & ~JSSLOT_CLASS_MASK_BITS);
+    return obj->getClass();
 }
 
 #define STOBJ_IS_DELEGATE(obj)  (((obj)->classword & 1) != 0)
 #define STOBJ_SET_DELEGATE(obj) ((obj)->classword |= 1)
 #define STOBJ_NULLSAFE_SET_DELEGATE(obj)                                      \
     (!(obj) || STOBJ_SET_DELEGATE((JSObject*)obj))
 #define STOBJ_IS_SYSTEM(obj)    (((obj)->classword & 2) != 0)
 #define STOBJ_SET_SYSTEM(obj)   ((obj)->classword |= 2)
 
-#define STOBJ_GET_PRIVATE(obj)                                                \
-    (JS_ASSERT(JSVAL_IS_INT(STOBJ_GET_SLOT(obj, JSSLOT_PRIVATE))),            \
-     JSVAL_TO_PRIVATE(STOBJ_GET_SLOT(obj, JSSLOT_PRIVATE)))
-
 #define OBJ_CHECK_SLOT(obj,slot)                                              \
     JS_ASSERT_IF(OBJ_IS_NATIVE(obj), slot < OBJ_SCOPE(obj)->freeslot)
 
 #define LOCKED_OBJ_GET_SLOT(obj,slot)                                         \
     (OBJ_CHECK_SLOT(obj, slot), STOBJ_GET_SLOT(obj, slot))
 #define LOCKED_OBJ_SET_SLOT(obj,slot,value)                                   \
     (OBJ_CHECK_SLOT(obj, slot), STOBJ_SET_SLOT(obj, slot, value))
 
@@ -324,19 +356,16 @@ STOBJ_GET_CLASS(const JSObject* obj)
 #define LOCKED_OBJ_GET_PARENT(obj) \
     (OBJ_CHECK_SLOT(obj, JSSLOT_PARENT), STOBJ_GET_PARENT(obj))
 #define LOCKED_OBJ_SET_PARENT(obj,parent) \
     (OBJ_CHECK_SLOT(obj, JSSLOT_PARENT), STOBJ_SET_PARENT(obj, parent))
 
 #define LOCKED_OBJ_GET_CLASS(obj) \
     STOBJ_GET_CLASS(obj)
 
-#define LOCKED_OBJ_GET_PRIVATE(obj) \
-    (OBJ_CHECK_SLOT(obj, JSSLOT_PRIVATE), STOBJ_GET_PRIVATE(obj))
-
 #ifdef JS_THREADSAFE
 
 /* Thread-safe functions and wrapper macros for accessing slots in obj. */
 #define OBJ_GET_SLOT(cx,obj,slot)                                             \
     (OBJ_CHECK_SLOT(obj, slot),                                               \
      (OBJ_IS_NATIVE(obj) && OBJ_SCOPE(obj)->title.ownercx == cx)              \
      ? LOCKED_OBJ_GET_SLOT(obj, slot)                                         \
      : js_GetSlotThreadSafe(cx, obj, slot))
@@ -387,17 +416,16 @@ STOBJ_GET_CLASS(const JSObject* obj)
 #define OBJ_SET_PARENT(cx,obj,parent)   STOBJ_SET_PARENT(obj, parent)
 #define OBJ_CLEAR_PARENT(cx,obj)        STOBJ_CLEAR_PARENT(obj)
 
 /*
  * Class is invariant and comes from the fixed clasp member. Thus no locking
  * is necessary to read it. Same for the private slot.
  */
 #define OBJ_GET_CLASS(cx,obj)           STOBJ_GET_CLASS(obj)
-#define OBJ_GET_PRIVATE(cx,obj)         STOBJ_GET_PRIVATE(obj)
 
 /*
  * Test whether the object is native. FIXME bug 492938: consider how it would
  * affect the performance to do just the !ops->objectMap check.
  */
 #define OPS_IS_NATIVE(ops)                                                    \
     JS_LIKELY((ops) == &js_ObjectOps || !(ops)->objectMap)
 
@@ -440,17 +468,17 @@ OBJ_IS_CLONED_BLOCK(JSObject *obj)
     STOBJ_SET_SLOT(obj, JSSLOT_BLOCK_DEPTH, INT_TO_JSVAL(depth))
 
 /*
  * To make sure this slot is well-defined, always call js_NewWithObject to
  * create a With object, don't call js_NewObject directly.  When creating a
  * With object that does not correspond to a stack slot, pass -1 for depth.
  *
  * When popping the stack across this object's "with" statement, client code
- * must call JS_SetPrivate(cx, withobj, NULL).
+ * must call withobj->setPrivate(NULL).
  */
 extern JS_REQUIRES_STACK JSObject *
 js_NewWithObject(JSContext *cx, JSObject *proto, JSObject *parent, jsint depth);
 
 /*
  * Create a new block scope object not linked to any proto or parent object.
  * Blocks are created by the compiler to reify let blocks and comprehensions.
  * Only when dynamic scope is captured do they need to be cloned and spliced
--- a/js/src/jsregexp.cpp
+++ b/js/src/jsregexp.cpp
@@ -4972,17 +4972,17 @@ regexp_getProperty(JSContext *cx, JSObje
         if (!obj)
             return JS_TRUE;
     }
     slot = JSVAL_TO_INT(id);
     if (slot == REGEXP_LAST_INDEX)
         return JS_GetReservedSlot(cx, obj, 0, vp);
 
     JS_LOCK_OBJ(cx, obj);
-    re = (JSRegExp *) JS_GetPrivate(cx, obj);
+    re = (JSRegExp *) obj->getPrivate();
     if (re) {
         switch (slot) {
           case REGEXP_SOURCE:
             *vp = STRING_TO_JSVAL(re->source);
             break;
           case REGEXP_GLOBAL:
             *vp = BOOLEAN_TO_JSVAL((re->flags & JSREG_GLOB) != 0);
             break;
@@ -5236,19 +5236,17 @@ static JSPropertySpec regexp_static_prop
      regexp_static_getProperty,    regexp_static_getProperty},
 
     {0,0,0,0,0}
 };
 
 static void
 regexp_finalize(JSContext *cx, JSObject *obj)
 {
-    JSRegExp *re;
-
-    re = (JSRegExp *) JS_GetPrivate(cx, obj);
+    JSRegExp *re = (JSRegExp *) obj->getPrivate();
     if (!re)
         return;
     js_DestroyRegExp(cx, re);
 }
 
 /* Forward static prototype. */
 static JSBool
 regexp_exec_sub(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
@@ -5269,17 +5267,17 @@ JSBool
 js_XDRRegExpObject(JSXDRState *xdr, JSObject **objp)
 {
     JSRegExp *re;
     JSString *source;
     uint32 flagsword;
     JSObject *obj;
 
     if (xdr->mode == JSXDR_ENCODE) {
-        re = (JSRegExp *) JS_GetPrivate(xdr->cx, *objp);
+        re = (JSRegExp *) (*objp)->getPrivate();
         if (!re)
             return JS_FALSE;
         source = re->source;
         flagsword = (uint32)re->flags;
     }
     if (!JS_XDRString(xdr, &source) ||
         !JS_XDRUint32(xdr, &flagsword)) {
         return JS_FALSE;
@@ -5288,38 +5286,34 @@ js_XDRRegExpObject(JSXDRState *xdr, JSOb
         obj = js_NewObject(xdr->cx, &js_RegExpClass, NULL, NULL);
         if (!obj)
             return JS_FALSE;
         STOBJ_CLEAR_PARENT(obj);
         STOBJ_CLEAR_PROTO(obj);
         re = js_NewRegExp(xdr->cx, NULL, source, (uint8)flagsword, JS_FALSE);
         if (!re)
             return JS_FALSE;
-        if (!JS_SetPrivate(xdr->cx, obj, re) ||
-            !js_SetLastIndex(xdr->cx, obj, 0)) {
-            js_DestroyRegExp(xdr->cx, re);
+        obj->setPrivate(re);
+        if (!js_SetLastIndex(xdr->cx, obj, 0))
             return JS_FALSE;
-        }
         *objp = obj;
     }
     return JS_TRUE;
 }
 
 #else  /* !JS_HAS_XDR */
 
 #define js_XDRRegExpObject NULL
 
 #endif /* !JS_HAS_XDR */
 
 static void
 regexp_trace(JSTracer *trc, JSObject *obj)
 {
-    JSRegExp *re;
-
-    re = (JSRegExp *) JS_GetPrivate(trc->context, obj);
+    JSRegExp *re = (JSRegExp *) obj->getPrivate();
     if (re && re->source)
         JS_CALL_STRING_TRACER(trc, re->source, "source");
 }
 
 JSClass js_RegExpClass = {
     js_RegExp_str,
     JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1) |
     JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_RegExp),
@@ -5343,17 +5337,17 @@ js_regexp_toString(JSContext *cx, JSObje
     jschar *chars;
     size_t length, nflags;
     uintN flags;
     JSString *str;
 
     if (!JS_InstanceOf(cx, obj, &js_RegExpClass, vp + 2))
         return JS_FALSE;
     JS_LOCK_OBJ(cx, obj);
-    re = (JSRegExp *) JS_GetPrivate(cx, obj);
+    re = (JSRegExp *) obj->getPrivate();
     if (!re) {
         JS_UNLOCK_OBJ(cx, obj);
         *vp = STRING_TO_JSVAL(cx->runtime->emptyString);
         return JS_TRUE;
     }
 
     re->source->getCharsAndLength(source, length);
     if (length == 0) {
@@ -5405,17 +5399,16 @@ regexp_toString(JSContext *cx, uintN arg
 }
 
 static JSBool
 regexp_compile_sub(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
                    jsval *rval)
 {
     JSString *opt, *str;
     JSRegExp *oldre, *re;
-    JSBool ok, ok2;
     JSObject *obj2;
     size_t length, nbytes;
     const jschar *cp, *start, *end;
     jschar *nstart, *ncp, *tmp;
 
     if (!JS_InstanceOf(cx, obj, &js_RegExpClass, argv))
         return JS_FALSE;
     opt = NULL;
@@ -5433,17 +5426,17 @@ regexp_compile_sub(JSContext *cx, JSObje
             obj2 = JSVAL_TO_OBJECT(argv[0]);
             if (obj2 && OBJ_GET_CLASS(cx, obj2) == &js_RegExpClass) {
                 if (argc >= 2 && !JSVAL_IS_VOID(argv[1])) { /* 'flags' passed */
                     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                                          JSMSG_NEWREGEXP_FLAGGED);
                     return JS_FALSE;
                 }
                 JS_LOCK_OBJ(cx, obj2);
-                re = (JSRegExp *) JS_GetPrivate(cx, obj2);
+                re = (JSRegExp *) obj->getPrivate();
                 if (!re) {
                     JS_UNLOCK_OBJ(cx, obj2);
                     return JS_FALSE;
                 }
                 re = js_NewRegExp(cx, NULL, re->source, re->flags, JS_FALSE);
                 JS_UNLOCK_OBJ(cx, obj2);
                 goto created;
             }
@@ -5504,28 +5497,25 @@ regexp_compile_sub(JSContext *cx, JSObje
         }
     }
 
     re = js_NewRegExpOpt(cx, str, opt, JS_FALSE);
 created:
     if (!re)
         return JS_FALSE;
     JS_LOCK_OBJ(cx, obj);
-    oldre = (JSRegExp *) JS_GetPrivate(cx, obj);
-    ok = JS_SetPrivate(cx, obj, re);
-    ok2 = js_SetLastIndex(cx, obj, 0);
+    oldre = (JSRegExp *) obj->getPrivate();
+    obj->setPrivate(re);
+
+    JSBool ok = js_SetLastIndex(cx, obj, 0);
     JS_UNLOCK_OBJ(cx, obj);
-    if (!ok) {
-        js_DestroyRegExp(cx, re);
-        return JS_FALSE;
-    }
     if (oldre)
         js_DestroyRegExp(cx, oldre);
     *rval = OBJECT_TO_JSVAL(obj);
-    return ok2;
+    return ok;
 }
 
 static JSBool
 regexp_compile(JSContext *cx, uintN argc, jsval *vp)
 {
     JSObject *obj;
 
     obj = JS_THIS_OBJECT(cx, vp);
@@ -5541,17 +5531,17 @@ regexp_exec_sub(JSContext *cx, JSObject 
     jsdouble lastIndex;
     JSString *str;
     size_t i;
 
     ok = JS_InstanceOf(cx, obj, &js_RegExpClass, argv);
     if (!ok)
         return JS_FALSE;
     JS_LOCK_OBJ(cx, obj);
-    re = (JSRegExp *) JS_GetPrivate(cx, obj);
+    re = (JSRegExp *) obj->getPrivate();
     if (!re) {
         JS_UNLOCK_OBJ(cx, obj);
         return JS_TRUE;
     }
 
     /* NB: we must reach out: after this paragraph, in order to drop re. */
     HOLD_REGEXP(cx, re);
     sticky = (re->flags & JSREG_STICKY) != 0;
@@ -5705,41 +5695,41 @@ js_NewRegExpObject(JSContext *cx, JSToke
     str = js_NewStringCopyN(cx, chars, length);
     if (!str)
         return NULL;
     JSAutoTempValueRooter tvr(cx, str);
     re = js_NewRegExp(cx, ts,  str, flags, JS_FALSE);
     if (!re)
         return NULL;
     obj = js_NewObject(cx, &js_RegExpClass, NULL, NULL);
-    if (!obj || !JS_SetPrivate(cx, obj, re)) {
+    if (!obj) {
         js_DestroyRegExp(cx, re);
-        obj = NULL;
+        return NULL;
     }
-    if (obj && !js_SetLastIndex(cx, obj, 0))
-        obj = NULL;
+    obj->setPrivate(re);
+    if (!js_SetLastIndex(cx, obj, 0))
+        return NULL;
     return obj;
 }
 
 JSObject *
 js_CloneRegExpObject(JSContext *cx, JSObject *obj, JSObject *parent)
 {
     JSObject *clone;
     JSRegExp *re;
 
     JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_RegExpClass);
     clone = js_NewObject(cx, &js_RegExpClass, NULL, parent);
     if (!clone)
         return NULL;
-    re = (JSRegExp *) JS_GetPrivate(cx, obj);
-    if (!JS_SetPrivate(cx, clone, re) || !js_SetLastIndex(cx, clone, 0)) {
-        cx->weakRoots.newborn[GCX_OBJECT] = NULL;
-        return NULL;
+    re = (JSRegExp *) obj->getPrivate();
+    if (re) {
+        clone->setPrivate(re);
+        HOLD_REGEXP(cx, re);
     }
-    HOLD_REGEXP(cx, re);
     return clone;
 }
 
 JSBool
 js_GetLastIndex(JSContext *cx, JSObject *obj, jsdouble *lastIndex)
 {
     jsval v;
 
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -113,17 +113,17 @@ script_toSource(JSContext *cx, uintN arg
 
     indent = 0;
     if (argc != 0) {
         indent = js_ValueToECMAUint32(cx, &vp[2]);
         if (JSVAL_IS_NULL(vp[2]))
             return JS_FALSE;
     }
 
-    script = (JSScript *) JS_GetPrivate(cx, obj);
+    script = (JSScript *) obj->getPrivate();
 
     /* Let n count the source string length, j the "front porch" length. */
     j = JS_snprintf(buf, sizeof buf, "(new %s(", js_ScriptClass.name);
     n = j + 2;
     if (!script) {
         /* Let k count the constructor argument string length. */
         k = 0;
         s = NULL;               /* quell GCC overwarning */
@@ -175,17 +175,17 @@ script_toString(JSContext *cx, uintN arg
         indent = js_ValueToECMAUint32(cx, &vp[2]);
         if (JSVAL_IS_NULL(vp[2]))
             return JS_FALSE;
     }
 
     obj = JS_THIS_OBJECT(cx, vp);
     if (!JS_InstanceOf(cx, obj, &js_ScriptClass, vp + 2))
         return JS_FALSE;
-    script = (JSScript *) JS_GetPrivate(cx, obj);
+    script = (JSScript *) obj->getPrivate();
     if (!script) {
         *vp = STRING_TO_JSVAL(cx->runtime->emptyString);
         return JS_TRUE;
     }
 
     str = JS_DecompileScript(cx, script, "Script.prototype.toString",
                              (uintN)indent);
     if (!str)
@@ -195,17 +195,16 @@ script_toString(JSContext *cx, uintN arg
 }
 
 static JSBool
 script_compile_sub(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
                    jsval *rval)
 {
     JSString *str;
     JSObject *scopeobj;
-    jsval v;
     JSScript *script, *oldscript;
     JSStackFrame *caller;
     const char *file;
     uintN line;
     JSPrincipals *principals;
     uint32 tcflags;
     jsint execDepth;
 
@@ -279,19 +278,18 @@ script_compile_sub(JSContext *cx, JSObje
     if (execDepth > 0) {
         JS_UNLOCK_OBJ(cx, obj);
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                              JSMSG_COMPILE_EXECED_SCRIPT);
         return JS_FALSE;
     }
 
     /* Swap script for obj's old script, if any. */
-    v = LOCKED_OBJ_GET_SLOT(obj, JSSLOT_PRIVATE);
-    oldscript = (JSScript*) (!JSVAL_IS_VOID(v) ? JSVAL_TO_PRIVATE(v) : NULL);
-    LOCKED_OBJ_SET_SLOT(obj, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(script));
+    oldscript = (JSScript*) obj->getPrivate();
+    obj->setPrivate(script);
     JS_UNLOCK_OBJ(cx, obj);
 
     if (oldscript)
         js_DestroyScript(cx, oldscript);
 
     script->u.object = obj;
     js_CallNewScriptHook(cx, script, NULL);
 
@@ -375,17 +373,17 @@ script_exec_sub(JSContext *cx, JSObject 
     scopeobj = js_CheckScopeChainValidity(cx, scopeobj, js_script_exec_str);
     if (!scopeobj)
         return JS_FALSE;
 
     /* Keep track of nesting depth for the script. */
     AdjustScriptExecDepth(cx, obj, 1);
 
     /* Must get to out label after this */
-    script = (JSScript *) JS_GetPrivate(cx, obj);
+    script = (JSScript *) obj->getPrivate();
     if (!script) {
         ok = JS_FALSE;
         goto out;
     }
 
     /* Belt-and-braces: check that this script object has access to scopeobj. */
     principals = script->principals;
     ok = js_CheckPrincipalsAccess(cx, scopeobj, principals,
@@ -691,17 +689,17 @@ script_freeze(JSContext *cx, uintN argc,
     JSBool ok, hasMagic;
     uint32 len;
     void *buf;
     JSString *str;
 
     obj = JS_THIS_OBJECT(cx, vp);
     if (!JS_InstanceOf(cx, obj, &js_ScriptClass, vp + 2))
         return JS_FALSE;
-    script = (JSScript *) JS_GetPrivate(cx, obj);
+    script = (JSScript *) obj->getPrivate();
     if (!script)
         return JS_TRUE;
 
     /* create new XDR */
     xdr = JS_XDRNewMem(cx, JSXDR_ENCODE);
     if (!xdr)
         return JS_FALSE;
 
@@ -815,19 +813,18 @@ script_thaw(JSContext *cx, uintN argc, j
     if (execDepth > 0) {
         JS_UNLOCK_OBJ(cx, obj);
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                              JSMSG_COMPILE_EXECED_SCRIPT);
         goto out;
     }
 
     /* Swap script for obj's old script, if any. */
-    v = LOCKED_OBJ_GET_SLOT(obj, JSSLOT_PRIVATE);
-    oldscript = !JSVAL_IS_VOID(v) ? JSVAL_TO_PRIVATE(v) : NULL;
-    LOCKED_OBJ_SET_SLOT(obj, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(script));
+    oldscript = (JSScript *) obj->getPrivate();
+    obj->setPrivate(script);
     JS_UNLOCK_OBJ(cx, obj);
 
     if (oldscript)
         js_DestroyScript(cx, oldscript);
 
     script->u.object = obj;
     js_CallNewScriptHook(cx, script, NULL);
 
@@ -866,19 +863,17 @@ static JSFunctionSpec script_methods[] =
     JS_FS_END
 };
 
 #endif /* JS_HAS_SCRIPT_OBJECT */
 
 static void
 script_finalize(JSContext *cx, JSObject *obj)
 {
-    JSScript *script;
-
-    script = (JSScript *) JS_GetPrivate(cx, obj);
+    JSScript *script = (JSScript *) obj->getPrivate();
     if (script)
         js_DestroyScript(cx, script);
 }
 
 static JSBool
 script_call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 {
 #if JS_HAS_SCRIPT_OBJECT
@@ -886,19 +881,17 @@ script_call(JSContext *cx, JSObject *obj
 #else
     return JS_FALSE;
 #endif
 }
 
 static void
 script_trace(JSTracer *trc, JSObject *obj)
 {
-    JSScript *script;
-
-    script = (JSScript *) JS_GetPrivate(trc->context, obj);
+    JSScript *script = (JSScript *) obj->getPrivate();
     if (script)
         js_TraceScript(trc, script);
 }
 
 #if !JS_HAS_SCRIPT_OBJECT
 #define JSProto_Script  JSProto_Object
 #endif
 
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -182,17 +182,17 @@ StackDepth(JSScript *script)
     JS_END_MACRO
 
 #define JS_GET_SCRIPT_FUNCTION(script, index, fun)                            \
     JS_BEGIN_MACRO                                                            \
         JSObject *funobj_;                                                    \
                                                                               \
         JS_GET_SCRIPT_OBJECT(script, index, funobj_);                         \
         JS_ASSERT(HAS_FUNCTION_CLASS(funobj_));                               \
-        JS_ASSERT(funobj_ == (JSObject *) STOBJ_GET_PRIVATE(funobj_));        \
+        JS_ASSERT(funobj_ == (JSObject *) funobj_->getAssignedPrivate());     \
         (fun) = (JSFunction *) funobj_;                                       \
         JS_ASSERT(FUN_INTERPRETED(fun));                                      \
     JS_END_MACRO
 
 #define JS_GET_SCRIPT_REGEXP(script, index, obj)                              \
     JS_BEGIN_MACRO                                                            \
         JSObjectArray *regexps_ = JS_SCRIPT_REGEXPS(script);                  \
         JS_ASSERT((uint32)(index) < regexps_->length);                        \
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -545,17 +545,17 @@ static JSBool
 str_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
 {
     jsval v;
     JSString *str;
 
     if (id == ATOM_KEY(cx->runtime->atomState.lengthAtom)) {
         if (OBJ_GET_CLASS(cx, obj) == &js_StringClass) {
             /* Follow ECMA-262 by fetching intrinsic length of our string. */
-            v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
+            v = obj->fslots[JSSLOT_PRIVATE];
             JS_ASSERT(JSVAL_IS_STRING(v));
             str = JSVAL_TO_STRING(v);
         } else {
             /* Preserve compatibility: convert obj to a string primitive. */
             str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj));
             if (!str)
                 return JS_FALSE;
         }
@@ -570,17 +570,17 @@ str_getProperty(JSContext *cx, JSObject 
 
 static JSBool
 str_enumerate(JSContext *cx, JSObject *obj)
 {
     jsval v;
     JSString *str, *str1;
     size_t i, length;
 
-    v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
+    v = obj->fslots[JSSLOT_PRIVATE];
     JS_ASSERT(JSVAL_IS_STRING(v));
     str = JSVAL_TO_STRING(v);
 
     length = str->length();
     for (i = 0; i < length; i++) {
         str1 = js_NewDependentString(cx, str, i, 1);
         if (!str1)
             return JS_FALSE;
@@ -599,17 +599,17 @@ str_resolve(JSContext *cx, JSObject *obj
 {
     jsval v;
     JSString *str, *str1;
     jsint slot;
 
     if (!JSVAL_IS_INT(id) || (flags & JSRESOLVE_ASSIGNING))
         return JS_TRUE;
 
-    v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
+    v = obj->fslots[JSSLOT_PRIVATE];
     JS_ASSERT(JSVAL_IS_STRING(v));
     str = JSVAL_TO_STRING(v);
 
     slot = JSVAL_TO_INT(id);
     if ((size_t)slot < str->length()) {
         str1 = js_GetUnitString(cx, str, (size_t)slot);
         if (!str1)
             return JS_FALSE;
@@ -620,17 +620,17 @@ str_resolve(JSContext *cx, JSObject *obj
         }
         *objp = obj;
     }
     return JS_TRUE;
 }
 
 JSClass js_StringClass = {
     js_String_str,
-    JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE |
+    JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_NEW_RESOLVE |
     JSCLASS_HAS_CACHED_PROTO(JSProto_String),
     JS_PropertyStub,   JS_PropertyStub,   str_getProperty,   JS_PropertyStub,
     str_enumerate, (JSResolveOp)str_resolve, JS_ConvertStub, NULL,
     JSCLASS_NO_OPTIONAL_MEMBERS
 };
 
 #define NORMALIZE_THIS(cx,vp,str)                                             \
     JS_BEGIN_MACRO                                                            \
@@ -780,17 +780,17 @@ str_substring(JSContext *cx, uintN argc,
 }
 
 #ifdef JS_TRACER
 static JSString* FASTCALL
 String_p_toString(JSContext* cx, JSObject* obj)
 {
     if (!JS_InstanceOf(cx, obj, &js_StringClass, NULL))
         return NULL;
-    jsval v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
+    jsval v = obj->fslots[JSSLOT_PRIVATE];
     JS_ASSERT(JSVAL_IS_STRING(v));
     return JSVAL_TO_STRING(v);
 }
 #endif
 
 JSString* JS_FASTCALL
 js_toLowerCase(JSContext *cx, JSString *str)
 {
@@ -1311,17 +1311,17 @@ match_or_replace(JSContext *cx,
     JSBool ok, test;
     jsint count;
 
     NORMALIZE_THIS(cx, vp, str);
     data->str = str;
 
     if (argc != 0 && VALUE_IS_REGEXP(cx, vp[2])) {
         reobj = JSVAL_TO_OBJECT(vp[2]);
-        re = (JSRegExp *) JS_GetPrivate(cx, reobj);
+        re = (JSRegExp *) reobj->getPrivate();
     } else {
         src = ArgToRootedString(cx, argc, vp, 0);
         if (!src)
             return JS_FALSE;
         if (data->optarg < argc) {
             opt = js_ValueToString(cx, vp[2 + data->optarg]);
             if (!opt)
                 return JS_FALSE;
@@ -1997,17 +1997,17 @@ str_split(JSContext *cx, uintN argc, jsv
         return JS_FALSE;
     *vp = OBJECT_TO_JSVAL(arrayobj);
 
     if (argc == 0) {
         v = STRING_TO_JSVAL(str);
         ok = OBJ_SET_PROPERTY(cx, arrayobj, INT_TO_JSID(0), &v);
     } else {
         if (VALUE_IS_REGEXP(cx, vp[2])) {
-            re = (JSRegExp *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(vp[2]));
+            re = (JSRegExp *) JSVAL_TO_OBJECT(vp[2])->getPrivate();
             sep = &tmp;
 
             /* Set a magic value so we can detect a successful re match. */
             sep->chars = NULL;
             sep->length = 0;
         } else {
             JSString *str2 = js_ValueToString(cx, vp[2]);
             if (!str2)
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -227,17 +227,17 @@ jitstats_getProperty(JSContext *cx, JSOb
     char retstr[64];
     JS_snprintf(retstr, sizeof retstr, "%llu", result);
     *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, retstr));
     return JS_TRUE;
 }
 
 JSClass jitstats_class = {
     "jitstats",
-    JSCLASS_HAS_PRIVATE,
+    0,
     JS_PropertyStub,       JS_PropertyStub,
     jitstats_getProperty,  JS_PropertyStub,
     JS_EnumerateStub,      JS_ResolveStub,
     JS_ConvertStub,        NULL,
     JSCLASS_NO_OPTIONAL_MEMBERS
 };
 
 void
@@ -2359,17 +2359,17 @@ GetFromClosure(JSContext* cx, JSObject* 
      */
     VOUCH_DOES_NOT_REQUIRE_STACK();
     if (cx->fp->callobj == call) {
         slot = T::adj_slot(cx->fp, slot);
         *result = state->stackBase[slot];
         return state->callstackBase[0]->get_typemap()[slot];
     }
 
-    JSStackFrame* fp = (JSStackFrame*) OBJ_GET_PRIVATE(cx, call);
+    JSStackFrame* fp = (JSStackFrame*) call->getPrivate();
     if (!fp)
         return TT_INVALID;
     jsval v = T::slots(fp)[slot];
     JSTraceType type = getCoercedType(v);
     ValueToNative(cx, v, type, result);
     return type;
 }
 
@@ -6767,17 +6767,17 @@ TraceRecorder::scopeChain() const
 /*
  * Return the frame of a call object if that frame is part of the current
  * trace. |depthp| is an optional outparam: if it is non-null, it will be
  * filled in with the depth of the call object's frame relevant to cx->fp.
  */
 JS_REQUIRES_STACK JSStackFrame*
 TraceRecorder::frameIfInRange(JSObject* obj, unsigned* depthp) const
 {
-    JSStackFrame* ofp = (JSStackFrame*) JS_GetPrivate(cx, obj);
+    JSStackFrame* ofp = (JSStackFrame*) obj->getPrivate();
     JSStackFrame* fp = cx->fp;
     for (unsigned depth = 0; depth <= callDepth; ++depth) {
         if (fp == ofp) {
             if (depthp)
                 *depthp = depth;
             return ofp;
         }
         if (!(fp = fp->down))
@@ -6834,17 +6834,17 @@ TraceRecorder::scopeChainProp(JSObject* 
         nr.tracked = true;
         return JSRS_CONTINUE;
     }
 
     if (wasDeepAborted())
         ABORT_TRACE("deep abort from property lookup");
 
     if (obj == obj2 && OBJ_GET_CLASS(cx, obj) == &js_CallClass) {
-        JSStackFrame* cfp = (JSStackFrame*) JS_GetPrivate(cx, obj);
+        JSStackFrame* cfp = (JSStackFrame*) obj->getPrivate();
         if (cfp) {
             JSScopeProperty* sprop = (JSScopeProperty*) prop;
 
             uint32 setflags = (js_CodeSpec[*cx->fp->regs->pc].format & (JOF_SET | JOF_INCDEC | JOF_FOR));
             if (setflags && (sprop->attrs & JSPROP_READONLY))
                 ABORT_TRACE("writing to a read-only property");
 
             uintN slot = sprop->shortid;
@@ -10437,17 +10437,17 @@ TraceRecorder::guardCallee(jsval& callee
 
     VMSideExit* branchExit = snapshot(BRANCH_EXIT);
     JSObject* callee_obj = JSVAL_TO_OBJECT(callee);
     LIns* callee_ins = get(&callee);
 
     guard(true,
           lir->ins2(LIR_eq,
                     stobj_get_private(callee_ins),
-                    INS_CONSTPTR(OBJ_GET_PRIVATE(cx, callee_obj))),
+                    INS_CONSTPTR(callee_obj->getAssignedPrivate())),
           branchExit);
     guard(true,
           lir->ins2(LIR_eq,
                     stobj_get_fslot(callee_ins, JSSLOT_PARENT),
                     INS_CONSTPTR(OBJ_GET_PARENT(cx, callee_obj))),
           branchExit);
     return JSRS_CONTINUE;
 }
@@ -11426,17 +11426,17 @@ TraceRecorder::record_JSOP_BINDNAME()
     } else {
         obj = fp->scopeChain;
 
         // In global code, fp->scopeChain can only contain blocks
         // whose values are still on the stack.  We never use BINDNAME
         // to refer to these.
         while (OBJ_GET_CLASS(cx, obj) == &js_BlockClass) {
             // The block's values are still on the stack.
-            JS_ASSERT(OBJ_GET_PRIVATE(cx, obj) == fp);
+            JS_ASSERT(obj->getAssignedPrivate() == fp);
 
             obj = OBJ_GET_PARENT(cx, obj);
 
             // Blocks always have parents.
             JS_ASSERT(obj);
         }
     }
 
--- a/js/src/jsxml.cpp
+++ b/js/src/jsxml.cpp
@@ -1962,17 +1962,17 @@ ToXML(JSContext *cx, jsval v)
     uint32 length;
 
     if (JSVAL_IS_PRIMITIVE(v)) {
         if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v))
             goto bad;
     } else {
         obj = JSVAL_TO_OBJECT(v);
         if (OBJECT_IS_XML(cx, obj)) {
-            xml = (JSXML *) JS_GetPrivate(cx, obj);
+            xml = (JSXML *) obj->getAssignedPrivate();
             if (xml->xml_class == JSXML_CLASS_LIST) {
                 if (xml->xml_kids.length != 1)
                     goto bad;
                 xml = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML);
                 if (xml) {
                     JS_ASSERT(xml->xml_class != JSXML_CLASS_LIST);
                     return js_GetXMLObject(cx, xml);
                 }
@@ -2043,22 +2043,22 @@ ToXMLList(JSContext *cx, jsval v)
     uint32 i, length;
 
     if (JSVAL_IS_PRIMITIVE(v)) {
         if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v))
             goto bad;
     } else {
         obj = JSVAL_TO_OBJECT(v);
         if (OBJECT_IS_XML(cx, obj)) {
-            xml = (JSXML *) JS_GetPrivate(cx, obj);
+            xml = (JSXML *) obj->getAssignedPrivate();
             if (xml->xml_class != JSXML_CLASS_LIST) {
                 listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST);
                 if (!listobj)
                     return NULL;
-                list = (JSXML *) JS_GetPrivate(cx, listobj);
+                list = (JSXML *) listobj->getAssignedPrivate();
                 if (!Append(cx, list, xml))
                     return NULL;
                 return listobj;
             }
             return obj;
         }
 
         clasp = OBJ_GET_CLASS(cx, obj);
@@ -2087,17 +2087,17 @@ ToXMLList(JSContext *cx, jsval v)
             js_LeaveLocalRootScope(cx);
             return NULL;
         }
         length = JSXML_LENGTH(xml);
     }
 
     listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST);
     if (listobj) {
-        list = (JSXML *) JS_GetPrivate(cx, listobj);
+        list = (JSXML *) listobj->getAssignedPrivate();
         for (i = 0; i < length; i++) {
             kid = OrphanXMLChild(cx, xml, i);
             if (!kid || !Append(cx, list, kid)) {
                 listobj = NULL;
                 break;
             }
         }
     }
@@ -2956,17 +2956,17 @@ ToXMLString(JSContext *cx, jsval v, uint
             return NULL;
         str = js_ValueToString(cx, v);
         if (!str)
             return NULL;
         return EscapeElementValue(cx, NULL, str);
     }
 
     /* Handle non-element cases in this switch, returning from each case. */
-    xml = (JSXML *) JS_GetPrivate(cx, obj);
+    xml = (JSXML *) obj->getAssignedPrivate();
     return XMLToXMLString(cx, xml, NULL, toSourceFlag | 0);
 }
 
 static JSObject *
 ToAttributeName(JSContext *cx, jsval v)
 {
     JSString *name, *uri, *prefix;
     JSObject *obj;
@@ -3208,33 +3208,29 @@ Append(JSContext *cx, JSXML *list, JSXML
 /* ECMA-357 9.1.1.7 XML [[DeepCopy]] and 9.2.1.7 XMLList [[DeepCopy]]. */
 static JSXML *
 DeepCopyInLRS(JSContext *cx, JSXML *xml, uintN flags);
 
 static JSXML *
 DeepCopy(JSContext *cx, JSXML *xml, JSObject *obj, uintN flags)
 {
     JSXML *copy;
-    JSBool ok;
 
     /* Our caller may not be protecting newborns with a local root scope. */
     if (!js_EnterLocalRootScope(cx))
         return NULL;
     copy = DeepCopyInLRS(cx, xml, flags);
     if (copy) {
         if (obj) {
             /* Caller provided the object for this copy, hook 'em up. */
-            ok = JS_SetPrivate(cx, obj, copy);
-            if (ok)
-                copy->object = obj;
-        } else {
-            ok = js_GetXMLObject(cx, copy) != NULL;
-        }
-        if (!ok)
+            obj->setPrivate(copy);
+            copy->object = obj;
+        } else if (!js_GetXMLObject(cx, copy)) {
             copy = NULL;
+        }
     }
     js_LeaveLocalRootScopeWithResult(cx, (jsval) copy);
     return copy;
 }
 
 /*
  * (i) We must be in a local root scope (InLRS).
  * (ii) parent must have a rooted object.
@@ -3465,17 +3461,17 @@ Descendants(JSContext *cx, JSXML *xml, j
 
     nameqn = ToXMLName(cx, id, &funid);
     if (!nameqn)
         return NULL;
 
     listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST);
     if (!listobj)
         return NULL;
-    list = (JSXML *) JS_GetPrivate(cx, listobj);
+    list = (JSXML *) listobj->getAssignedPrivate();
     if (funid)
         return list;
 
     /*
      * Protect nameqn's object and strings from GC by linking list to it
      * temporarily.  The cx->newborn[GCX_OBJECT] GC root protects listobj,
      * which protects list.  Any other object allocations occuring beneath
      * DescendantsHelper use local roots.
@@ -3615,17 +3611,17 @@ Equals(JSContext *cx, JSXML *xml, jsval 
             if (JSVAL_IS_VOID(v) && xml->xml_kids.length == 0)
                 *bp = JS_TRUE;
         }
     } else {
         vobj = JSVAL_TO_OBJECT(v);
         if (!OBJECT_IS_XML(cx, vobj)) {
             *bp = JS_FALSE;
         } else {
-            vxml = (JSXML *) JS_GetPrivate(cx, vobj);
+            vxml = (JSXML *) vobj->getAssignedPrivate();
             if (!XMLEquals(cx, xml, vxml, bp))
                 return JS_FALSE;
         }
     }
     return JS_TRUE;
 }
 
 static JSBool
@@ -3656,17 +3652,17 @@ Insert(JSContext *cx, JSXML *xml, uint32
     if (!JSXML_HAS_KIDS(xml))
         return JS_TRUE;
 
     n = 1;
     vxml = NULL;
     if (!JSVAL_IS_PRIMITIVE(v)) {
         vobj = JSVAL_TO_OBJECT(v);
         if (OBJECT_IS_XML(cx, vobj)) {
-            vxml = (JSXML *) JS_GetPrivate(cx, vobj);
+            vxml = (JSXML *) vobj->getAssignedPrivate();
             if (vxml->xml_class == JSXML_CLASS_LIST) {
                 n = vxml->xml_kids.length;
                 if (n == 0)
                     return JS_TRUE;
                 for (j = 0; j < n; j++) {
                     kid = XMLARRAY_MEMBER(&vxml->xml_kids, j, JSXML);
                     if (!kid)
                         continue;
@@ -3750,17 +3746,17 @@ Replace(JSContext *cx, JSXML *xml, uint3
     n = xml->xml_kids.length;
     if (i > n)
         i = n;
 
     vxml = NULL;
     if (!JSVAL_IS_PRIMITIVE(v)) {
         vobj = JSVAL_TO_OBJECT(v);
         if (OBJECT_IS_XML(cx, vobj))
-            vxml = (JSXML *) JS_GetPrivate(cx, vobj);
+            vxml = (JSXML *) vobj->getAssignedPrivate();
     }
 
     switch (vxml ? JSXMLClass(vxml->xml_class) : JSXML_CLASS_LIMIT) {
       case JSXML_CLASS_ELEMENT:
         /* OPTION: enforce that descendants have superset namespaces. */
         if (!CheckCycle(cx, xml, vxml))
             return JS_FALSE;
       case JSXML_CLASS_COMMENT:
@@ -4000,17 +3996,17 @@ GetProperty(JSContext *cx, JSObject *obj
     roots[0] = OBJECT_TO_JSVAL(nameqn);
     JS_PUSH_TEMP_ROOT(cx, 1, roots, &tvr);
 
     listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST);
     if (listobj) {
         roots[1] = OBJECT_TO_JSVAL(listobj);
         tvr.count++;
 
-        list = (JSXML *) JS_GetPrivate(cx, listobj);
+        list = (JSXML *) listobj->getAssignedPrivate();
         if (!GetNamedProperty(cx, xml, nameqn, list)) {
             listobj = NULL;
         } else {
             /*
              * Erratum: ECMA-357 9.1.1.1 misses that [[Append]] sets the
              * given list's [[TargetProperty]] to the property that is being
              * appended. This means that any use of the internal [[Get]]
              * property returns a list which, when used by e.g. [[Insert]]
@@ -4086,17 +4082,17 @@ PutProperty(JSContext *cx, JSObject *obj
     if (!xml)
         return JS_FALSE;
 
     /* Precompute vxml for 9.2.1.2 2(c)(vii)(2-3) and 2(d) and 9.1.1.2 1. */
     vxml = NULL;
     if (!JSVAL_IS_PRIMITIVE(*vp)) {
         vobj = JSVAL_TO_OBJECT(*vp);
         if (OBJECT_IS_XML(cx, vobj))
-            vxml = (JSXML *) JS_GetPrivate(cx, vobj);
+            vxml = (JSXML *) vobj->getAssignedPrivate();
     }
 
     ok = js_EnterLocalRootScope(cx);
     if (!ok)
         return JS_FALSE;
     MUST_FLOW_THROUGH("out");
     roots[OBJ_ROOT] = OBJECT_TO_JSVAL(obj);
     roots[ID_ROOT] = id;
@@ -4179,17 +4175,17 @@ PutProperty(JSContext *cx, JSObject *obj
                      * and targetprop are non-null.
                      */
                     ok = GetProperty(cx, rxml->object, id, &attrval);
                     if (!ok)
                         goto out;
                     if (JSVAL_IS_PRIMITIVE(attrval))    /* no such attribute */
                         goto out;
                     attrobj = JSVAL_TO_OBJECT(attrval);
-                    attr = (JSXML *) JS_GetPrivate(cx, attrobj);
+                    attr = (JSXML *) attrobj->getAssignedPrivate();
                     if (JSXML_LENGTH(attr) != 0)
                         goto out;
 
                     kid = js_NewXML(cx, JSXML_CLASS_ATTRIBUTE);
                 } else {
                     /* 2(c)(v). */
                     kid = js_NewXML(cx, JSXML_CLASS_ELEMENT);
                 }
@@ -4285,17 +4281,17 @@ PutProperty(JSContext *cx, JSObject *obj
                 ok = PutProperty(cx, parentobj, id, vp);
                 if (!ok)
                     goto out;
 
                 /* 2(e)(ii). */
                 ok = GetProperty(cx, parentobj, id, vp);
                 if (!ok)
                     goto out;
-                attr = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(*vp));
+                attr = (JSXML *) JSVAL_TO_OBJECT(*vp)->getAssignedPrivate();
 
                 /* 2(e)(iii) - the length check comes from the bug 375406. */
                 if (attr->xml_kids.length != 0)
                     xml->xml_kids.vector[i] = attr->xml_kids.vector[0];
             }
         }
 
         /* 2(f). */
@@ -4378,17 +4374,17 @@ PutProperty(JSContext *cx, JSObject *obj
              * on it to satisfy the constraint.
              */
             if (!vxml) {
                 JS_ASSERT(JSVAL_IS_STRING(*vp));
                 vobj = ToXML(cx, *vp);
                 if (!vobj)
                     goto bad;
                 roots[VAL_ROOT] = *vp = OBJECT_TO_JSVAL(vobj);
-                vxml = (JSXML *) JS_GetPrivate(cx, vobj);
+                vxml = (JSXML *) vobj->getAssignedPrivate();
             }
             XMLARRAY_SET_MEMBER(&xml->xml_kids, i, vxml);
         }
 
         /* 2(h). */
         else {
             kidobj = js_GetXMLObject(cx, kid);
             if (!kidobj)
@@ -4641,17 +4637,17 @@ PutProperty(JSContext *cx, JSObject *obj
                 nameqn = NewXMLQName(cx, left, right, GetLocalName(nameqn));
                 if (!nameqn)
                     goto bad;
 
                 /* 13(b)(iii). */
                 vobj = js_NewXMLObject(cx, JSXML_CLASS_ELEMENT);
                 if (!vobj)
                     goto bad;
-                vxml = (JSXML *) JS_GetPrivate(cx, vobj);
+                vxml = (JSXML *) vobj->getAssignedPrivate();
                 vxml->parent = xml;
                 vxml->name = nameqn;
 
                 /* 13(b)(iv-vi). */
                 ns = GetNamespace(cx, nameqn, NULL);
                 if (!ns)
                     goto bad;
                 ok = Replace(cx, xml, matchIndex, OBJECT_TO_JSVAL(vobj));
@@ -4743,29 +4739,29 @@ ResolveValue(JSContext *cx, JSXML *list,
         return JS_TRUE;
     }
     if (!js_GetXMLObject(cx, base))
         return JS_FALSE;
 
     id = OBJECT_TO_JSVAL(targetprop);
     if (!GetProperty(cx, base->object, id, &tv))
         return JS_FALSE;
-    target = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(tv));
+    target = (JSXML *) JSVAL_TO_OBJECT(tv)->getAssignedPrivate();
 
     if (JSXML_LENGTH(target) == 0) {
         if (base->xml_class == JSXML_CLASS_LIST && JSXML_LENGTH(base) > 1) {
             *result = NULL;
             return JS_TRUE;
         }
         tv = STRING_TO_JSVAL(cx->runtime->emptyString);
         if (!PutProperty(cx, base->object, id, &tv))
             return JS_FALSE;
         if (!GetProperty(cx, base->object, id, &tv))
             return JS_FALSE;
-        target = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(tv));
+        target = (JSXML *) JSVAL_TO_OBJECT(tv)->getAssignedPrivate();
     }
 
     *result = target;
     return JS_TRUE;
 }
 
 static JSBool
 HasNamedProperty(JSXML *xml, JSObject *nameqn)
@@ -4833,17 +4829,17 @@ HasFunctionProperty(JSContext *cx, JSObj
 
     JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_XMLClass);
 
     if (!js_LookupProperty(cx, obj, funid, &pobj, &prop))
         return JS_FALSE;
     if (prop) {
         OBJ_DROP_PROPERTY(cx, pobj, prop);
     } else {
-        xml = (JSXML *) JS_GetPrivate(cx, obj);
+        xml = (JSXML *) obj->getAssignedPrivate();
         if (HasSimpleContent(xml)) {
             /*
              * Search in String.prototype to set found whenever
              * GetXMLFunction returns existing function.
              */
             JS_PUSH_TEMP_ROOT_OBJECT(cx, NULL, &tvr);
             ok = js_GetClassPrototype(cx, NULL, INT_TO_JSID(JSProto_String),
                                       &tvr.u.object);
@@ -4866,17 +4862,17 @@ HasFunctionProperty(JSContext *cx, JSObj
 static JSBool
 HasProperty(JSContext *cx, JSObject *obj, jsval id, JSBool *found)
 {
     JSXML *xml;
     uint32 i;
     JSObject *qn;
     jsid funid;
 
-    xml = (JSXML *) JS_GetPrivate(cx, obj);
+    xml = (JSXML *) obj->getAssignedPrivate();
     if (js_IdIsIndex(id, &i)) {
         *found = HasIndexedProperty(xml, i);
     } else {
         qn = ToXMLName(cx, id, &funid);
         if (!qn)
             return JS_FALSE;
         if (funid) {
             if (!HasFunctionProperty(cx, obj, funid, found))
@@ -4886,19 +4882,17 @@ HasProperty(JSContext *cx, JSObject *obj
         }
     }
     return JS_TRUE;
 }
 
 static void
 xml_finalize(JSContext *cx, JSObject *obj)
 {
-    JSXML *xml;
-
-    xml = (JSXML *) JS_GetPrivate(cx, obj);
+    JSXML *xml = (JSXML *) obj->getPrivate();
     if (!xml)
         return;
     if (xml->object == obj)
         xml->object = NULL;
 }
 
 static void
 xml_trace_vector(JSTracer *trc, JSXML **vec, uint32 len)
@@ -4947,17 +4941,17 @@ xml_lookupProperty(JSContext *cx, JSObje
     JSBool found;
     JSXML *xml;
     uint32 i;
     JSObject *qn;
     jsid funid;
     JSScopeProperty *sprop;
 
     v = ID_TO_VALUE(id);
-    xml = (JSXML *) JS_GetPrivate(cx, obj);
+    xml = (JSXML *) obj->getAssignedPrivate();
     if (js_IdIsIndex(v, &i)) {
         found = HasIndexedProperty(xml, i);
     } else {
         qn = ToXMLName(cx, v, &funid);
         if (!qn)
             return JS_FALSE;
         if (funid)
             return js_LookupProperty(cx, obj, funid, objp, propp);
@@ -5059,17 +5053,17 @@ xml_deleteProperty(JSContext *cx, JSObje
 {
     JSXML *xml;
     jsval idval;
     uint32 index;
     JSObject *nameqn;
     jsid funid;
 
     idval = ID_TO_VALUE(id);
-    xml = (JSXML *) JS_GetPrivate(cx, obj);
+    xml = (JSXML *) obj->getAssignedPrivate();
     if (js_IdIsIndex(idval, &index)) {
         if (xml->xml_class != JSXML_CLASS_LIST) {
             /* See NOTE in spec: this variation is reserved for future use. */
             ReportBadXMLName(cx, id);
             return JS_FALSE;
         }
 
         /* ECMA-357 9.2.1.3. */
@@ -5102,17 +5096,17 @@ xml_deleteProperty(JSContext *cx, JSObje
 
 static JSBool
 xml_defaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp)
 {
     JSXML *xml;
 
     if (hint == JSTYPE_OBJECT) {
         /* Called from for..in code in js_Interpret: return an XMLList. */
-        xml = (JSXML *) JS_GetPrivate(cx, obj);
+        xml = (JSXML *) obj->getAssignedPrivate();
         if (xml->xml_class != JSXML_CLASS_LIST) {
             obj = ToXMLList(cx, OBJECT_TO_JSVAL(obj));
             if (!obj)
                 return JS_FALSE;
         }
         *vp = OBJECT_TO_JSVAL(obj);
         return JS_TRUE;
     }
@@ -5123,17 +5117,17 @@ xml_defaultValue(JSContext *cx, JSObject
 static JSBool
 xml_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
               jsval *statep, jsid *idp)
 {
     JSXML *xml;
     uint32 length, index;
     JSXMLArrayCursor *cursor;
 
-    xml = (JSXML *) JS_GetPrivate(cx, obj);
+    xml = (JSXML *)obj->getAssignedPrivate();
     length = JSXML_LENGTH(xml);
 
     switch (enum_op) {
       case JSENUMERATE_INIT:
         if (length == 0) {
             cursor = NULL;
         } else {
             cursor = (JSXMLArrayCursor *) cx->malloc(sizeof *cursor);
@@ -5171,19 +5165,17 @@ static JSBool
 xml_hasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
 {
     return JS_TRUE;
 }
 
 static void
 xml_trace(JSTracer *trc, JSObject *obj)
 {
-    JSXML *xml;
-
-    xml = (JSXML *) JS_GetPrivate(trc->context, obj);
+    JSXML *xml = (JSXML *) obj->getPrivate();
     if (xml)
         JS_CALL_TRACER(trc, xml, JSTRACE_XML, "private");
 }
 
 static void
 xml_clear(JSContext *cx, JSObject *obj)
 {
 }
@@ -5256,17 +5248,17 @@ js_EnumerateXMLValues(JSContext *cx, JSO
                       jsval *statep, jsid *idp, jsval *vp)
 {
     JSXML *xml, *kid;
     uint32 length, index;
     JSXMLArrayCursor *cursor;
     JSObject *kidobj;
 
     JS_ASSERT(JS_InstanceOf(cx, obj, &js_XMLClass, NULL));
-    xml = (JSXML *) JS_GetPrivate(cx, obj);
+    xml = (JSXML *) obj->getAssignedPrivate();
     length = JSXML_LENGTH(xml);
     JS_ASSERT(INT_FITS_IN_JSVAL(length));
 
     switch (enum_op) {
       case JSENUMERATE_INIT:
         if (length == 0) {
             cursor = NULL;
         } else {
@@ -5318,22 +5310,22 @@ js_TestXMLEquality(JSContext *cx, JSObje
 {
     JSXML *xml, *vxml;
     JSObject *vobj;
     JSBool ok;
     JSString *str, *vstr;
     jsdouble d, d2;
 
     JS_ASSERT(JS_InstanceOf(cx, obj, &js_XMLClass, NULL));
-    xml = (JSXML *) JS_GetPrivate(cx, obj);
+    xml = (JSXML *) obj->getAssignedPrivate();
     vxml = NULL;
     if (!JSVAL_IS_PRIMITIVE(v)) {
         vobj = JSVAL_TO_OBJECT(v);
         if (OBJECT_IS_XML(cx, vobj))
-            vxml = (JSXML *) JS_GetPrivate(cx, vobj);
+            vxml = (JSXML *) vobj->getAssignedPrivate();
     }
 
     if (xml->xml_class == JSXML_CLASS_LIST) {
         ok = Equals(cx, xml, v, bp);
     } else if (vxml) {
         if (vxml->xml_class == JSXML_CLASS_LIST) {
             ok = Equals(cx, vxml, OBJECT_TO_JSVAL(obj), bp);
         } else {
@@ -5401,31 +5393,31 @@ js_ConcatenateXML(JSContext *cx, JSObjec
         return JS_FALSE;
 
     listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST);
     if (!listobj) {
         ok = JS_FALSE;
         goto out;
     }
 
-    list = (JSXML *) JS_GetPrivate(cx, listobj);
-    lxml = (JSXML *) JS_GetPrivate(cx, obj);
+    list = (JSXML *) listobj->getAssignedPrivate();
+    lxml = (JSXML *) obj->getAssignedPrivate();
     ok = Append(cx, list, lxml);
     if (!ok)
         goto out;
 
     if (VALUE_IS_XML(cx, v)) {
-        rxml = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(v));
+        rxml = (JSXML *) JSVAL_TO_OBJECT(v)->getAssignedPrivate();
     } else {
         robj = ToXML(cx, v);
         if (!robj) {
             ok = JS_FALSE;
             goto out;
         }
-        rxml = (JSXML *) JS_GetPrivate(cx, robj);
+        rxml = (JSXML *) robj->getAssignedPrivate();
     }
     ok = Append(cx, list, rxml);
     if (!ok)
         goto out;
 
     *vp = OBJECT_TO_JSVAL(listobj);
 out:
     js_LeaveLocalRootScopeWithResult(cx, *vp);
@@ -5552,17 +5544,17 @@ xml_appendChild(JSContext *cx, uintN arg
         return JS_FALSE;
 
     if (!GetProperty(cx, obj, name, &v))
         return JS_FALSE;
 
     JS_ASSERT(!JSVAL_IS_PRIMITIVE(v));
     vobj = JSVAL_TO_OBJECT(v);
     JS_ASSERT(OBJECT_IS_XML(cx, vobj));
-    vxml = (JSXML *) JS_GetPrivate(cx, vobj);
+    vxml = (JSXML *) vobj->getAssignedPrivate();
     JS_ASSERT(vxml->xml_class == JSXML_CLASS_LIST);
 
     if (!IndexToIdVal(cx, vxml->xml_kids.length, &name))
         return JS_FALSE;
     *vp = (argc != 0) ? vp[2] : JSVAL_VOID;
     if (!PutProperty(cx, JSVAL_TO_OBJECT(v), name, vp))
         return JS_FALSE;
 
@@ -5615,17 +5607,17 @@ xml_list_helper(JSContext *cx, JSXML *xm
     JSObject *listobj;
     JSXML *list;
 
     listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST);
     if (!listobj)
         return NULL;
 
     *rval = OBJECT_TO_JSVAL(listobj);
-    list = (JSXML *) JS_GetPrivate(cx, listobj);
+    list = (JSXML *) listobj->getAssignedPrivate();
     list->xml_target = xml;
     return list;
 }
 
 static JSBool
 xml_child_helper(JSContext *cx, JSObject *obj, JSXML *xml, jsval name,
                  jsval *rval)
 {
@@ -5681,17 +5673,17 @@ xml_child(JSContext *cx, uintN argc, jsv
             if (!xml_child_helper(cx, kidobj, kid, name, &v))
                 break;
             if (JSVAL_IS_VOID(v)) {
                 /* The property didn't exist in this kid. */
                 continue;
             }
 
             JS_ASSERT(!JSVAL_IS_PRIMITIVE(v));
-            vxml = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(v));
+            vxml = (JSXML *) JSVAL_TO_OBJECT(v)->getAssignedPrivate();
             if ((!JSXML_HAS_KIDS(vxml) || vxml->xml_kids.length != 0) &&
                 !Append(cx, list, vxml)) {
                 break;
             }
         }
         XMLArrayCursorFinish(&cursor);
         return !kid;
     }
@@ -5763,17 +5755,17 @@ xml_comments_helper(JSContext *cx, JSObj
                     ok = xml_comments_helper(cx, kidobj, kid, &v);
                 } else {
                     ok = JS_FALSE;
                     v = JSVAL_NULL;
                 }
                 js_LeaveLocalRootScopeWithResult(cx, v);
                 if (!ok)
                     break;
-                vxml = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(v));
+                vxml = (JSXML *) JSVAL_TO_OBJECT(v)->getAssignedPrivate();
                 if (JSXML_LENGTH(vxml) != 0) {
                     ok = Append(cx, list, vxml);
                     if (!ok)
                         break;
                 }
             }
         }
     } else {
@@ -5893,17 +5885,17 @@ xml_elements_helper(JSContext *cx, JSObj
                     ok = xml_elements_helper(cx, kidobj, kid, nameqn, &v);
                 } else {
                     ok = JS_FALSE;
                     v = JSVAL_NULL;
                 }
                 js_LeaveLocalRootScopeWithResult(cx, v);
                 if (!ok)
                     break;
-                vxml = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(v));
+                vxml = (JSXML *) JSVAL_TO_OBJECT(v)->getAssignedPrivate();
                 if (JSXML_LENGTH(vxml) != 0) {
                     ok = Append(cx, list, vxml);
                     if (!ok)
                         break;
                 }
             }
         }
         XMLArrayCursorFinish(&cursor);
@@ -5987,17 +5979,17 @@ again:
             *vp = JSVAL_TRUE;
         } else if (xml->xml_kids.length == 1) {
             kid = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML);
             if (kid) {
                 kidobj = js_GetXMLObject(cx, kid);
                 if (!kidobj)
                     return JS_FALSE;
                 obj = kidobj;
-                xml = (JSXML *) JS_GetPrivate(cx, obj);
+                xml = (JSXML *) obj->getAssignedPrivate();
                 goto again;
             }
         }
         /* FALL THROUGH */
       default:
         *vp = JSVAL_FALSE;
         for (i = 0, n = xml->xml_kids.length; i < n; i++) {
             kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
@@ -6165,17 +6157,17 @@ xml_insertChildAfter(JSContext *cx, uint
 
     arg = vp[2];
     if (JSVAL_IS_NULL(arg)) {
         kid = NULL;
         i = 0;
     } else {
         if (!VALUE_IS_XML(cx, arg))
             return JS_TRUE;
-        kid = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(arg));
+        kid = (JSXML *) JSVAL_TO_OBJECT(arg)->getAssignedPrivate();
         i = XMLARRAY_FIND_MEMBER(&xml->xml_kids, kid, NULL);
         if (i == XML_NOT_FOUND)
             return JS_TRUE;
         ++i;
     }
 
     xml = CHECK_COPY_ON_WRITE(cx, xml, obj);
     if (!xml)
@@ -6197,17 +6189,17 @@ xml_insertChildBefore(JSContext *cx, uin
 
     arg = vp[2];
     if (JSVAL_IS_NULL(arg)) {
         kid = NULL;
         i = xml->xml_kids.length;
     } else {
         if (!VALUE_IS_XML(cx, arg))
             return JS_TRUE;
-        kid = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(arg));
+        kid = (JSXML *) JSVAL_TO_OBJECT(arg)->getAssignedPrivate();
         i = XMLARRAY_FIND_MEMBER(&xml->xml_kids, kid, NULL);
         if (i == XML_NOT_FOUND)
             return JS_TRUE;
     }
 
     xml = CHECK_COPY_ON_WRITE(cx, xml, obj);
     if (!xml)
         return JS_FALSE;
@@ -6516,17 +6508,17 @@ xml_processingInstructions_helper(JSCont
                                                            nameqn, &v);
                 } else {
                     ok = JS_FALSE;
                     v = JSVAL_NULL;
                 }
                 js_LeaveLocalRootScopeWithResult(cx, v);
                 if (!ok)
                     break;
-                vxml = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(v));
+                vxml = (JSXML *) JSVAL_TO_OBJECT(v)->getAssignedPrivate();
                 if (JSXML_LENGTH(vxml) != 0) {
                     ok = Append(cx, list, vxml);
                     if (!ok)
                         break;
                 }
             }
         }
         XMLArrayCursorFinish(&cursor);
@@ -6691,17 +6683,17 @@ xml_replace(JSContext *cx, uintN argc, j
         goto done;
 
     if (argc <= 1) {
         value = STRING_TO_JSVAL(ATOM_TO_STRING(cx->runtime->atomState.
                                                typeAtoms[JSTYPE_VOID]));
     } else {
         value = vp[3];
         vxml = VALUE_IS_XML(cx, value)
-               ? (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(value))
+               ? (JSXML *) JSVAL_TO_OBJECT(value)->getAssignedPrivate()
                : NULL;
         if (!vxml) {
             if (!JS_ConvertValue(cx, value, JSTYPE_STRING, &vp[3]))
                 return JS_FALSE;
             value = vp[3];
         } else {
             vxml = DeepCopy(cx, vxml, NULL, 0);
             if (!vxml)
@@ -6986,17 +6978,17 @@ xml_text_helper(JSContext *cx, JSObject 
                     ok = xml_text_helper(cx, kidobj, kid, &v);
                 } else {
                     ok = JS_FALSE;
                     v = JSVAL_NULL;
                 }
                 js_LeaveLocalRootScopeWithResult(cx, v);
                 if (!ok)
                     return JS_FALSE;
-                vxml = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(v));
+                vxml = (JSXML *) JSVAL_TO_OBJECT(v)->getAssignedPrivate();
                 if (JSXML_LENGTH(vxml) != 0 && !Append(cx, list, vxml))
                     return JS_FALSE;
             }
         }
     } else {
         for (i = 0, n = JSXML_LENGTH(xml); i < n; i++) {
             kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
             if (kid && kid->xml_class == JSXML_CLASS_TEXT) {
@@ -7259,17 +7251,17 @@ XML(JSContext *cx, JSObject *obj, uintN 
     v = argv[0];
     if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v))
         v = STRING_TO_JSVAL(cx->runtime->emptyString);
 
     xobj = ToXML(cx, v);
     if (!xobj)
         return JS_FALSE;
     *rval = OBJECT_TO_JSVAL(xobj);
-    xml = (JSXML *) JS_GetPrivate(cx, xobj);
+    xml = (JSXML *) xobj->getAssignedPrivate();
 
     if (JS_IsConstructing(cx) && !JSVAL_IS_PRIMITIVE(v)) {
         vobj = JSVAL_TO_OBJECT(v);
         clasp = OBJ_GET_CLASS(cx, vobj);
         if (clasp == &js_XMLClass ||
             (clasp->flags & JSCLASS_DOCUMENT_OBSERVER)) {
             /* No need to lock obj, it's newly constructed and thread local. */
             copy = DeepCopy(cx, xml, obj, 0);
@@ -7292,24 +7284,24 @@ XMLList(JSContext *cx, JSObject *obj, ui
 
     v = argv[0];
     if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v))
         v = STRING_TO_JSVAL(cx->runtime->emptyString);
 
     if (JS_IsConstructing(cx) && !JSVAL_IS_PRIMITIVE(v)) {
         vobj = JSVAL_TO_OBJECT(v);
         if (OBJECT_IS_XML(cx, vobj)) {
-            xml = (JSXML *) JS_GetPrivate(cx, vobj);
+            xml = (JSXML *) vobj->getAssignedPrivate();
             if (xml->xml_class == JSXML_CLASS_LIST) {
                 listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST);
                 if (!listobj)
                     return JS_FALSE;
                 *rval = OBJECT_TO_JSVAL(listobj);
 
-                list = (JSXML *) JS_GetPrivate(cx, listobj);
+                list = (JSXML *) listobj->getAssignedPrivate();
                 if (!Append(cx, list, xml))
                     return JS_FALSE;
                 return JS_TRUE;
             }
         }
     }
 
     /* Toggle on XML support since the script has explicitly requested it. */
@@ -7465,32 +7457,31 @@ js_NewXMLObject(JSContext *cx, JSXMLClas
 }
 
 static JSObject *
 NewXMLObject(JSContext *cx, JSXML *xml)
 {
     JSObject *obj;
 
     obj = js_NewObject(cx, &js_XMLClass, NULL, NULL);
-    if (!obj || !JS_SetPrivate(cx, obj, xml)) {
-        cx->weakRoots.newborn[GCX_OBJECT] = NULL;
+    if (!obj)
         return NULL;
-    }
+    obj->setPrivate(xml);
     METER(xml_stats.xmlobj);
     return obj;
 }
 
 JSObject *
 js_GetXMLObject(JSContext *cx, JSXML *xml)
 {
     JSObject *obj;
 
     obj = xml->object;
     if (obj) {
-        JS_ASSERT(JS_GetPrivate(cx, obj) == xml);
+        JS_ASSERT(obj->getAssignedPrivate() == xml);
         return obj;
     }
 
     /*
      * A JSXML cannot be shared among threads unless it has an object.
      * A JSXML cannot be given an object unless:
      * (a) it has no parent; or
      * (b) its parent has no object (therefore is thread-private); or
@@ -7557,18 +7548,19 @@ js_InitXMLClass(JSContext *cx, JSObject 
     /* Define the XML class constructor and prototype. */
     proto = JS_InitClass(cx, obj, NULL, &js_XMLClass, XML, 1,
                          NULL, xml_methods,
                          xml_static_props, xml_static_methods);
     if (!proto)
         return NULL;
 
     xml = js_NewXML(cx, JSXML_CLASS_TEXT);
-    if (!xml || !JS_SetPrivate(cx, proto, xml))
+    if (!xml)
         return NULL;
+    proto->setPrivate(xml);
     xml->object = proto;
     METER(xml_stats.xmlobj);
 
     /*
      * Prepare to set default settings on the XML constructor we just made.
      * NB: We can't use JS_GetConstructor, because it calls OBJ_GET_PROPERTY,
      * which is xml_getProperty, which creates a new XMLList every time!  We
      * must instead call js_LookupProperty directly.
@@ -7950,17 +7942,17 @@ js_FindXMLProperty(JSContext *cx, jsval 
              proto = OBJ_GET_PROTO(cx, target);
              if (!proto)
                  break;
              target = proto;
         }
 
         if (OBJECT_IS_XML(cx, target)) {
             if (funid == 0) {
-                xml = (JSXML *) JS_GetPrivate(cx, target);
+                xml = (JSXML *) target->getAssignedPrivate();
                 found = HasNamedProperty(xml, qn);
             } else {
                 if (!HasFunctionProperty(cx, target, funid, &found))
                     return JS_FALSE;
             }
             if (found) {
                 *idp = OBJECT_TO_JSID(nameobj);
                 *objp = target;
@@ -8014,17 +8006,17 @@ GetXMLFunction(JSContext *cx, JSObject *
             goto out;
         }
         target = OBJ_GET_PROTO(cx, target);
         if (target == NULL)
             break;
         tvr.u.object = target;
     }
 
-    xml = (JSXML *) JS_GetPrivate(cx, obj);
+    xml = (JSXML *) obj->getAssignedPrivate();
     if (HasSimpleContent(xml)) {
         /* Search in String.prototype to implement 11.2.2.1 Step 3(f). */
         ok = js_GetClassPrototype(cx, NULL, INT_TO_JSID(JSProto_String),
                                   &tvr.u.object);
         if (!ok)
             goto out;
         JS_ASSERT(tvr.u.object);
         ok = OBJ_GET_PROPERTY(cx, tvr.u.object, id, vp);
@@ -8066,17 +8058,17 @@ js_GetXMLDescendants(JSContext *cx, JSOb
 }
 
 JSBool
 js_DeleteXMLListElements(JSContext *cx, JSObject *listobj)
 {
     JSXML *list;
     uint32 n;
 
-    list = (JSXML *) JS_GetPrivate(cx, listobj);
+    list = (JSXML *) listobj->getAssignedPrivate();
     for (n = list->xml_kids.length; n != 0; --n)
         DeleteListElement(cx, list, 0);
 
     return JS_TRUE;
 }
 
 typedef struct JSXMLFilter {
     JSXML               *list;
@@ -8084,19 +8076,17 @@ typedef struct JSXMLFilter {
     JSXML               *kid;
     JSXMLArrayCursor    cursor;
 
 } JSXMLFilter;
 
 static void
 xmlfilter_trace(JSTracer *trc, JSObject *obj)
 {
-    JSXMLFilter *filter;
-
-    filter = (JSXMLFilter *) JS_GetPrivate(trc->context, obj);
+    JSXMLFilter *filter = (JSXMLFilter *) obj->getPrivate();
     if (!filter)
         return;
 
     JS_ASSERT(filter->list);
     JS_CALL_TRACER(trc, filter->list, JSTRACE_XML, "list");
     if (filter->result)
         JS_CALL_TRACER(trc, filter->result, JSTRACE_XML, "result");
     if (filter->kid)
@@ -8106,19 +8096,17 @@ xmlfilter_trace(JSTracer *trc, JSObject 
      * We do not need to trace the cursor as that would be done when
      * tracing the filter->list.
      */
 }
 
 static void
 xmlfilter_finalize(JSContext *cx, JSObject *obj)
 {
-    JSXMLFilter *filter;
-
-    filter = (JSXMLFilter *) JS_GetPrivate(cx, obj);
+    JSXMLFilter *filter = (JSXMLFilter *) obj->getPrivate();
     if (!filter)
         return;
 
     XMLArrayCursorFinish(&filter->cursor);
     cx->free(filter);
 }
 
 JSClass js_XMLFilterClass = {
@@ -8144,69 +8132,69 @@ js_StepXMLListFilter(JSContext *cx, JSBo
          * We haven't iterated yet, so initialize the filter based on the
          * value stored in sp[-2].
          */
         if (!VALUE_IS_XML(cx, sp[-2])) {
             js_ReportValueError(cx, JSMSG_NON_XML_FILTER, -2, sp[-2], NULL);
             return JS_FALSE;
         }
         obj = JSVAL_TO_OBJECT(sp[-2]);
-        xml = (JSXML *) JS_GetPrivate(cx, obj);
+        xml = (JSXML *) obj->getAssignedPrivate();
 
         if (xml->xml_class == JSXML_CLASS_LIST) {
             list = xml;
         } else {
             obj = js_NewXMLObject(cx, JSXML_CLASS_LIST);
             if (!obj)
                 return JS_FALSE;
 
             /*
              * Root just-created obj. sp[-2] cannot be used yet for rooting
              * as it may be the only root holding xml.
              */
             sp[-1] = OBJECT_TO_JSVAL(obj);
-            list = (JSXML *) JS_GetPrivate(cx, obj);
+            list = (JSXML *) obj->getAssignedPrivate();
             if (!Append(cx, list, xml))
                 return JS_FALSE;
         }
 
         filterobj = js_NewObjectWithGivenProto(cx, &js_XMLFilterClass,
                                                NULL, NULL);
         if (!filterobj)
             return JS_FALSE;
 
         filter = (JSXMLFilter *) cx->malloc(sizeof *filter);
         if (!filter)
             return JS_FALSE;
 
         /*
-         * Init all filter fields before JS_SetPrivate exposes it to
+         * Init all filter fields before setPrivate exposes it to
          * xmlfilter_trace or xmlfilter_finalize.
          */
         filter->list = list;
         filter->result = NULL;
         filter->kid = NULL;
         XMLArrayCursorInit(&filter->cursor, &list->xml_kids);
-        JS_SetPrivate(cx, filterobj, filter);
+        filterobj->setPrivate(filter);
 
         /* Store filterobj to use in the later iterations. */
         sp[-2] = OBJECT_TO_JSVAL(filterobj);
 
         resobj = js_NewXMLObject(cx, JSXML_CLASS_LIST);
         if (!resobj)
             return JS_FALSE;
 
         /* This also roots resobj. */
-        filter->result = (JSXML *) JS_GetPrivate(cx, resobj);
+        filter->result = (JSXML *) resobj->getAssignedPrivate();
     } else {
         /* We have iterated at least once. */
         JS_ASSERT(!JSVAL_IS_PRIMITIVE(sp[-2]));
         JS_ASSERT(OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(sp[-2])) ==
                                 &js_XMLFilterClass);
-        filter = (JSXMLFilter *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(sp[-2]));
+        filter = (JSXMLFilter *) JSVAL_TO_OBJECT(sp[-2])->getAssignedPrivate();
         JS_ASSERT(filter->kid);
 
         /* Check if the filter expression wants to append the element. */
         if (js_ValueToBoolean(sp[-1]) &&
             !Append(cx, filter->result, filter->kid)) {
             return JS_FALSE;
         }
     }
@@ -8248,17 +8236,17 @@ js_ValueToXMLListObject(JSContext *cx, j
 JSObject *
 js_CloneXMLObject(JSContext *cx, JSObject *obj)
 {
     uintN flags;
     JSXML *xml;
 
     if (!GetXMLSettingFlags(cx, &flags))
         return NULL;
-    xml = (JSXML *) JS_GetPrivate(cx, obj);
+    xml = (JSXML *) obj->getAssignedPrivate();
     if (flags & (XSF_IGNORE_COMMENTS |
                  XSF_IGNORE_PROCESSING_INSTRUCTIONS |
                  XSF_IGNORE_WHITESPACE)) {
         xml = DeepCopy(cx, xml, NULL, flags);
         if (!xml)
             return NULL;
         return xml->object;
     }
@@ -8282,17 +8270,17 @@ js_NewXMLSpecialObject(JSContext *cx, JS
         (xml_class == JSXML_CLASS_PROCESSING_INSTRUCTION &&
          (flags & XSF_IGNORE_PROCESSING_INSTRUCTIONS))) {
         return js_NewXMLObject(cx, JSXML_CLASS_TEXT);
     }
 
     obj = js_NewXMLObject(cx, xml_class);
     if (!obj)
         return NULL;
-    xml = (JSXML *) JS_GetPrivate(cx, obj);
+    xml = (JSXML *) obj->getAssignedPrivate();
     if (name) {
         qn = NewXMLQName(cx, cx->runtime->emptyString, NULL, name);
         if (!qn)
             return NULL;
         xml->name = qn;
     }
     xml->xml_value = value;
     return obj;
--- a/js/src/xpconnect/src/xpcprivate.h
+++ b/js/src/xpconnect/src/xpcprivate.h
@@ -4084,23 +4084,17 @@ NS_DEFINE_STATIC_IID_ACCESSOR(PrincipalH
 #endif /* !XPCONNECT_STANDALONE */
 
 /***************************************************************************/
 // Utilities
 
 inline void *
 xpc_GetJSPrivate(JSObject *obj)
 {
-    jsval v;
-
-    JS_ASSERT(STOBJ_GET_CLASS(obj)->flags & JSCLASS_HAS_PRIVATE);
-    v = obj->fslots[JSSLOT_PRIVATE];
-    if (!JSVAL_IS_INT(v))
-        return NULL;
-    return JSVAL_TO_PRIVATE(v);
+    return obj->getPrivate();
 }
 
 #ifndef XPCONNECT_STANDALONE
 
 // Helper for creating a sandbox object to use for evaluating
 // untrusted code completely separated from all other code in the
 // system using xpc_EvalInSandbox(). Takes the JSContext on which to
 // do setup etc on, puts the sandbox object in *vp (which must be
--- a/js/src/xpconnect/src/xpcquickstubs.cpp
+++ b/js/src/xpconnect/src/xpcquickstubs.cpp
@@ -510,17 +510,17 @@ GetMemberInfo(JSObject *obj,
                  "obj must be a wrapper");
     XPCWrappedNativeProto *proto;
     if(IS_SLIM_WRAPPER(obj))
     {
         proto = GetSlimWrapperProto(obj);
     }
     else
     {
-        XPCWrappedNative *wrapper = (XPCWrappedNative *) STOBJ_GET_PRIVATE(obj);
+        XPCWrappedNative *wrapper = (XPCWrappedNative *) obj->getAssignedPrivate();
         proto = wrapper->GetProto();
     }
     if(proto)
     {
         XPCNativeSet *set = proto->GetSet();
         if(set)
         {
             XPCNativeMember *member;