Bug 377751: JSClass instances in xpconnect use the tracing API. r=brendan, sr=jst
authorigor@mir2.org
Tue, 01 May 2007 14:06:07 -0700
changeset 974 1fdb587b35d96d30d2818f483ff1915fec728645
parent 973 6f8b6e5b16e9284992346a3954599ad6411acaf9
child 975 d322074cda72f1485f4e1bd55d9985c5dede7052
push idunknown
push userunknown
push dateunknown
reviewersbrendan, jst
bugs377751
milestone1.9a5pre
Bug 377751: JSClass instances in xpconnect use the tracing API. r=brendan, sr=jst
dom/src/base/nsDOMClassInfo.cpp
js/src/xpconnect/idl/nsIXPCScriptable.idl
js/src/xpconnect/idl/nsIXPConnect.idl
js/src/xpconnect/public/xpc_map_end.h
js/src/xpconnect/src/XPCDispInlines.h
js/src/xpconnect/src/XPCDispParamPropJSClass.cpp
js/src/xpconnect/src/XPCDispPrivate.h
js/src/xpconnect/src/XPCDispTypeInfo.cpp
js/src/xpconnect/src/XPCNativeWrapper.cpp
js/src/xpconnect/src/xpcjsruntime.cpp
js/src/xpconnect/src/xpcprivate.h
js/src/xpconnect/src/xpcthreadcontext.cpp
js/src/xpconnect/src/xpcwrappednative.cpp
js/src/xpconnect/src/xpcwrappednativejsops.cpp
js/src/xpconnect/src/xpcwrappednativescope.cpp
storage/src/mozStorageStatementWrapper.cpp
--- a/dom/src/base/nsDOMClassInfo.cpp
+++ b/dom/src/base/nsDOMClassInfo.cpp
@@ -3677,20 +3677,20 @@ nsDOMClassInfo::HasInstance(nsIXPConnect
                             PRBool *_retval)
 {
   NS_WARNING("nsDOMClassInfo::HasInstance Don't call me!");
 
   return NS_ERROR_UNEXPECTED;
 }
 
 NS_IMETHODIMP
-nsDOMClassInfo::Mark(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                     JSObject *obj, void *arg, PRUint32 *_retval)
-{
-  NS_WARNING("nsDOMClassInfo::Mark Don't call me!");
+nsDOMClassInfo::Trace(nsIXPConnectWrappedNative *wrapper, JSTracer *trc,
+                      JSObject *obj)
+{
+  NS_WARNING("nsDOMClassInfo::Trace Don't call me!");
 
   return NS_ERROR_UNEXPECTED;
 }
 
 NS_IMETHODIMP
 nsDOMClassInfo::Equality(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
                          JSObject * obj, jsval val, PRBool *bp)
 {
--- a/js/src/xpconnect/idl/nsIXPCScriptable.idl
+++ b/js/src/xpconnect/idl/nsIXPCScriptable.idl
@@ -48,17 +48,17 @@
 
 /**
  * Note: This is not really an XPCOM interface.  For example, callers must
  * guarantee that they set the *_retval of the various methods that return a
  * boolean to PR_TRUE before making the call.  Implementations may skip writing
  * to *_retval unless they want to return PR_FALSE.
  */
 
-[uuid(9cc0c2e0-f769-4f14-8cd6-2d2d40466f6c)]
+[uuid(1455f6fe-6de9-4b62-a2b3-d1aee82dd829)]
 interface nsIXPCScriptable : nsISupports
 {
     /* bitflags used for 'flags' (only 32 bits available!) */
 
     const PRUint32 WANT_PRECREATE                   = 1 <<  0;
     const PRUint32 WANT_CREATE                      = 1 <<  1;
     const PRUint32 WANT_POSTCREATE                  = 1 <<  2;
     const PRUint32 WANT_ADDPROPERTY                 = 1 <<  3;
@@ -69,17 +69,17 @@ interface nsIXPCScriptable : nsISupports
     const PRUint32 WANT_NEWENUMERATE                = 1 <<  8;
     const PRUint32 WANT_NEWRESOLVE                  = 1 <<  9;
     const PRUint32 WANT_CONVERT                     = 1 << 10;
     const PRUint32 WANT_FINALIZE                    = 1 << 11;
     const PRUint32 WANT_CHECKACCESS                 = 1 << 12;
     const PRUint32 WANT_CALL                        = 1 << 13;
     const PRUint32 WANT_CONSTRUCT                   = 1 << 14;
     const PRUint32 WANT_HASINSTANCE                 = 1 << 15;
-    const PRUint32 WANT_MARK                        = 1 << 16;
+    const PRUint32 WANT_TRACE                       = 1 << 16;
     const PRUint32 USE_JSSTUB_FOR_ADDPROPERTY       = 1 << 17;
     const PRUint32 USE_JSSTUB_FOR_DELPROPERTY       = 1 << 18;
     const PRUint32 USE_JSSTUB_FOR_SETPROPERTY       = 1 << 19;
     const PRUint32 DONT_ENUM_STATIC_PROPS           = 1 << 20;
     const PRUint32 DONT_ENUM_QUERY_INTERFACE        = 1 << 21;
     const PRUint32 DONT_ASK_INSTANCE_FOR_SCRIPTABLE = 1 << 22;
     const PRUint32 CLASSINFO_INTERFACES_ONLY        = 1 << 23;
     const PRUint32 ALLOW_PROP_MODS_DURING_RESOLVE   = 1 << 24;
@@ -156,18 +156,18 @@ interface nsIXPCScriptable : nsISupports
     PRBool construct(in nsIXPConnectWrappedNative wrapper,
                      in JSContextPtr cx, in JSObjectPtr obj,
                      in PRUint32 argc, in JSValPtr argv, in JSValPtr vp);
 
     PRBool hasInstance(in nsIXPConnectWrappedNative wrapper,
                        in JSContextPtr cx, in JSObjectPtr obj,
                        in JSVal val, out PRBool bp);
 
-    PRUint32 mark(in nsIXPConnectWrappedNative wrapper,
-                  in JSContextPtr cx, in JSObjectPtr obj, in voidPtr arg);
+    void trace(in nsIXPConnectWrappedNative wrapper,
+               in JSTracerPtr trc, in JSObjectPtr obj);
 
     PRBool equality(in nsIXPConnectWrappedNative wrapper,
                     in JSContextPtr cx, in JSObjectPtr obj, in JSVal val);
 
     JSObjectPtr outerObject(in nsIXPConnectWrappedNative wrapper,
                             in JSContextPtr cx, in JSObjectPtr obj);
 
     JSObjectPtr innerObject(in nsIXPConnectWrappedNative wrapper,
--- a/js/src/xpconnect/idl/nsIXPConnect.idl
+++ b/js/src/xpconnect/idl/nsIXPConnect.idl
@@ -59,16 +59,17 @@
 /***************************************************************************/
 
 [ptr] native JSContextPtr(JSContext);
 [ptr] native JSObjectPtr(JSObject);
 [ptr] native JSValPtr(jsval);
       native JSVal(jsval);
       native JSID(jsid);
 [ptr] native voidPtrPtr(void*);
+[ptr] native JSTracerPtr(JSTracer);
 
 /***************************************************************************/
 
 %{ C++
 /***************************************************************************/
 #define GENERATE_XPC_FAILURE(x) \
             (NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XPCONNECT,x))
 
--- a/js/src/xpconnect/public/xpc_map_end.h
+++ b/js/src/xpconnect/public/xpc_map_end.h
@@ -104,18 +104,18 @@ NS_IMETHODIMP XPC_MAP_CLASSNAME::GetScri
     nsIXPCScriptable::WANT_CALL |
 #endif
 #ifdef XPC_MAP_WANT_CONSTRUCT
     nsIXPCScriptable::WANT_CONSTRUCT |
 #endif
 #ifdef XPC_MAP_WANT_HASINSTANCE
     nsIXPCScriptable::WANT_HASINSTANCE |
 #endif
-#ifdef XPC_MAP_WANT_MARK
-    nsIXPCScriptable::WANT_MARK |
+#ifdef XPC_MAP_WANT_TRACE
+    nsIXPCScriptable::WANT_TRACE |
 #endif
 #ifdef XPC_MAP_WANT_EQUALITY
     nsIXPCScriptable::WANT_EQUALITY |
 #endif
 #ifdef XPC_MAP_WANT_OUTER_OBJECT
     nsIXPCScriptable::WANT_OUTER_OBJECT |
 #endif
 #ifdef XPC_MAP_WANT_INNER_OBJECT
@@ -207,18 +207,18 @@ NS_IMETHODIMP XPC_MAP_CLASSNAME::Constru
     {NS_ERROR("never called"); return NS_ERROR_NOT_IMPLEMENTED;}
 #endif
 
 #ifndef XPC_MAP_WANT_HASINSTANCE
 NS_IMETHODIMP XPC_MAP_CLASSNAME::HasInstance(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj, jsval val, PRBool *bp, PRBool *_retval)
     {NS_ERROR("never called"); return NS_ERROR_NOT_IMPLEMENTED;}
 #endif
 
-#ifndef XPC_MAP_WANT_MARK
-NS_IMETHODIMP XPC_MAP_CLASSNAME::Mark(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj, void * arg, PRUint32 *_retval)
+#ifndef XPC_MAP_WANT_TRACE
+NS_IMETHODIMP XPC_MAP_CLASSNAME::Trace(nsIXPConnectWrappedNative *wrapper, JSTracer *trc, JSObject * obj)
     {NS_ERROR("never called"); return NS_ERROR_NOT_IMPLEMENTED;}
 #endif
 
 #ifndef XPC_MAP_WANT_EQUALITY
 NS_IMETHODIMP XPC_MAP_CLASSNAME::Equality(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj, jsval val, PRBool *bp)
     {NS_ERROR("never called"); return NS_ERROR_NOT_IMPLEMENTED;}
 #endif
 
@@ -296,18 +296,18 @@ NS_IMETHODIMP XPC_MAP_CLASSNAME::InnerOb
 #ifdef XPC_MAP_WANT_CONSTRUCT
 #undef XPC_MAP_WANT_CONSTRUCT
 #endif
 
 #ifdef XPC_MAP_WANT_HASINSTANCE
 #undef XPC_MAP_WANT_HASINSTANCE
 #endif
 
-#ifdef XPC_MAP_WANT_MARK
-#undef XPC_MAP_WANT_MARK
+#ifdef XPC_MAP_WANT_TRACE
+#undef XPC_MAP_WANT_TRACE
 #endif
 
 #ifdef XPC_MAP_WANT_EQUALITY
 #undef XPC_MAP_WANT_EQUALITY
 #endif
 
 #ifdef XPC_MAP_WANT_OUTER_OBJECT
 #undef XPC_MAP_WANT_OUTER_OBJECT
--- a/js/src/xpconnect/src/XPCDispInlines.h
+++ b/js/src/xpconnect/src/XPCDispInlines.h
@@ -458,17 +458,17 @@ void XPCDispIDArray::Unmark()
 inline
 JSBool XPCDispIDArray::IsMarked() const
 {
     return mMarked;
 }
 
     // NOP. This is just here to make the AutoMarkingPtr code compile.
 inline
-void XPCDispIDArray::MarkBeforeJSFinalize(JSContext*) 
+void XPCDispIDArray::TraceJS(JSTracer* trc)
 {
 }
 
 //=============================================================================
 // XPCDispTypeInfo inlines
 
 inline
 FUNCDESC* XPCDispTypeInfo::FuncDescArray::Get(PRUint32 index) 
--- a/js/src/xpconnect/src/XPCDispParamPropJSClass.cpp
+++ b/js/src/xpconnect/src/XPCDispParamPropJSClass.cpp
@@ -129,42 +129,39 @@ XPC_PP_SetProperty(JSContext *cx, JSObje
  */
 JS_STATIC_DLL_CALLBACK(void)
 XPC_PP_Finalize(JSContext *cx, JSObject *obj)
 {
     delete GetParamProp(cx, obj);
 }
 
 /**
- * Is called to mark during GC
- * @param cx the JS context
+ * Is called to trace things that the object holds.
+ * @param trc the tracing structure
  * @param obj the object being marked
- * @param arg we just pass this on
- * @return 0
  */
-JS_STATIC_DLL_CALLBACK(uint32)
-XPC_PP_Mark(JSContext *cx, JSObject *obj, void *arg)
+JS_STATIC_DLL_CALLBACK(void)
+XPC_PP_Trace(JSTracer *trc, JSObject *obj)
 {
-    XPCDispParamPropJSClass* paramProp = GetParamProp(cx, obj);
+    XPCDispParamPropJSClass* paramProp = GetParamProp(trc->context, obj);
     if(paramProp)
     {
         XPCWrappedNative* wrapper = paramProp->GetWrapper();
         if(wrapper && wrapper->IsValid())
-            xpc_MarkForValidWrapper(cx, wrapper, arg);
+            xpc_TraceForValidWrapper(trc, wrapper);
     }
-    return 0;
 }
 
 /**
  * Our JSClass used by XPCDispParamPropClass
  * @see XPCDispParamPropClass
  */
 static JSClass ParamPropClass = {
     "XPCDispParamPropJSCass",   // Name 
-    JSCLASS_HAS_PRIVATE,        // flags  
+    JSCLASS_HAS_PRIVATE | JSCLASS_MARK_IS_TRACE, // flags
 
     /* Mandatory non-null function pointer members. */
     JS_PropertyStub,            // addProperty
     JS_PropertyStub,            // delProperty
     XPC_PP_GetProperty,         // getProperty
     XPC_PP_SetProperty,         // setProperty
     JS_EnumerateStub,           // enumerate
     JS_ResolveStub,             // resolve
@@ -173,17 +170,17 @@ static JSClass ParamPropClass = {
 
     /* Optionally non-null members start here. */
     nsnull,                     // getObjectOps;
     nsnull,                     // checkAccess;
     nsnull,                     // call;
     nsnull,                     // construct;
     nsnull,                     // xdrObject;
     nsnull,                     // hasInstance;
-    XPC_PP_Mark,                // mark;
+    JS_CLASS_TRACE(XPC_PP_Trace), // mark/trace;
     nsnull                      // spare;
 };
 
 // static
 JSBool XPCDispParamPropJSClass::NewInstance(XPCCallContext& ccx,
                                              XPCWrappedNative* wrapper, 
                                              PRUint32 dispID, 
                                              XPCDispParams* dispParams, 
--- a/js/src/xpconnect/src/XPCDispPrivate.h
+++ b/js/src/xpconnect/src/XPCDispPrivate.h
@@ -287,46 +287,45 @@ class XPCDispIDArray
 {
 public:
     /**
      * Initializes the array from the JSIdArray passed in
      * @param ccx XPConnect call context
      * @param array a JS array of ID's
      */
     XPCDispIDArray(XPCCallContext& ccx, JSIdArray* array);
+
     /**
      * Returns the length of the array
      * @return length of the array
      */
     PRUint32 Length() const;
+
     /**
      * Returns an ID within the array
      * @param cx a JS context
      * @param index index into the array
      * @return the ID as a jsval
      */
     jsval Item(JSContext* cx, PRUint32 index) const;
 
     /**
-     * Called to mark the ID's during GC
+     * Called to trace jsval associated with the ID's
      */
-    void Mark();
+    void TraceJS(JSTracer* trc);
+
     /**
-     * Called to unmark the ID's after GC has been done
+     * Called to unmark the ID's marked during GC marking trace
      */
     void Unmark();
+
     /**
      * Tests whether the ID is marked
      */
     JSBool IsMarked() const;
-
-    /**
-     * NOP. This is just here to make the AutoMarkingPtr code compile.
-     */
-    inline void MarkBeforeJSFinalize(JSContext*);
 private:
     JSBool mMarked;
     nsVoidArray mIDArray;
 };
 
 /**
  * Implements ITypeInfo interface for JSObjects
  */
--- a/js/src/xpconnect/src/XPCDispTypeInfo.cpp
+++ b/js/src/xpconnect/src/XPCDispTypeInfo.cpp
@@ -439,37 +439,33 @@ XPCDispIDArray::XPCDispIDArray(XPCCallCo
     for(jsint index = 0; index < array->length; ++index)
     {
         mIDArray.ReplaceElementAt(NS_REINTERPRET_CAST(void*,
                                                       array->vector[index]), 
                                   index);
     }   
 }
 
-void XPCDispIDArray::Mark()
+void XPCDispIDArray::TraceJS(JSTracer* trc)
 {
     // If already marked nothing to do
-    if(IsMarked())
-        return;
-    mMarked = JS_TRUE;
-    XPCCallContext ccx(NATIVE_CALLER);
-    // Bail if our call context is bad
-    if(!ccx.IsValid())
-        return;
+    if(JS_IsGCMarkingTracer(trc))
+    {
+        if (IsMarked())
+            return;
+        mMarked = JS_TRUE;
+    }
 
     PRInt32 count = Length();
     jsval val;
-    JSContext* cx = ccx;
+
     // Iterate each of the ID's and mark them
     for(PRInt32 index = 0; index < count; ++index)
     {
-        if(JS_IdToValue(cx,
-                        NS_REINTERPRET_CAST(jsid,
-                                            mIDArray.ElementAt(index)),
-                        &val) &&
-            JSVAL_IS_GCTHING(val))
+        if(JS_IdToValue(trc->context,
+                        NS_REINTERPRET_CAST(jsid, mIDArray.ElementAt(index)),
+                        &val))
         {
-            JS_MarkGCThing(cx, NS_REINTERPRET_CAST(void*,val),
-                           nsnull, nsnull);
+            JS_CALL_VALUE_TRACER(trc, val, "disp_id_array_element");
         }
     }
 }
 
--- a/js/src/xpconnect/src/XPCNativeWrapper.cpp
+++ b/js/src/xpconnect/src/XPCNativeWrapper.cpp
@@ -77,18 +77,18 @@ XPC_NW_Call(JSContext *cx, JSObject *obj
 
 JS_STATIC_DLL_CALLBACK(JSBool)
 XPC_NW_Construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
                  jsval *rval);
 
 JS_STATIC_DLL_CALLBACK(JSBool)
 XPC_NW_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
 
-JS_STATIC_DLL_CALLBACK(uint32)
-XPC_NW_Mark(JSContext *cx, JSObject *obj, void *arg);
+JS_STATIC_DLL_CALLBACK(void)
+XPC_NW_Trace(JSTracer *trc, JSObject *obj);
 
 JS_STATIC_DLL_CALLBACK(JSBool)
 XPC_NW_Equality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
 
 static JSBool
 RewrapIfDeepWrapper(JSContext *cx, JSObject *obj, jsval v, jsval *rval);
 
 JS_STATIC_DLL_CALLBACK(JSBool)
@@ -99,25 +99,25 @@ XPC_NW_FunctionWrapper(JSContext *cx, JS
 // for XPCNativeWrapper for the moment too...)
 
 JSExtendedClass XPCNativeWrapper::sXPC_NW_JSClass = {
   // JSClass (JSExtendedClass.base) initialization
   { "XPCNativeWrapper",
     JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS |
     // Our one reserved slot holds a jsint of flag bits
     JSCLASS_NEW_RESOLVE | JSCLASS_HAS_RESERVED_SLOTS(1) |
-    JSCLASS_IS_EXTENDED,
+    JSCLASS_MARK_IS_TRACE | JSCLASS_IS_EXTENDED,
     XPC_NW_AddProperty, XPC_NW_DelProperty,
     XPC_NW_GetProperty, XPC_NW_SetProperty,
     XPC_NW_Enumerate,   (JSResolveOp)XPC_NW_NewResolve,
     XPC_NW_Convert,     XPC_NW_Finalize,
     nsnull,             XPC_NW_CheckAccess,
     XPC_NW_Call,        XPC_NW_Construct,
     nsnull,             XPC_NW_HasInstance,
-    XPC_NW_Mark,        nsnull
+    JS_CLASS_TRACE(XPC_NW_Trace), nsnull
   },
   // JSExtendedClass initialization
   XPC_NW_Equality
 };
 
 #define FLAG_DEEP     0x1
 #define FLAG_EXPLICIT 0x2
 // FLAG_RESOLVING is used to tag an XPCNativeWrapper when while it's calling
@@ -1180,28 +1180,26 @@ XPCNativeWrapperCtor(JSContext *cx, JSOb
     // scoped lock
     XPCAutoLock lock(rt->GetMapLock());
     rt->GetExplicitNativeWrapperMap()->Add(wrapperObj);
   }
 
   return JS_TRUE;
 }
 
-JS_STATIC_DLL_CALLBACK(uint32)
-XPC_NW_Mark(JSContext *cx, JSObject *obj, void *arg)
+JS_STATIC_DLL_CALLBACK(void)
+XPC_NW_Trace(JSTracer *trc, JSObject *obj)
 {
   XPCWrappedNative *wrappedNative =
-    XPCNativeWrapper::GetWrappedNative(cx, obj);
+    XPCNativeWrapper::GetWrappedNative(trc->context, obj);
 
   if (wrappedNative && wrappedNative->IsValid()) {
-    ::JS_MarkGCThing(cx, wrappedNative->GetFlatJSObject(),
-                     "XPCNativeWrapper wrapped native", arg);
+    JS_CALL_OBJECT_TRACER(trc, wrappedNative->GetFlatJSObject(),
+                          "wrappedNative.flatJSObject");
   }
-
-  return 0;
 }
 
 JS_STATIC_DLL_CALLBACK(JSBool)
 XPC_NW_Equality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
 {
   NS_ASSERTION(XPCNativeWrapper::IsNativeWrapper(cx, obj),
                "Uh, we should only ever be called for XPCNativeWrapper "
                "objects!");
--- a/js/src/xpconnect/src/xpcjsruntime.cpp
+++ b/js/src/xpconnect/src/xpcjsruntime.cpp
@@ -245,16 +245,41 @@ ContextCallback(JSContext *cx, uintN ope
     }
 
     return gOldJSContextCallback
            ? gOldJSContextCallback(cx, operation)
            : JS_TRUE;
 }
 
 // static
+void XPCJSRuntime::TraceJS(JSTracer *trc, XPCJSRuntime* self)
+{
+    // Skip this part if XPConnect is shutting down. We get into
+    // bad locking problems with the thread iteration otherwise.
+    if(!self->GetXPConnect()->IsShuttingDown())
+    {
+        PRLock* threadLock = XPCPerThreadData::GetLock();
+        if(threadLock)
+        { // scoped lock
+            nsAutoLock lock(threadLock);
+
+            XPCPerThreadData* iterp = nsnull;
+            XPCPerThreadData* thread;
+
+            while(nsnull != (thread =
+                             XPCPerThreadData::IterateThreads(&iterp)))
+            {
+                // Trace those AutoMarkingPtr lists!
+                thread->TraceJS(trc);
+            }
+        }
+    }
+}
+
+// static
 JSBool XPCJSRuntime::GCCallback(JSContext *cx, JSGCStatus status)
 {
     nsVoidArray* dyingWrappedJSArray;
 
     XPCJSRuntime* self = nsXPConnect::GetRuntime();
     if(self)
     {
         switch(status)
@@ -273,40 +298,17 @@ JSBool XPCJSRuntime::GCCallback(JSContex
     
                 // mThreadRunningGC indicates that GC is running
                 { // scoped lock
                     XPCAutoLock lock(self->GetMapLock());
                     NS_ASSERTION(!self->mThreadRunningGC, "bad state");
                     self->mThreadRunningGC = PR_GetCurrentThread();
                 }
 
-                // Skip this part if XPConnect is shutting down. We get into
-                // bad locking problems with the thread iteration otherwise.
-                if(!self->GetXPConnect()->IsShuttingDown())
-                {
-                    PRLock* threadLock = XPCPerThreadData::GetLock();
-                    if(threadLock)
-                    { // scoped lock
-                        nsAutoLock lock(threadLock);
-
-                        XPCPerThreadData* iterp = nsnull;
-                        XPCPerThreadData* thread;
-
-                        while(nsnull != (thread =
-                                     XPCPerThreadData::IterateThreads(&iterp)))
-                        {
-                            // Mark those AutoMarkingPtr lists!
-                            // XXX This should be in a JSGC_MARK_BEGIN
-                            // callback, in case other callbacks use
-                            // JSGC_MARK_END (or a close phase before it)
-                            // to determine what is about to be finalized.
-                            thread->MarkAutoRootsBeforeJSFinalize(cx);
-                        }
-                    }
-                }
+                TraceJS(JS_GetGCMarkingTracer(cx), self);
 
                 dyingWrappedJSArray = &self->mWrappedJSToReleaseArray;
                 {
                     XPCLock* lock = self->GetMainThreadOnlyGC() ?
                                     nsnull : self->GetMapLock();
 
                     XPCAutoLock al(lock); // lock the wrapper map if necessary
                     JSDyingJSObjectData data = {cx, dyingWrappedJSArray};
--- a/js/src/xpconnect/src/xpcprivate.h
+++ b/js/src/xpconnect/src/xpcprivate.h
@@ -623,16 +623,18 @@ public:
         return mStrJSVals[index];
     }
     const char* GetStringName(uintN index) const
     {
         NS_ASSERTION(index < IDX_TOTAL_COUNT, "index out of range");
         return mStrings[index];
     }
 
+    static void TraceJS(JSTracer *trc, XPCJSRuntime* self);
+
     static JSBool JS_DLL_CALLBACK GCCallback(JSContext *cx, JSGCStatus status);
 
     void DebugDump(PRInt16 depth);
 
     void SystemIsBeingShutDown(XPCCallContext* ccx);
 
     PRThread* GetThreadRunningGC() const {return mThreadRunningGC;}
 
@@ -1033,17 +1035,17 @@ extern JSBool
 xpc_InitWrappedNativeJSOps();
 
 #define IS_PROTO_CLASS(clazz)                                                 \
           ((clazz) == &XPC_WN_NoMods_Proto_JSClass ||                         \
            (clazz) == &XPC_WN_ModsAllowed_Proto_JSClass)
 
 // Comes from xpcwrappednativeops.cpp
 extern void
-xpc_MarkForValidWrapper(JSContext *cx, XPCWrappedNative* wrapper, void *arg);
+xpc_TraceForValidWrapper(JSTracer *trc, XPCWrappedNative* wrapper);
 
 /***************************************************************************/
 
 /***************************************************************************/
 // XPCWrappedNativeScope is one-to-one with a JS global object.
 
 class XPCWrappedNativeScope
 {
@@ -1085,16 +1087,19 @@ public:
     static XPCWrappedNativeScope*
     FindInJSObjectScope(XPCCallContext& ccx, JSObject* obj,
                         JSBool OKIfNotInitialized = JS_FALSE);
 
     static void
     SystemIsBeingShutDown(XPCCallContext& ccx);
 
     static void
+    TraceJS(JSTracer* trc, XPCJSRuntime* rt);
+
+    static void
     FinishedMarkPhaseOfGC(JSContext* cx, XPCJSRuntime* rt);
 
     static void
     FinishedFinalizationPhaseOfGC(JSContext* cx);
 
     static void
     MarkAllWrappedNativesAndProtos();
 
@@ -1289,18 +1294,18 @@ public:
 #define XPC_NATIVE_IFACE_MARK_FLAG ((PRUint16)JS_BIT(15)) // only high bit of 16 is set
 
     void Mark()     {mMemberCount |= XPC_NATIVE_IFACE_MARK_FLAG;}
     void Unmark()   {mMemberCount &= ~XPC_NATIVE_IFACE_MARK_FLAG;}
     JSBool IsMarked() const
                     {return 0 != (mMemberCount & XPC_NATIVE_IFACE_MARK_FLAG);}
 
     // NOP. This is just here to make the AutoMarkingPtr code compile.
-    inline void MarkBeforeJSFinalize(JSContext*) {}
-    inline void AutoMark(JSContext*) {}
+    inline void TraceJS(JSTracer* trc) {}
+    inline void AutoTrace(JSTracer* trc) {}
 
     static void DestroyInstance(JSContext* cx, XPCJSRuntime* rt,
                                 XPCNativeInterface* inst);
 
 protected:
     static XPCNativeInterface* NewInstance(XPCCallContext& ccx,
                                            nsIInterfaceInfo* aInfo);
 
@@ -1418,18 +1423,18 @@ public:
     inline JSBool MatchesSetUpToInterface(const XPCNativeSet* other,
                                           XPCNativeInterface* iface) const;
 
 #define XPC_NATIVE_SET_MARK_FLAG ((PRUint16)JS_BIT(15)) // only high bit of 16 is set
 
     inline void Mark();
 
     // NOP. This is just here to make the AutoMarkingPtr code compile.
-    inline void MarkBeforeJSFinalize(JSContext*) {}
-    inline void AutoMark(JSContext*) {}
+    inline void TraceJS(JSTracer* trc) {}
+    inline void AutoTrace(JSTracer* trc) {}
 
 private:
     void MarkSelfOnly() {mInterfaceCount |= XPC_NATIVE_SET_MARK_FLAG;}
 public:
     void Unmark()       {mInterfaceCount &= ~XPC_NATIVE_SET_MARK_FLAG;}
     JSBool IsMarked() const
                   {return 0 != (mInterfaceCount & XPC_NATIVE_SET_MARK_FLAG);}
 
@@ -1507,17 +1512,17 @@ public:
     JSBool WantNewEnumerate()             GET_IT(WANT_NEWENUMERATE)
     JSBool WantNewResolve()               GET_IT(WANT_NEWRESOLVE)
     JSBool WantConvert()                  GET_IT(WANT_CONVERT)
     JSBool WantFinalize()                 GET_IT(WANT_FINALIZE)
     JSBool WantCheckAccess()              GET_IT(WANT_CHECKACCESS)
     JSBool WantCall()                     GET_IT(WANT_CALL)
     JSBool WantConstruct()                GET_IT(WANT_CONSTRUCT)
     JSBool WantHasInstance()              GET_IT(WANT_HASINSTANCE)
-    JSBool WantMark()                     GET_IT(WANT_MARK)
+    JSBool WantTrace()                    GET_IT(WANT_TRACE)
     JSBool WantEquality()                 GET_IT(WANT_EQUALITY)
     JSBool WantOuterObject()              GET_IT(WANT_OUTER_OBJECT)
     JSBool WantInnerObject()              GET_IT(WANT_INNER_OBJECT)
     JSBool UseJSStubForAddProperty()      GET_IT(USE_JSSTUB_FOR_ADDPROPERTY)
     JSBool UseJSStubForDelProperty()      GET_IT(USE_JSSTUB_FOR_DELPROPERTY)
     JSBool UseJSStubForSetProperty()      GET_IT(USE_JSSTUB_FOR_SETPROPERTY)
     JSBool DontEnumStaticProps()          GET_IT(DONT_ENUM_STATIC_PROPS)
     JSBool DontEnumQueryInterface()       GET_IT(DONT_ENUM_QUERY_INTERFACE)
@@ -1718,26 +1723,33 @@ public:
         {NS_ASSERTION(!mScriptableInfo, "leak here!"); mScriptableInfo = si;}
 
     void JSProtoObjectFinalized(JSContext *cx, JSObject *obj);
 
     void SystemIsBeingShutDown(XPCCallContext& ccx);
 
     void DebugDump(PRInt16 depth);
 
-    // This is called in the 'early' phase by AutoMarkingWrappedNativeProtoPtr.
+    // During the mark traversal of JS GC this is called in the 'early' phase
+    // by AutoMarkingWrappedNativeProtoPtr.
     // 'early' meaning after JSGC_MARK_END and before JSGC_FINALIZE_END.
     // At this point in time we can still mark JSObjects in the JS gc heap.
-    void MarkBeforeJSFinalize(JSContext* cx)
-        {if(mJSProtoObject)
-            JS_MarkGCThing(cx, mJSProtoObject, 
-                           "XPCWrappedNativeProto::mJSProtoObject", nsnull);
-         if(mScriptableInfo) mScriptableInfo->Mark();}
+    void TraceJS(JSTracer* trc)
+    {
+        if(mJSProtoObject)
+        {
+            JS_CALL_OBJECT_TRACER(trc, mJSProtoObject,
+                                  "XPCWrappedNativeProto::mJSProtoObject");
+        }
+        if(mScriptableInfo && JS_IsGCMarkingTracer(trc))
+            mScriptableInfo->Mark();
+    }
+
     // NOP. This is just here to make the AutoMarkingPtr code compile.
-    inline void AutoMark(JSContext*) {}
+    inline void AutoTrace(JSTracer* trc) {}
 
     // Yes, we *do* need to mark the mScriptableInfo in both cases.
     void Mark() const
         {mSet->Mark(); 
          if(mScriptableInfo) mScriptableInfo->Mark();}
 
 #ifdef DEBUG
     void ASSERT_SetNotMarked() const {mSet->ASSERT_NotMarked();}
@@ -1796,18 +1808,18 @@ public:
 
     void JSObjectFinalized() {SetJSObject(nsnull);}
 
     XPCWrappedNativeTearOff()
         : mInterface(nsnull), mNative(nsnull), mJSObject(nsnull) {}
     ~XPCWrappedNativeTearOff();
 
     // NOP. This is just here to make the AutoMarkingPtr code compile.
-    inline void MarkBeforeJSFinalize(JSContext*) {}
-    inline void AutoMark(JSContext*) {}
+    inline void TraceJS(JSTracer* trc) {}
+    inline void AutoTrace(JSTracer* trc) {}
 
     void Mark()       {mJSObject = (JSObject*)(((jsword)mJSObject) | 1);}
     void Unmark()     {mJSObject = (JSObject*)(((jsword)mJSObject) & ~1);}
     JSBool IsMarked() const {return (JSBool)(((jsword)mJSObject) & 1);}
 
 #ifdef XPC_IDISPATCH_SUPPORT
     enum JSObject_flags
     {
@@ -2021,38 +2033,39 @@ public:
     void Mark() const
     {
         mSet->Mark();
         if(mScriptableInfo) mScriptableInfo->Mark();
         if(HasProto()) mMaybeProto->Mark();
     }
 
     // Yes, we *do* need to mark the mScriptableInfo in both cases.
-    inline void MarkBeforeJSFinalize(JSContext* cx)
+    inline void TraceJS(JSTracer* trc)
     {
-        if(mScriptableInfo) mScriptableInfo->Mark();
-        if(HasProto()) mMaybeProto->MarkBeforeJSFinalize(cx);
+        if(mScriptableInfo && JS_IsGCMarkingTracer(trc))
+            mScriptableInfo->Mark();
+        if(HasProto()) mMaybeProto->TraceJS(trc);
         if(mNativeWrapper)
         {
-            JS_MarkGCThing(cx, mNativeWrapper, 
-                           "XPCWrappedNative::mNativeWrapper", nsnull);
+            JS_CALL_OBJECT_TRACER(trc, mNativeWrapper,
+                                  "XPCWrappedNative::mNativeWrapper");
         }
     }
 
-    inline void AutoMark(JSContext* cx)
+    inline void AutoTrace(JSTracer* trc)
     {
         // If this got called, we're being kept alive by someone who really
         // needs us alive and whole.  Do not let our mFlatJSObject go away.
-        // This is the only time we should be marking our mFlatJSObject;
-        // normally we just go away quietly when it does.  Be careful not to
-        // mark the bogus JSVAL_ONE value we can have during init, though.
+        // This is the only time we should be tracing our mFlatJSObject,
+        // normally somebody else is doing that. Be careful not to trace the
+        // bogus JSVAL_ONE value we can have during init, though.
         if(mFlatJSObject && mFlatJSObject != (JSObject*)JSVAL_ONE)
         {
-            ::JS_MarkGCThing(cx, mFlatJSObject,
-                             "XPCWrappedNative::mFlatJSObject", nsnull);
+            JS_CALL_OBJECT_TRACER(trc, mFlatJSObject,
+                                  "XPCWrappedNative::mFlatJSObject");
         }
     }
 
 #ifdef DEBUG
     void ASSERT_SetsNotMarked() const
         {mSet->ASSERT_NotMarked();
          if(HasProto()){mMaybeProto->ASSERT_SetNotMarked();}}
 
@@ -2895,17 +2908,17 @@ public:
     void SetRecentContext(JSContext* cx, XPCContext* xpcc)
         {mMostRecentJSContext = cx; mMostRecentXPCContext = xpcc;}
 
     void ClearRecentContext()
         {mMostRecentJSContext = nsnull; mMostRecentXPCContext = nsnull;}
 
     AutoMarkingPtr**  GetAutoRootsAdr() {return &mAutoRoots;}
 
-    void MarkAutoRootsBeforeJSFinalize(JSContext* cx);
+    void TraceJS(JSTracer* trc);
     void MarkAutoRootsAfterJSFinalize();
 
     jsuword GetStackLimit() const { return mStackLimit; }
 
     static void InitStatics()
         { gLock = nsnull; gThreads = nsnull; gTLSIndex = BAD_TLS_INDEX; }
 
 #ifdef XPC_CHECK_WRAPPER_THREADSAFETY
@@ -3370,21 +3383,21 @@ private:
 /***************************************************************************/
 class XPCMarkableJSVal
 {
 public:
     XPCMarkableJSVal(jsval val) : mVal(val), mValPtr(&mVal) {}
     XPCMarkableJSVal(jsval *pval) : mVal(0), mValPtr(pval) {}
     ~XPCMarkableJSVal() {}
     void Mark() {}
-    void MarkBeforeJSFinalize(JSContext* cx)
-        {if(JSVAL_IS_GCTHING(*mValPtr))
-            JS_MarkGCThing(cx, JSVAL_TO_GCTHING(*mValPtr), 
-                           "XPCMarkableJSVal", nsnull);}
-    void AutoMark(JSContext*) {}
+    void TraceJS(JSTracer* trc)
+    {
+        JS_CALL_VALUE_TRACER(trc, *mValPtr, "XPCMarkableJSVal");
+    }
+    void AutoTrace(JSTracer* trc) {}
 private:
     XPCMarkableJSVal(); // not implemented    
     jsval  mVal;
     jsval* mValPtr;
 }; 
 
 /***************************************************************************/
 // AutoMarkingPtr is the base class for the various AutoMarking pointer types 
@@ -3414,17 +3427,17 @@ public:
             cur = &(*cur)->mNext;
          }
          *cur = mNext;
          mTLS = nsnull;
         }
 
     AutoMarkingPtr* GetNext() {return mNext;}
     
-    virtual void MarkBeforeJSFinalize(JSContext* cx) = 0;
+    virtual void TraceJS(JSTracer* trc) = 0;
     virtual void MarkAfterJSFinalize() = 0;
 
 protected:
     AutoMarkingPtr* mNext;
     XPCPerThreadData* mTLS;
 };
 
 // More joy of macros...
@@ -3432,22 +3445,22 @@ protected:
 #define DEFINE_AUTO_MARKING_PTR_TYPE(class_, type_)                          \
 class class_ : public AutoMarkingPtr                                         \
 {                                                                            \
 public:                                                                      \
     class_ (XPCCallContext& ccx, type_ * ptr = nsnull)                       \
         : AutoMarkingPtr(ccx), mPtr(ptr) {}                                  \
     virtual ~ class_ () {}                                                   \
                                                                              \
-    virtual void MarkBeforeJSFinalize(JSContext* cx)                         \
+    virtual void TraceJS(JSTracer* trc)                                      \
         {if(mPtr) {                                                          \
-           mPtr->MarkBeforeJSFinalize(cx);                                   \
-           mPtr->AutoMark(cx);                                               \
+           mPtr->TraceJS(trc);                                               \
+           mPtr->AutoTrace(trc);                                             \
          }                                                                   \
-         if(mNext) mNext->MarkBeforeJSFinalize(cx);}                         \
+         if(mNext) mNext->TraceJS(trc);}                                     \
                                                                              \
     virtual void MarkAfterJSFinalize()                                       \
         {if(mPtr) mPtr->Mark();                                              \
          if(mNext) mNext->MarkAfterJSFinalize();}                            \
                                                                              \
     type_ * get()        const  {return mPtr;}                               \
     operator type_ *()   const  {return mPtr;}                               \
     type_ * operator->() const  {return mPtr;}                               \
@@ -3478,28 +3491,28 @@ public:                                 
             PRBool aClear = PR_FALSE)                                        \
         : AutoMarkingPtr(ccx), mPtr(aPtr), mCount(aCount)                    \
     {                                                                        \
         if(!mPtr) mCount = 0;                                                \
         else if(aClear) memset(mPtr, 0, mCount*sizeof(type_*));              \
     }                                                                        \
     virtual ~ class_ () {}                                                   \
                                                                              \
-    virtual void MarkBeforeJSFinalize(JSContext* cx)                         \
+    virtual void TraceJS(JSTracer* trc)                                      \
     {                                                                        \
         for(PRUint32 i = 0; i < mCount; ++i)                                 \
         {                                                                    \
             type_* cur = mPtr[i];                                            \
             if(cur)                                                          \
             {                                                                \
-                cur->MarkBeforeJSFinalize(cx);                               \
-                cur->AutoMark(cx);                                           \
+                cur->TraceJS(trc);                                           \
+                cur->AutoTrace(trc);                                         \
             }                                                                \
         }                                                                    \
-        if(mNext) mNext->MarkBeforeJSFinalize(cx);                           \
+        if(mNext) mNext->TraceJS(trc);                                       \
     }                                                                        \
                                                                              \
     virtual void MarkAfterJSFinalize()                                       \
     {                                                                        \
         for(PRUint32 i = 0; i < mCount; ++i)                                 \
         {                                                                    \
             type_* cur = mPtr[i];                                            \
             if(cur)                                                          \
--- a/js/src/xpconnect/src/xpcthreadcontext.cpp
+++ b/js/src/xpconnect/src/xpcthreadcontext.cpp
@@ -499,33 +499,33 @@ XPCPerThreadData::~XPCPerThreadData()
 PR_STATIC_CALLBACK(void)
 xpc_ThreadDataDtorCB(void* ptr)
 {
     XPCPerThreadData* data = (XPCPerThreadData*) ptr;
     if(data)
         delete data;
 }
 
-void XPCPerThreadData::MarkAutoRootsBeforeJSFinalize(JSContext* cx)
+void XPCPerThreadData::TraceJS(JSTracer *trc)
 {
 #ifdef XPC_TRACK_AUTOMARKINGPTR_STATS
     {
         static int maxLength = 0;
         int length = 0;
         for(AutoMarkingPtr* p = mAutoRoots; p; p = p->GetNext())
             length++;
         if(length > maxLength)
             maxLength = length;
         printf("XPC gc on thread %x with %d AutoMarkingPtrs (%d max so far)\n",
                this, length, maxLength);
     }
 #endif
 
     if(mAutoRoots)
-        mAutoRoots->MarkBeforeJSFinalize(cx);
+        mAutoRoots->TraceJS(trc);
 }
 
 void XPCPerThreadData::MarkAutoRootsAfterJSFinalize()
 {
     if(mAutoRoots)
         mAutoRoots->MarkAfterJSFinalize();
 }
 
--- a/js/src/xpconnect/src/xpcwrappednative.cpp
+++ b/js/src/xpconnect/src/xpcwrappednative.cpp
@@ -88,25 +88,24 @@ NS_CYCLE_COLLECTION_CLASSNAME(XPCWrapped
         if (NS_SUCCEEDED(rv))
             cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT, obj);
     }
 
     // XXX If there is a scriptable helper we will not be able to find out what
     //     it marked.
 
 
-    // xpc_MarkForValidWrapper calls MarkBeforeJSFinalize and
-    // MarkScopeJSObjects.
-
-    // XPCWrappedNative marks its proto (see MarkBeforeJSFinalize).
+    // xpc_TraceForValidWrapper calls TraceJS and TraceScopeJSObjects.
+
+    // XPCWrappedNative marks its proto (see TraceJS).
     if(tmp->HasProto())
         cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT,
                            tmp->GetProto()->GetJSProtoObject());
 
-    // XPCWrappedNative marks its mNativeWrapper (see MarkBeforeJSFinalize).
+    // XPCWrappedNative marks its mNativeWrapper (see TraceJS).
     cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT, tmp->mNativeWrapper);
 
     // XPCWrappedNative marks its scope.
     tmp->GetScope()->Traverse(cb);
 
     // XPCWrappedNative keeps its native object alive.
     cb.NoteXPCOMChild(tmp->GetIdentityObject());
 
--- a/js/src/xpconnect/src/xpcwrappednativejsops.cpp
+++ b/js/src/xpconnect/src/xpcwrappednativejsops.cpp
@@ -646,75 +646,78 @@ XPC_WN_NoHelper_Finalize(JSContext *cx, 
 {
     XPCWrappedNative* p = (XPCWrappedNative*) JS_GetPrivate(cx, obj);
     if(!p)
         return;
     p->FlatJSObjectFinalized(cx, obj);
 }
 
 static void
-MarkScopeJSObjects(JSContext *cx, XPCWrappedNativeScope* scope, void *arg)
+TraceScopeJSObjects(JSTracer *trc, XPCWrappedNativeScope* scope)
 {
     NS_ASSERTION(scope, "bad scope");
 
     JSObject* obj;
 
     obj = scope->GetGlobalJSObject();
     NS_ASSERTION(scope, "bad scope JSObject");
-    JS_MarkGCThing(cx, obj, "XPCWrappedNativeScope::mGlobalJSObject", arg);
+    JS_CALL_OBJECT_TRACER(trc, obj, "XPCWrappedNativeScope::mGlobalJSObject");
 
     obj = scope->GetPrototypeJSObject();
     if(obj)
     {
-        JS_MarkGCThing(cx, obj, "XPCWrappedNativeScope::mPrototypeJSObject", arg);
+        JS_CALL_OBJECT_TRACER(trc, obj,
+                              "XPCWrappedNativeScope::mPrototypeJSObject");
     }
 
     obj = scope->GetPrototypeJSFunction();
     if(obj)
     {
-        JS_MarkGCThing(cx, obj, "XPCWrappedNativeScope::mPrototypeJSFunction", arg);
+        JS_CALL_OBJECT_TRACER(trc, obj,
+                              "XPCWrappedNativeScope::mPrototypeJSFunction");
     }
 }
 
 void
-xpc_MarkForValidWrapper(JSContext *cx, XPCWrappedNative* wrapper, void *arg)
+xpc_TraceForValidWrapper(JSTracer *trc, XPCWrappedNative* wrapper)
 {
-    // NOTE: It might be nice to also do the wrapper->Mark() call here too.
-    // That call marks the wrapper's and wrapper's proto's interface sets.
+    // NOTE: It might be nice to also do the wrapper->Mark() call here too
+    // when we are called during the marking phase of JS GC to mark the
+    // wrapper's and wrapper's proto's interface sets.
+    //
     // We currently do that in the GC callback code. The reason we don't do that
     // here is because the bits used in that marking do unpleasant things to the
     // member counts in the interface and interface set objects. Those counts
     // are used in the DealWithDyingGCThings calls that are part of this JS GC
     // marking phase. By doing these calls later during our GC callback we 
     // avoid that problem. Arguably this could be changed. But it ain't broke.
-
-    // However, we do need to call the wrapper's MarkBeforeJSFinalize so that
-    // it can be sure that its (potentially shared) JSClass gets marked. The
+    //
+    // However, we do need to call the wrapper's TraceJS so that
+    // it can be sure that its (potentially shared) JSClass is traced. The
     // danger is that a live wrapper might not be in a wrapper map and thus
     // won't be fully marked in the GC callback. This can happen if there is
     // a security exception during wrapper creation or if during wrapper
     // creation it is determined that the wrapper is not needed. In those cases
     // the wrapper can never actually be used from JS code - so resources like
     // the interface set will never be accessed. But the JS engine will still
     // need to use the JSClass. So, some marking is required for protection.
 
-    wrapper->MarkBeforeJSFinalize(cx);
+    wrapper->TraceJS(trc);
      
-    MarkScopeJSObjects(cx, wrapper->GetScope(), arg);
+    TraceScopeJSObjects(trc, wrapper->GetScope());
 }
 
-JS_STATIC_DLL_CALLBACK(uint32)
-XPC_WN_Shared_Mark(JSContext *cx, JSObject *obj, void *arg)
+JS_STATIC_DLL_CALLBACK(void)
+XPC_WN_Shared_Trace(JSTracer *trc, JSObject *obj)
 {
     XPCWrappedNative* wrapper =
-        XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);
+        XPCWrappedNative::GetWrappedNativeOfJSObject(trc->context, obj);
 
     if(wrapper && wrapper->IsValid())
-        xpc_MarkForValidWrapper(cx, wrapper, arg);
-    return 1;
+        xpc_TraceForValidWrapper(trc, wrapper);
 }
 
 JS_STATIC_DLL_CALLBACK(JSBool)
 XPC_WN_NoHelper_Resolve(JSContext *cx, JSObject *obj, jsval idval)
 {
     CHECK_IDVAL(cx, idval);
 
     XPCCallContext ccx(JS_CALLER, cx, obj, nsnull, idval);
@@ -875,16 +878,17 @@ XPC_WN_InnerObject(JSContext *cx, JSObje
     return obj;
 }
 
 JSExtendedClass XPC_WN_NoHelper_JSClass = {
     {
         "XPCWrappedNative_NoHelper",    // name;
         JSCLASS_HAS_PRIVATE |
         JSCLASS_PRIVATE_IS_NSISUPPORTS |
+        JSCLASS_MARK_IS_TRACE |
         JSCLASS_IS_EXTENDED, // flags;
 
         /* Mandatory non-null function pointer members. */
         XPC_WN_OnlyIWrite_PropertyStub, // addProperty;
         XPC_WN_CannotModifyPropertyStub,// delProperty;
         JS_PropertyStub,                // getProperty;
         XPC_WN_OnlyIWrite_PropertyStub, // setProperty;
 
@@ -895,17 +899,17 @@ JSExtendedClass XPC_WN_NoHelper_JSClass 
 
         /* Optionally non-null members start here. */
         nsnull,                         // getObjectOps;
         nsnull,                         // checkAccess;
         nsnull,                         // call;
         nsnull,                         // construct;
         nsnull,                         // xdrObject;
         nsnull,                         // hasInstance;
-        XPC_WN_Shared_Mark,             // mark;
+        JS_CLASS_TRACE(XPC_WN_Shared_Trace), // mark/trace;
         nsnull                          // spare;
     },
     XPC_WN_Equality,
     XPC_WN_OuterObject,
     XPC_WN_InnerObject,
     nsnull,nsnull,nsnull,nsnull,nsnull
 };
 
@@ -1029,28 +1033,26 @@ XPC_WN_Helper_Finalize(JSContext *cx, JS
 {
     XPCWrappedNative* wrapper = (XPCWrappedNative*) JS_GetPrivate(cx, obj);
     if(!wrapper)
         return;
     wrapper->GetScriptableCallback()->Finalize(wrapper, cx, obj);
     wrapper->FlatJSObjectFinalized(cx, obj);
 }
 
-JS_STATIC_DLL_CALLBACK(uint32)
-XPC_WN_Helper_Mark(JSContext *cx, JSObject *obj, void *arg)
+JS_STATIC_DLL_CALLBACK(void)
+XPC_WN_Helper_Trace(JSTracer *trc, JSObject *obj)
 {
-    PRUint32 ignored = 0;
     XPCWrappedNative* wrapper =
-        XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);
+        XPCWrappedNative::GetWrappedNativeOfJSObject(trc->context, obj);
     if(wrapper && wrapper->IsValid())
     {
-        wrapper->GetScriptableCallback()->Mark(wrapper, cx, obj, arg, &ignored);
-        xpc_MarkForValidWrapper(cx, wrapper, arg);
+        wrapper->GetScriptableCallback()->Trace(wrapper, trc, obj);
+        xpc_TraceForValidWrapper(trc, wrapper);
     }
-    return (uint32) ignored;
 }
 
 JS_STATIC_DLL_CALLBACK(JSBool)
 XPC_WN_Helper_NewResolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags,
                          JSObject **objp)
 {
     CHECK_IDVAL(cx, idval);
 
@@ -1339,16 +1341,17 @@ XPCNativeScriptableInfo::Construct(XPCCa
 void
 XPCNativeScriptableShared::PopulateJSClass(JSBool isGlobal)
 {
     NS_ASSERTION(mJSClass.base.name, "bad state!");
 
     mJSClass.base.flags = JSCLASS_HAS_PRIVATE |
                           JSCLASS_PRIVATE_IS_NSISUPPORTS |
                           JSCLASS_NEW_RESOLVE |
+                          JSCLASS_MARK_IS_TRACE |
                           JSCLASS_IS_EXTENDED;
 
     if(isGlobal)
         mJSClass.base.flags |= JSCLASS_GLOBAL_FLAGS;
 
     if(mFlags.WantAddProperty())
         mJSClass.base.addProperty = XPC_WN_Helper_AddProperty;
     else if(mFlags.UseJSStubForAddProperty())
@@ -1427,20 +1430,20 @@ XPCNativeScriptableShared::PopulateJSCla
     else
     {
         mJSClass.base.getObjectOps = XPC_WN_GetObjectOpsNoCall;
     }
 
     if(mFlags.WantHasInstance())
         mJSClass.base.hasInstance = XPC_WN_Helper_HasInstance;
 
-    if(mFlags.WantMark())
-        mJSClass.base.mark = XPC_WN_Helper_Mark;
+    if(mFlags.WantTrace())
+        mJSClass.base.mark = JS_CLASS_TRACE(XPC_WN_Helper_Trace);
     else
-        mJSClass.base.mark = XPC_WN_Shared_Mark;
+        mJSClass.base.mark = JS_CLASS_TRACE(XPC_WN_Shared_Trace);
 
     mJSClass.equality = XPC_WN_Equality;
     mJSClass.outerObject = XPC_WN_OuterObject;
     mJSClass.innerObject = XPC_WN_InnerObject;
 }
 
 /***************************************************************************/
 /***************************************************************************/
@@ -1549,24 +1552,24 @@ JS_STATIC_DLL_CALLBACK(void)
 XPC_WN_Shared_Proto_Finalize(JSContext *cx, JSObject *obj)
 {
     // This can be null if xpc shutdown has already happened
     XPCWrappedNativeProto* p = (XPCWrappedNativeProto*) JS_GetPrivate(cx, obj);
     if(p)
         p->JSProtoObjectFinalized(cx, obj);
 }
 
-JS_STATIC_DLL_CALLBACK(uint32)
-XPC_WN_Shared_Proto_Mark(JSContext *cx, JSObject *obj, void *arg)
+JS_STATIC_DLL_CALLBACK(void)
+XPC_WN_Shared_Proto_Trace(JSTracer *trc, JSObject *obj)
 {
     // This can be null if xpc shutdown has already happened
-    XPCWrappedNativeProto* p = (XPCWrappedNativeProto*) JS_GetPrivate(cx, obj);
+    XPCWrappedNativeProto* p =
+        (XPCWrappedNativeProto*) JS_GetPrivate(trc->context, obj);
     if(p)
-        MarkScopeJSObjects(cx, p->GetScope(), arg);
-    return 1;
+        TraceScopeJSObjects(trc, p->GetScope());
 }
 
 /*****************************************************/
 
 JS_STATIC_DLL_CALLBACK(JSBool)
 XPC_WN_ModsAllowed_Proto_Resolve(JSContext *cx, JSObject *obj, jsval idval)
 {
     CHECK_IDVAL(cx, idval);
@@ -1592,17 +1595,17 @@ XPC_WN_ModsAllowed_Proto_Resolve(JSConte
                                  self->GetScope(),
                                  JS_TRUE, nsnull, nsnull, si,
                                  enumFlag, nsnull);
 }
 
 
 JSClass XPC_WN_ModsAllowed_Proto_JSClass = {
     "XPC_WN_ModsAllowed_Proto_JSClass", // name;
-    JSCLASS_HAS_PRIVATE,                // flags;
+    JSCLASS_HAS_PRIVATE | JSCLASS_MARK_IS_TRACE, // flags;
 
     /* Mandatory non-null function pointer members. */
     JS_PropertyStub,                // addProperty;
     JS_PropertyStub,                // delProperty;
     JS_PropertyStub,                // getProperty;
     JS_PropertyStub,                // setProperty;
     XPC_WN_Shared_Proto_Enumerate,         // enumerate;
     XPC_WN_ModsAllowed_Proto_Resolve,      // resolve;
@@ -1611,17 +1614,17 @@ JSClass XPC_WN_ModsAllowed_Proto_JSClass
 
     /* Optionally non-null members start here. */
     nsnull,                         // getObjectOps;
     nsnull,                         // checkAccess;
     nsnull,                         // call;
     nsnull,                         // construct;
     nsnull,                         // xdrObject;
     nsnull,                         // hasInstance;
-    XPC_WN_Shared_Proto_Mark,       // mark;
+    JS_CLASS_TRACE(XPC_WN_Shared_Proto_Trace), // mark/trace;
     nsnull                          // spare;
 };
 
 /***************************************************************************/
 
 JS_STATIC_DLL_CALLBACK(JSBool)
 XPC_WN_OnlyIWrite_Proto_PropertyStub(JSContext *cx, JSObject *obj, jsval idval, jsval *vp)
 {
@@ -1673,17 +1676,17 @@ XPC_WN_NoMods_Proto_Resolve(JSContext *c
                                  JS_TRUE, nsnull, nsnull, si,
                                  JSPROP_READONLY |
                                  JSPROP_PERMANENT |
                                  enumFlag, nsnull);
 }
 
 JSClass XPC_WN_NoMods_Proto_JSClass = {
     "XPC_WN_NoMods_Proto_JSClass",      // name;
-    JSCLASS_HAS_PRIVATE,                // flags;
+    JSCLASS_HAS_PRIVATE | JSCLASS_MARK_IS_TRACE, // flags;
 
     /* Mandatory non-null function pointer members. */
     XPC_WN_OnlyIWrite_Proto_PropertyStub,  // addProperty;
     XPC_WN_CannotModifyPropertyStub,       // delProperty;
     JS_PropertyStub,                       // getProperty;
     XPC_WN_OnlyIWrite_Proto_PropertyStub,  // setProperty;
     XPC_WN_Shared_Proto_Enumerate,         // enumerate;
     XPC_WN_NoMods_Proto_Resolve,           // resolve;
@@ -1692,17 +1695,17 @@ JSClass XPC_WN_NoMods_Proto_JSClass = {
 
     /* Optionally non-null members start here. */
     nsnull,                         // getObjectOps;
     nsnull,                         // checkAccess;
     nsnull,                         // call;
     nsnull,                         // construct;
     nsnull,                         // xdrObject;
     nsnull,                         // hasInstance;
-    XPC_WN_Shared_Proto_Mark,       // mark;
+    JS_CLASS_TRACE(XPC_WN_Shared_Proto_Trace), // mark/trace;
     nsnull                          // spare;
 };
 
 /***************************************************************************/
 
 JS_STATIC_DLL_CALLBACK(JSBool)
 XPC_WN_TearOff_Enumerate(JSContext *cx, JSObject *obj)
 {
@@ -1756,17 +1759,17 @@ XPC_WN_TearOff_Finalize(JSContext *cx, J
         JS_GetPrivate(cx, obj);
     if(!p)
         return;
     p->JSObjectFinalized();
 }
 
 JSClass XPC_WN_Tearoff_JSClass = {
     "WrappedNative_TearOff",            // name;
-    JSCLASS_HAS_PRIVATE,                // flags;
+    JSCLASS_HAS_PRIVATE | JSCLASS_MARK_IS_TRACE, // flags;
 
     /* Mandatory non-null function pointer members. */
     XPC_WN_OnlyIWrite_PropertyStub,     // addProperty;
     XPC_WN_CannotModifyPropertyStub,    // delProperty;
     JS_PropertyStub,                    // getProperty;
     XPC_WN_OnlyIWrite_PropertyStub,     // setProperty;
     XPC_WN_TearOff_Enumerate,           // enumerate;
     XPC_WN_TearOff_Resolve,             // resolve;
@@ -1775,12 +1778,12 @@ JSClass XPC_WN_Tearoff_JSClass = {
 
     /* Optionally non-null members start here. */
     nsnull,                         // getObjectOps;
     nsnull,                         // checkAccess;
     nsnull,                         // call;
     nsnull,                         // construct;
     nsnull,                         // xdrObject;
     nsnull,                         // hasInstance;
-    nsnull,                         // mark;
+    nsnull,                         // mark/trace;
     nsnull                          // spare;
 };
 
--- a/js/src/xpconnect/src/xpcwrappednativescope.cpp
+++ b/js/src/xpconnect/src/xpcwrappednativescope.cpp
@@ -263,50 +263,57 @@ XPCWrappedNativeScope::~XPCWrappedNative
 
 JS_STATIC_DLL_CALLBACK(JSDHashOperator)
 WrappedNativeJSGCThingMarker(JSDHashTable *table, JSDHashEntryHdr *hdr,
                              uint32 number, void *arg)
 {
     XPCWrappedNative* wrapper = ((Native2WrappedNativeMap::Entry*)hdr)->value;
     if(wrapper->HasExternalReference())
     {
-        JS_MarkGCThing((JSContext*)arg, wrapper->GetFlatJSObject(), 
-                       "XPCWrappedNative::mFlatJSObject", nsnull);
+        JSTracer* trc = (JSTracer *)arg;
+        JS_CALL_OBJECT_TRACER(trc, wrapper->GetFlatJSObject(),
+                              "XPCWrappedNative::mFlatJSObject");
 
         // FIXME: this call appears to do more harm than good, but
         // there is reason to imagine it might clean up some cycles
         // formed by a poor order between C++ and JS garbage cycle
         // formations. See Bug 368869.
         //
-        // nsCycleCollector_suspectCurrent(wrapper);
+        // if (JS_IsGCMarkTraversal(trc))
+        //     nsCycleCollector_suspectCurrent(wrapper);
     }
     return JS_DHASH_NEXT;
 }
 
 // static
 void
+XPCWrappedNativeScope::TraceJS(JSTracer* trc, XPCJSRuntime* rt)
+{
+    // Do JS_CallTracer for all wrapperednatives with external references.
+    for(XPCWrappedNativeScope* cur = gScopes; cur; cur = cur->mNext)
+    {
+        cur->mWrappedNativeMap->Enumerate(WrappedNativeJSGCThingMarker, trc);
+    }
+}
+
+// static
+void
 XPCWrappedNativeScope::FinishedMarkPhaseOfGC(JSContext* cx, XPCJSRuntime* rt)
 {
     // Hold the lock until return...
     XPCAutoLock lock(rt->GetMapLock());
 
-    XPCWrappedNativeScope* cur;
-    
-    // Do JS_MarkGCThing for all wrapperednatives with external references.
-    for(cur = gScopes; cur; cur = cur->mNext)
-    {
-        cur->mWrappedNativeMap->Enumerate(WrappedNativeJSGCThingMarker, cx);
-    }
+    TraceJS(JS_GetGCMarkingTracer(cx), rt);
 
     // Since the JSGC_END call happens outside of a lock,
     // it is possible for us to get called here twice before the FinshedGC
     // call happens. So, we allow for gDyingScopes not being null.
 
     XPCWrappedNativeScope* prev = nsnull;
-    cur = gScopes;
+    XPCWrappedNativeScope* cur = gScopes;
 
     while(cur)
     {
         XPCWrappedNativeScope* next = cur->mNext;
         if(cur->mGlobalJSObject &&
            JS_IsAboutToBeFinalized(cx, cur->mGlobalJSObject))
         {
             cur->mGlobalJSObject = nsnull;
@@ -798,17 +805,17 @@ XPCWrappedNativeScope::DebugDump(PRInt16
         }
     XPC_LOG_OUTDENT();
 #endif
 }
 
 void
 XPCWrappedNativeScope::Traverse(nsCycleCollectionTraversalCallback &cb)
 {
-    // See MarkScopeJSObjects.
+    // See TraceScopeJSObjects.
     cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT, mGlobalJSObject);
     cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT, mPrototypeJSObject);
     cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT,
                        mPrototypeJSFunction);
 }
 
 #ifndef XPCONNECT_STANDALONE
 // static
--- a/storage/src/mozStorageStatementWrapper.cpp
+++ b/storage/src/mozStorageStatementWrapper.cpp
@@ -445,20 +445,20 @@ mozStorageStatementWrapper::Construct(ns
 /* PRBool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal val, out PRBool bp); */
 NS_IMETHODIMP
 mozStorageStatementWrapper::HasInstance(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
                                  JSObject * obj, jsval val, PRBool *bp, PRBool *_retval)
 {
     return NS_ERROR_NOT_IMPLEMENTED;
 }
 
-/* PRUint32 mark (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in voidPtr arg); */
+/* void trace (in nsIXPConnectWrappedNative wrapper, in JSTracerPtr trc, in JSObjectPtr obj); */
 NS_IMETHODIMP
-mozStorageStatementWrapper::Mark(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
-                          JSObject * obj, void * arg, PRUint32 *_retval)
+mozStorageStatementWrapper::Trace(nsIXPConnectWrappedNative *wrapper,
+                                  JSTracer *trc, JSObject *obj)
 {
     return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 /* PRBool equality(in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal val); */
 NS_IMETHODIMP
 mozStorageStatementWrapper::Equality(nsIXPConnectWrappedNative *wrapper,
                                     JSContext *cx, JSObject *obj, jsval val,
@@ -713,20 +713,20 @@ mozStorageStatementRow::Construct(nsIXPC
 /* PRBool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal val, out PRBool bp); */
 NS_IMETHODIMP
 mozStorageStatementRow::HasInstance(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
                                     JSObject * obj, jsval val, PRBool *bp, PRBool *_retval)
 {
     return NS_ERROR_NOT_IMPLEMENTED;
 }
 
-/* PRUint32 mark (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in voidPtr arg); */
+/* void trace (in nsIXPConnectWrappedNative wrapper, in JSTracerPtr trc, in JSObjectPtr obj); */
 NS_IMETHODIMP
-mozStorageStatementRow::Mark(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
-                             JSObject * obj, void * arg, PRUint32 *_retval)
+mozStorageStatementRow::Trace(nsIXPConnectWrappedNative *wrapper,
+                              JSTracer * trc, JSObject * obj)
 {
     return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 /* PRBool equality(in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal val); */
 NS_IMETHODIMP
 mozStorageStatementRow::Equality(nsIXPConnectWrappedNative *wrapper,
                                  JSContext *cx, JSObject *obj, jsval val,
@@ -996,20 +996,20 @@ mozStorageStatementParams::Construct(nsI
 /* PRBool hasInstance (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal val, out PRBool bp); */
 NS_IMETHODIMP
 mozStorageStatementParams::HasInstance(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
                                     JSObject * obj, jsval val, PRBool *bp, PRBool *_retval)
 {
     return NS_ERROR_NOT_IMPLEMENTED;
 }
 
-/* PRUint32 mark (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in voidPtr arg); */
+/* void trace (in nsIXPConnectWrappedNative wrapper, in JSTracerPtr trc, in JSObjectPtr obj); */
 NS_IMETHODIMP
-mozStorageStatementParams::Mark(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
-                             JSObject * obj, void * arg, PRUint32 *_retval)
+mozStorageStatementParams::Trace(nsIXPConnectWrappedNative *wrapper,
+                                JSTracer *trc, JSObject * obj)
 {
     return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 /* PRBool equality(in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in JSVal val); */
 NS_IMETHODIMP
 mozStorageStatementParams::Equality(nsIXPConnectWrappedNative *wrapper,
                                     JSContext *cx, JSObject *obj, jsval val,