Backout 10ebc5ea11ac due to test failures.
authorBen Turner <bent.mozilla@gmail.com>
Wed, 09 Feb 2011 15:29:31 -0800
changeset 62400 c6465659390620d1ffceed0e2279cae58f5dc536
parent 62399 85610aaf53cc46e1ea12718040f53fe3fc4faf9c
child 62401 9f5cce1a629e3d5b8ed12a2b6650637fed5abbb9
push id1
push userroot
push dateTue, 10 Dec 2013 15:46:25 +0000
milestone2.0b12pre
backs out10ebc5ea11ac28b232ba48f562e23e6a4b3e0ad7
Backout 10ebc5ea11ac due to test failures.
content/base/public/nsContentUtils.h
content/base/src/nsDOMDocumentType.cpp
content/base/src/nsDocument.cpp
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfo.h
dom/base/nsJSEnvironment.cpp
dom/base/nsWrapperCache.h
js/src/jscell.h
js/src/jsgc.h
js/src/xpconnect/idl/nsIXPConnect.idl
js/src/xpconnect/src/nsXPConnect.cpp
js/src/xpconnect/src/xpccallcontext.cpp
js/src/xpconnect/src/xpcconvert.cpp
js/src/xpconnect/src/xpcjsruntime.cpp
js/src/xpconnect/src/xpcmaps.h
js/src/xpconnect/src/xpcprivate.h
js/src/xpconnect/src/xpcpublic.h
js/src/xpconnect/src/xpcquickstubs.cpp
js/src/xpconnect/src/xpcquickstubs.h
js/src/xpconnect/src/xpcvariant.cpp
js/src/xpconnect/src/xpcwrappedjs.cpp
js/src/xpconnect/src/xpcwrappednative.cpp
js/src/xpconnect/src/xpcwrappednativescope.cpp
modules/plugin/base/src/nsJSNPRuntime.cpp
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -1275,18 +1275,17 @@ public:
       DropJSObjects(aScriptObjectHolder);
       aCache->SetPreservingWrapper(PR_FALSE);
     }
   }
   static void TraceWrapper(nsWrapperCache* aCache, TraceCallback aCallback,
                            void *aClosure)
   {
     if (aCache->PreservingWrapper()) {
-      aCallback(nsIProgrammingLanguage::JAVASCRIPT,
-                aCache->GetWrapperPreserveColor(),
+      aCallback(nsIProgrammingLanguage::JAVASCRIPT, aCache->GetWrapper(),
                 aClosure);
     }
   }
 
   /**
    * Convert nsIContent::IME_STATUS_* to nsIWidget::IME_STATUS_*
    */
   static PRUint32 GetWidgetStatusFromIMEStatus(PRUint32 aState);
--- a/content/base/src/nsDOMDocumentType.cpp
+++ b/content/base/src/nsDOMDocumentType.cpp
@@ -46,17 +46,16 @@
 #include "nsCOMPtr.h"
 #include "nsContentUtils.h"
 #include "nsDOMString.h"
 #include "nsIDOM3Node.h"
 #include "nsNodeInfoManager.h"
 #include "nsIDocument.h"
 #include "nsIXPConnect.h"
 #include "nsIDOMDocument.h"
-#include "xpcpublic.h"
 
 nsresult
 NS_NewDOMDocumentType(nsIDOMDocumentType** aDocType,
                       nsNodeInfoManager *aNodeInfoManager,
                       nsIPrincipal *aPrincipal,
                       nsIAtom *aName,
                       nsIDOMNamedNodeMap *aEntities,
                       nsIDOMNamedNodeMap *aNotations,
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -3785,17 +3785,17 @@ nsDocument::SetScriptGlobalObject(nsIScr
     // Go back to using the docshell for the layout history state
     mLayoutHistoryState = nsnull;
     mScopeObject = do_GetWeakReference(aScriptGlobalObject);
 
 #ifdef DEBUG
     if (!mWillReparent) {
       // We really shouldn't have a wrapper here but if we do we need to make sure
       // it has the correct parent.
-      JSObject *obj = GetWrapperPreserveColor();
+      JSObject *obj = GetWrapper();
       if (obj) {
         JSObject *newScope = aScriptGlobalObject->GetGlobalJSObject();
         nsIScriptContext *scx = aScriptGlobalObject->GetContext();
         JSContext *cx = scx ? (JSContext *)scx->GetNativeContext() : nsnull;
         if (!cx) {
           nsContentUtils::ThreadJSContextStack()->Peek(&cx);
           if (!cx) {
             nsContentUtils::ThreadJSContextStack()->GetSafeJSContext(&cx);
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -66,17 +66,16 @@
 #include "nsUnicharUtils.h"
 #include "xptcall.h"
 #include "prprf.h"
 #include "nsTArray.h"
 #include "nsCSSValue.h"
 #include "nsIRunnable.h"
 #include "nsThreadUtils.h"
 #include "nsDOMEventTargetWrapperCache.h"
-#include "xpcpublic.h"
 
 // General helper includes
 #include "nsGlobalWindow.h"
 #include "nsHistory.h"
 #include "nsIContent.h"
 #include "nsIAttribute.h"
 #include "nsIDocument.h"
 #include "nsIDOMDocument.h"
@@ -4235,41 +4234,16 @@ nsDOMClassInfo::GetArrayIndexFromId(JSCo
 
   if (aIsNumber) {
     *aIsNumber = PR_TRUE;
   }
 
   return i;
 }
 
-// static
-nsresult
-nsDOMClassInfo::WrapNative(JSContext *cx, JSObject *scope,
-                           nsISupports *native, nsWrapperCache *cache,
-                           const nsIID* aIID, jsval *vp,
-                           nsIXPConnectJSObjectHolder** aHolder,
-                           PRBool aAllowWrapping)
-{
-  if (!native) {
-    NS_ASSERTION(!aHolder || !*aHolder, "*aHolder should be null!");
-
-    *vp = JSVAL_NULL;
-
-    return NS_OK;
-  }
-
-  JSObject *wrapper = xpc_GetCachedSlimWrapper(cache, scope, vp);
-  if (wrapper) {
-    return NS_OK;
-  }
-
-  return sXPConnect->WrapNativeToJSVal(cx, scope, native, cache, aIID,
-                                       aAllowWrapping, vp, aHolder);
-}
-
 NS_IMETHODIMP
 nsDOMClassInfo::GetInterfaces(PRUint32 *aCount, nsIID ***aArray)
 {
   PRUint32 count = 0;
 
   while (mData->mInterfaces[count]) {
     count++;
   }
--- a/dom/base/nsDOMClassInfo.h
+++ b/dom/base/nsDOMClassInfo.h
@@ -43,16 +43,17 @@
 #include "nsIDOMClassInfo.h"
 #include "nsIXPCScriptable.h"
 #include "jsapi.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIScriptContext.h"
 #include "nsDOMJSUtils.h" // for GetScriptContextFromJSContext
 #include "nsIScriptGlobalObject.h"
 #include "nsContentUtils.h"
+#include "xpcpublic.h"
 
 class nsIDOMWindow;
 class nsIDOMNSHTMLOptionCollection;
 class nsIPluginInstance;
 class nsIForm;
 class nsIDOMNodeList;
 class nsIDOMDocument;
 class nsIHTMLDocument;
@@ -247,17 +248,34 @@ protected:
             id == sStatus_id       ||
             id == sName_id);
   }
 
   static nsresult WrapNative(JSContext *cx, JSObject *scope,
                              nsISupports *native, nsWrapperCache *cache,
                              const nsIID* aIID, jsval *vp,
                              nsIXPConnectJSObjectHolder** aHolder,
-                             PRBool aAllowWrapping);
+                             PRBool aAllowWrapping)
+  {
+    if (!native) {
+      NS_ASSERTION(!aHolder || !*aHolder, "*aHolder should be null!");
+
+      *vp = JSVAL_NULL;
+
+      return NS_OK;
+    }
+
+    JSObject *wrapper = xpc_GetCachedSlimWrapper(cache, scope, vp);
+    if (wrapper) {
+      return NS_OK;
+    }
+
+    return sXPConnect->WrapNativeToJSVal(cx, scope, native, cache, aIID,
+                                         aAllowWrapping, vp, aHolder);
+  }
 
   static nsIXPConnect *sXPConnect;
   static nsIScriptSecurityManager *sSecMan;
 
   // nsIXPCScriptable code
   static nsresult DefineStaticJSVals(JSContext *cx);
 
   static PRBool sIsInitialized;
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -80,17 +80,16 @@
 #include "nsEventDispatcher.h"
 #include "nsIContent.h"
 #include "nsCycleCollector.h"
 #include "nsNetUtil.h"
 #include "nsXPCOMCIDInternal.h"
 #include "nsIXULRuntime.h"
 
 #include "nsDOMClassInfo.h"
-#include "xpcpublic.h"
 
 #include "jsdbgapi.h"           // for JS_ClearWatchPointsForObject
 #include "jsxdrapi.h"
 #include "nsIArray.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "nsITimelineService.h"
 #include "nsDOMScriptObjectHolder.h"
--- a/dom/base/nsWrapperCache.h
+++ b/dom/base/nsWrapperCache.h
@@ -37,66 +37,45 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsWrapperCache_h___
 #define nsWrapperCache_h___
 
 #include "nsCycleCollectionParticipant.h"
 
 struct JSObject;
-class nsContentUtils;
 
 typedef PRUptrdiff PtrBits;
 
 #define NS_WRAPPERCACHE_IID \
 { 0x3a51ca81, 0xddab, 0x422c, \
   { 0x95, 0x3a, 0x13, 0x06, 0x28, 0x0e, 0xee, 0x14 } }
 
 /**
  * Class to store the XPCWrappedNative for an object. This can only be used
  * with objects that only have one XPCWrappedNative at a time (usually ensured
  * by setting an explicit parent in the PreCreate hook for the class). This
  * object can be gotten by calling QueryInterface, note that this breaks XPCOM
  * rules a bit (this object doesn't derive from nsISupports).
  */
 class nsWrapperCache
 {
-  friend class nsContentUtils;
-
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_WRAPPERCACHE_IID)
 
   nsWrapperCache() : mWrapperPtrBits(0)
   {
   }
   ~nsWrapperCache()
   {
     NS_ASSERTION(!PreservingWrapper(),
                  "Destroying cache with a preserved wrapper!");
   }
 
-  /**
-   * This getter clears the gray bit before handing out the JSObject which means
-   * that the object is guaranteed to be kept alive past the next CC.
-   *
-   * Implemented in xpcpublic.h because we have to include some JS headers that
-   * don't play nicely with the rest of the codebase. Include xpcpublic.h if you
-   * need to call this method.
-   */
-  inline JSObject* GetWrapper() const;
-
-  /**
-   * This getter does not change the color of the JSObject meaning that the
-   * object returned is not guaranteed to be kept alive past the next CC.
-   *
-   * This should only be called if you are certain that the return value won't
-   * be passed into a JS API function and that it won't be stored without being
-   * rooted (or otherwise signaling the stored value to the CC).
-   */
-  JSObject* GetWrapperPreserveColor() const
+  JSObject* GetWrapper() const
   {
     return reinterpret_cast<JSObject*>(mWrapperPtrBits & ~kWrapperBitMask);
   }
 
   void SetWrapper(JSObject* aWrapper)
   {
     NS_ASSERTION(!PreservingWrapper(), "Clearing a preserved wrapper!");
     mWrapperPtrBits = reinterpret_cast<PtrBits>(aWrapper) |
@@ -104,43 +83,42 @@ public:
   }
 
   void ClearWrapper()
   {
     NS_ASSERTION(!PreservingWrapper(), "Clearing a preserved wrapper!");
     mWrapperPtrBits = 0;
   }
 
-  PRBool PreservingWrapper()
-  {
-    return (mWrapperPtrBits & WRAPPER_BIT_PRESERVED) != 0;
-  }
-
-  void SetIsProxy()
-  {
-    mWrapperPtrBits |= WRAPPER_IS_PROXY;
-  }
-
-  PRBool IsProxy()
-  {
-    return (mWrapperPtrBits & WRAPPER_IS_PROXY) != 0;
-  }
-
-private:
-  // Only meant to be called by nsContentUtils.
   void SetPreservingWrapper(PRBool aPreserve)
   {
     if(aPreserve) {
       mWrapperPtrBits |= WRAPPER_BIT_PRESERVED;
     }
     else {
       mWrapperPtrBits &= ~WRAPPER_BIT_PRESERVED;
     }
   }
 
+  PRBool PreservingWrapper()
+  {
+    return (mWrapperPtrBits & WRAPPER_BIT_PRESERVED) != 0;
+  }
+
+  void SetIsProxy()
+  {
+      mWrapperPtrBits |= WRAPPER_IS_PROXY;
+  }
+
+  PRBool IsProxy()
+  {
+      return (mWrapperPtrBits & WRAPPER_IS_PROXY) != 0;
+  }
+
+private:
   enum { WRAPPER_BIT_PRESERVED = 1 << 0 };
   enum { WRAPPER_IS_PROXY = 1 << 1 };
   enum { kWrapperBitMask = (WRAPPER_BIT_PRESERVED | WRAPPER_IS_PROXY) };
 
   PtrBits mWrapperPtrBits;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsWrapperCache, NS_WRAPPERCACHE_IID)
--- a/js/src/jscell.h
+++ b/js/src/jscell.h
@@ -66,17 +66,16 @@ struct Cell {
 
     inline Arena<Cell> *arena() const;
     inline Chunk *chunk() const;
     inline ArenaBitmap *bitmap() const;
     JS_ALWAYS_INLINE size_t cellIndex() const;
 
     JS_ALWAYS_INLINE bool isMarked(uint32 color) const;
     JS_ALWAYS_INLINE bool markIfUnmarked(uint32 color) const;
-    JS_ALWAYS_INLINE void unmark(uint32 color) const;
 
     inline JSCompartment *compartment() const;
 
     /* Needed for compatibility reasons because Cell can't be a base class of JSString */
     JS_ALWAYS_INLINE js::gc::Cell *asCell() { return this; }
 
     JS_ALWAYS_INLINE js::gc::FreeCell *asFreeCell() {
         return reinterpret_cast<FreeCell *>(this);
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -208,23 +208,16 @@ struct ArenaBitmap {
             mask = (uintptr_t(1) << (bit % JS_BITS_PER_WORD));
             if (*word & mask)
                 return false;
             *word |= mask;
         }
         return true;
     }
 
-    JS_ALWAYS_INLINE void unmark(size_t bit, uint32 color) {
-        bit += color;
-        JS_ASSERT(bit < BitCount);
-        uintptr_t *word = &bitmap[bit / JS_BITS_PER_WORD];
-        *word &= ~(uintptr_t(1) << (bit % JS_BITS_PER_WORD));
-    }
-
 #ifdef DEBUG
     bool noBitsSet() {
         for (unsigned i = 0; i < BitWords; i++) {
             if (bitmap[i] != uintptr_t(0))
                 return false;
         }
         return true;
     }
@@ -463,24 +456,16 @@ Cell::isMarked(uint32 color = BLACK) con
 
 bool
 Cell::markIfUnmarked(uint32 color = BLACK) const
 {
     AssertValidColor(this, color);
     return bitmap()->markIfUnmarked(cellIndex(), color);
 }
 
-void
-Cell::unmark(uint32 color) const
-{
-    JS_ASSERT(color != BLACK);
-    AssertValidColor(this, color);
-    bitmap()->unmark(cellIndex(), color);
-}
-
 JSCompartment *
 Cell::compartment() const
 {
     return arena()->header()->compartment;
 }
 
 template <typename T>
 static inline
--- a/js/src/xpconnect/idl/nsIXPConnect.idl
+++ b/js/src/xpconnect/idl/nsIXPConnect.idl
@@ -50,18 +50,17 @@
 #include "nsIInterfaceInfoManager.idl"
 #include "nsIExceptionService.idl"
 #include "nsIVariant.idl"
 
 %{ C++
 #include "jspubtd.h"
 #include "xptinfo.h"
 #include "nsAXPCNativeCallContext.h"
-
-class nsWrapperCache;
+#include "nsWrapperCache.h"
 %}
 
 /***************************************************************************/
 
 // NB: jsval and jsid are declared in nsIVariant.idl
 
 [ptr] native JSContextPtr(JSContext);
 [ptr] native JSClassPtr(JSClass);
--- a/js/src/xpconnect/src/nsXPConnect.cpp
+++ b/js/src/xpconnect/src/nsXPConnect.cpp
@@ -564,22 +564,19 @@ struct TraversalTracer : public JSTracer
     {
     }
     nsCycleCollectionTraversalCallback &cb;
 };
 
 static void
 NoteJSChild(JSTracer *trc, void *thing, uint32 kind)
 {
-    TraversalTracer *tracer = static_cast<TraversalTracer*>(trc);
-    if(!nsXPConnect::IsGray(thing) && !tracer->cb.WantAllTraces())
-        return;
-
     if(ADD_TO_CC(kind))
     {
+        TraversalTracer *tracer = static_cast<TraversalTracer*>(trc);
 #if defined(DEBUG)
         if (NS_UNLIKELY(tracer->cb.WantDebugInfo())) {
             // based on DumpNotify in jsapi.c
             if (tracer->debugPrinter) {
                 char buffer[200];
                 tracer->debugPrinter(trc, buffer, sizeof(buffer));
                 tracer->cb.NoteNextEdgeName(buffer);
             } else if (tracer->debugPrintIndex != (size_t)-1) {
@@ -678,17 +675,17 @@ nsXPConnect::Traverse(void *p, nsCycleCo
             PL_DHashTableOperate(&mJSRoots, p, PL_DHASH_LOOKUP);
         type = markJSObject || PL_DHASH_ENTRY_IS_BUSY(entry) ? GCMarked :
                                                                GCUnmarked;
     }
     else
 #endif
     {
         // Normal codepath (matches non-DEBUG_CC codepath).
-        type = !markJSObject ? GCUnmarked : GCMarked;
+        type = !markJSObject && IsGray(p) ? GCUnmarked : GCMarked;
     }
 
     if (cb.WantDebugInfo()) {
         char name[72];
         if(traceKind == JSTRACE_OBJECT)
         {
             JSObject *obj = static_cast<JSObject*>(p);
             js::Class *clazz = obj->getClass();
@@ -773,17 +770,17 @@ nsXPConnect::Traverse(void *p, nsCycleCo
 
     TraversalTracer trc(cb);
 
     JS_TRACER_INIT(&trc, cx, NoteJSChild);
     JS_TraceChildren(&trc, p, traceKind);
 
     if(traceKind != JSTRACE_OBJECT || dontTraverse)
         return NS_OK;
-
+    
     if(clazz == &XPC_WN_Tearoff_JSClass)
     {
         // A tearoff holds a strong reference to its native object
         // (see XPCWrappedNative::FlatJSObjectFinalized). Its XPCWrappedNative
         // will be held alive through the parent of the JSObject of the tearoff.
         XPCWrappedNativeTearOff *to =
             (XPCWrappedNativeTearOff*) xpc_GetJSPrivate(obj);
         NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "xpc_GetJSPrivate(obj)->mNative");
@@ -1586,17 +1583,17 @@ MoveWrapper(XPCCallContext& ccx, XPCWrap
 
         XPCWrappedNative *parentWrapper =
             XPCWrappedNative::GetWrappedNativeOfJSObject(ccx, newParent);
 
         rv = MoveWrapper(ccx, parentWrapper, newScope, oldScope);
 
         NS_ENSURE_SUCCESS(rv, rv);
 
-        newParent = parentWrapper->GetFlatJSObject();
+        newParent = parentWrapper->GetFlatJSObjectNoMark();
     }
     else
         NS_ASSERTION(betterScope == newScope, "Weird scope returned");
 
     // Now, reparent the wrapper, since we know that it wants to be
     // reparented.
 
     nsRefPtr<XPCWrappedNative> junk;
--- a/js/src/xpconnect/src/xpccallcontext.cpp
+++ b/js/src/xpconnect/src/xpccallcontext.cpp
@@ -191,17 +191,17 @@ XPCCallContext::Init(XPCContext::LangTyp
         mWrapper = XPCWrappedNative::GetWrappedNativeOfJSObject(mJSContext, obj,
                                                                 funobj,
                                                                 &mCurrentJSObject,
                                                                 &mTearOff);
     if(mWrapper)
     {
         DEBUG_CheckWrapperThreadSafety(mWrapper);
 
-        mFlattenedJSObject = mWrapper->GetFlatJSObject();
+        mFlattenedJSObject = mWrapper->GetFlatJSObjectAndMark();
 
         if(mTearOff)
         {
             mCurrentJSObject = mTearOff->GetJSObject();
             mScriptableInfo = nsnull;
         }
         else
         {
--- a/js/src/xpconnect/src/xpcconvert.cpp
+++ b/js/src/xpconnect/src/xpcconvert.cpp
@@ -1348,17 +1348,17 @@ XPCConvert::NativeInterface2JSObject(XPC
         *pErr = rv;
 
     // If creating the wrapped native failed, then return early.
     if(NS_FAILED(rv) || !wrapper)
         return JS_FALSE;
 
     // If we're not creating security wrappers, we can return the
     // XPCWrappedNative as-is here.
-    flat = wrapper->GetFlatJSObject();
+    flat = wrapper->GetFlatJSObjectAndMark();
     jsval v = OBJECT_TO_JSVAL(flat);
     if(!XPCPerThreadData::IsMainThread(lccx.GetJSContext()) ||
        !allowNativeWrapper)
     {
         *d = v;
         if(dest)
             *dest = strongWrapper.forget().get();
         return JS_TRUE;
--- a/js/src/xpconnect/src/xpcjsruntime.cpp
+++ b/js/src/xpconnect/src/xpcjsruntime.cpp
@@ -89,20 +89,18 @@ WrappedJSDyingJSObjectFinder(JSDHashTabl
     nsXPCWrappedJS* wrapper = ((JSObject2WrappedJSMap::Entry*)hdr)->value;
     NS_ASSERTION(wrapper, "found a null JS wrapper!");
 
     // walk the wrapper chain and find any whose JSObject is to be finalized
     while(wrapper)
     {
         if(wrapper->IsSubjectToFinalization())
         {
-            js::SwitchToCompartment sc(data->cx,
-                                       wrapper->GetJSObjectPreserveColor());
-            if(JS_IsAboutToBeFinalized(data->cx,
-                                       wrapper->GetJSObjectPreserveColor()))
+            js::SwitchToCompartment sc(data->cx, wrapper->GetJSObject());
+            if(JS_IsAboutToBeFinalized(data->cx, wrapper->GetJSObject()))
                 data->array->AppendElement(wrapper);
         }
         wrapper = wrapper->GetNextWrapper();
     }
     return JS_DHASH_NEXT;
 }
 
 struct CX_AND_XPCRT_Data
@@ -500,20 +498,23 @@ XPCJSRuntime::SuspectWrappedNative(JSCon
     if(!wrapper->IsValid() || wrapper->IsWrapperExpired())
         return;
 
     NS_ASSERTION(NS_IsMainThread() || NS_IsCycleCollectorThread(), 
                  "Suspecting wrapped natives from non-CC thread");
 
     // Only suspect wrappedJSObjects that are in a compartment that
     // participates in cycle collection.
-    JSObject* obj = wrapper->GetFlatJSObjectPreserveColor();
+    JSObject* obj = wrapper->GetFlatJSObjectAndMark();
     if(!xpc::ParticipatesInCycleCollection(cx, obj))
         return;
 
+    NS_ASSERTION(!JS_IsAboutToBeFinalized(cx, obj),
+                 "SuspectWrappedNative attempting to touch dead object");
+
     // Only record objects that might be part of a cycle as roots, unless
     // the callback wants all traces (a debug feature).
     if(nsXPConnect::IsGray(obj) || cb.WantAllTraces())
         cb.NoteRoot(nsIProgrammingLanguage::JAVASCRIPT, obj,
                     nsXPConnect::GetXPConnect());
 }
 
 static PLDHashOperator
@@ -566,17 +567,17 @@ XPCJSRuntime::AddXPConnectRoots(JSContex
     XPCWrappedNativeScope::SuspectAllWrappers(this, cx, cb);
 
     for(XPCRootSetElem *e = mVariantRoots; e ; e = e->GetNextRoot())
         cb.NoteXPCOMRoot(static_cast<XPCTraceableVariant*>(e));
 
     for(XPCRootSetElem *e = mWrappedJSRoots; e ; e = e->GetNextRoot())
     {
         nsXPCWrappedJS *wrappedJS = static_cast<nsXPCWrappedJS*>(e);
-        JSObject *obj = wrappedJS->GetJSObjectPreserveColor();
+        JSObject *obj = wrappedJS->GetJSObject();
 
         // Only suspect wrappedJSObjects that are in a compartment that
         // participates in cycle collection.
         if(!xpc::ParticipatesInCycleCollection(cx, obj))
             continue;
 
         cb.NoteXPCOMRoot(static_cast<nsIXPConnectWrappedJS *>(wrappedJS));
     }
@@ -634,17 +635,17 @@ SweepWaiverWrappers(JSDHashTable *table,
         return JS_DHASH_REMOVE;
     return JS_DHASH_NEXT;
 }
 
 static PLDHashOperator
 SweepExpandos(XPCWrappedNative *wn, JSObject *&expando, void *arg)
 {
     JSContext *cx = (JSContext *)arg;
-    return IsAboutToBeFinalized(cx, wn->GetFlatJSObjectPreserveColor())
+    return IsAboutToBeFinalized(cx, wn->GetFlatJSObjectNoMark())
            ? PL_DHASH_REMOVE
            : PL_DHASH_NEXT;
 }
 
 static PLDHashOperator
 SweepCompartment(nsCStringHashKey& aKey, JSCompartment *compartment, void *aClosure)
 {
     xpc::CompartmentPrivate *priv = (xpc::CompartmentPrivate *)
--- a/js/src/xpconnect/src/xpcmaps.h
+++ b/js/src/xpconnect/src/xpcmaps.h
@@ -74,33 +74,32 @@ public:
         if(JS_DHASH_ENTRY_IS_FREE(entry))
             return nsnull;
         return entry->value;
     }
 
     inline nsXPCWrappedJS* Add(nsXPCWrappedJS* wrapper)
     {
         NS_PRECONDITION(wrapper,"bad param");
-        JSObject* obj = wrapper->GetJSObjectPreserveColor();
+        JSObject* obj = wrapper->GetJSObject();
         Entry* entry = (Entry*)
             JS_DHashTableOperate(mTable, obj, JS_DHASH_ADD);
         if(!entry)
             return nsnull;
         if(entry->key)
             return entry->value;
         entry->key = obj;
         entry->value = wrapper;
         return wrapper;
     }
 
     inline void Remove(nsXPCWrappedJS* wrapper)
     {
         NS_PRECONDITION(wrapper,"bad param");
-        JS_DHashTableOperate(mTable, wrapper->GetJSObjectPreserveColor(),
-                             JS_DHASH_REMOVE);
+        JS_DHashTableOperate(mTable, wrapper->GetJSObject(), JS_DHASH_REMOVE);
     }
 
     inline uint32 Count() {return mTable->entryCount;}
     inline uint32 Enumerate(JSDHashEnumerator f, void *arg)
         {return JS_DHashTableEnumerate(mTable, f, arg);}
 
     ~JSObject2WrappedJSMap();
 private:
--- a/js/src/xpconnect/src/xpcprivate.h
+++ b/js/src/xpconnect/src/xpcprivate.h
@@ -55,16 +55,17 @@
 #include "jsdhash.h"
 #include "jsprf.h"
 #include "prprf.h"
 #include "jsinterp.h"
 #include "jscntxt.h"
 #include "jsdbgapi.h"
 #include "jsgc.h"
 #include "jscompartment.h"
+#include "xpcpublic.h"
 #include "nscore.h"
 #include "nsXPCOM.h"
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsCycleCollector.h"
 #include "nsISupports.h"
 #include "nsIServiceManager.h"
 #include "nsIClassInfoImpl.h"
@@ -482,16 +483,19 @@ private:
 /***************************************************************************
 ****************************************************************************
 *
 * Core runtime and context classes...
 *
 ****************************************************************************
 ***************************************************************************/
 
+static const uint32 XPC_GC_COLOR_BLACK = 0;
+static const uint32 XPC_GC_COLOR_GRAY = 1;
+
 // We have a general rule internally that getters that return addref'd interface
 // pointer generally do so using an 'out' parm. When interface pointers are
 // returned as function call result values they are not addref'd. Exceptions
 // to this rule are noted explicitly.
 
 const PRBool OBJ_IS_GLOBAL = PR_TRUE;
 const PRBool OBJ_IS_NOT_GLOBAL = PR_FALSE;
 
@@ -2520,36 +2524,24 @@ public:
     GetScope() const
         {return GetProto() ? GetProto()->GetScope() :
          (XPCWrappedNativeScope*)
          (XPC_SCOPE_WORD(mMaybeScope) & ~XPC_SCOPE_MASK);}
 
     nsISupports*
     GetIdentityObject() const {return mIdentity;}
 
-    /**
-     * This getter clears the gray bit before handing out the JSObject which
-     * means that the object is guaranteed to be kept alive past the next CC.
-     */
     JSObject*
-    GetFlatJSObject() const
+    GetFlatJSObjectAndMark() const
         {if(mFlatJSObject && mFlatJSObject != INVALID_OBJECT)
-             mFlatJSObject->unmark(XPC_GC_COLOR_GRAY);
+             mFlatJSObject->markIfUnmarked();
          return mFlatJSObject;}
 
-    /**
-     * This getter does not change the color of the JSObject meaning that the
-     * object returned is not guaranteed to be kept alive past the next CC.
-     *
-     * This should only be called if you are certain that the return value won't
-     * be passed into a JS API function and that it won't be stored without
-     * being rooted (or otherwise signaling the stored value to the CC).
-     */
     JSObject*
-    GetFlatJSObjectPreserveColor() const {return mFlatJSObject;}
+    GetFlatJSObjectNoMark() const {return mFlatJSObject;}
 
     XPCLock*
     GetLock() const {return IsValid() && HasProto() ?
                                 GetProto()->GetLock() : nsnull;}
 
     XPCNativeSet*
     GetSet() const {XPCAutoLock al(GetLock()); return mSet;}
 
@@ -2987,34 +2979,17 @@ public:
     static nsresult
     GetNewOrUsed(XPCCallContext& ccx,
                  JSObject* aJSObj,
                  REFNSIID aIID,
                  nsISupports* aOuter,
                  nsXPCWrappedJS** wrapper);
 
     nsISomeInterface* GetXPTCStub() { return mXPTCStub; }
-
-    /**
-     * This getter clears the gray bit before handing out the JSObject which
-     * means that the object is guaranteed to be kept alive past the next CC.
-     */
-    JSObject* GetJSObject() const {if(mJSObj) mJSObj->unmark(XPC_GC_COLOR_GRAY);
-                                   return mJSObj;}
-
-    /**
-     * This getter does not change the color of the JSObject meaning that the
-     * object returned is not guaranteed to be kept alive past the next CC.
-     *
-     * This should only be called if you are certain that the return value won't
-     * be passed into a JS API function and that it won't be stored without
-     * being rooted (or otherwise signaling the stored value to the CC).
-     */
-    JSObject* GetJSObjectPreserveColor() const {return mJSObj;}
-
+    JSObject* GetJSObject() const {return mJSObj;}
     nsXPCWrappedJSClass*  GetClass() const {return mClass;}
     REFNSIID GetIID() const {return GetClass()->GetIID();}
     nsXPCWrappedJS* GetRootWrapper() const {return mRoot;}
     nsXPCWrappedJS* GetNextWrapper() const {return mNext;}
 
     nsXPCWrappedJS* Find(REFNSIID aIID);
     nsXPCWrappedJS* FindInherited(REFNSIID aIID);
 
@@ -4326,35 +4301,20 @@ public:
 
     // We #define and iid so that out module local code can use QI to detect 
     // if a given nsIVariant is in fact an XPCVariant. 
     NS_DECLARE_STATIC_IID_ACCESSOR(XPCVARIANT_IID)
 
     static XPCVariant* newVariant(XPCCallContext& ccx, jsval aJSVal);
 
     /**
-     * This getter clears the gray bit before handing out the jsval if the jsval
-     * represents a JSObject. That means that the object is guaranteed to be
-     * kept alive past the next CC.
+     * nsIVariant exposes a GetAsJSVal() method, which also returns mJSVal.
+     * But if you can, you should call this one, since it can be inlined.
      */
-    jsval GetJSVal() const
-        {if(!JSVAL_IS_PRIMITIVE(mJSVal))
-             JSVAL_TO_OBJECT(mJSVal)->unmark(XPC_GC_COLOR_GRAY);
-         return mJSVal;}
-
-    /**
-     * This getter does not change the color of the jsval (if it represents a
-     * JSObject) meaning that the value returned is not guaranteed to be kept
-     * alive past the next CC.
-     *
-     * This should only be called if you are certain that the return value won't
-     * be passed into a JS API function and that it won't be stored without
-     * being rooted (or otherwise signaling the stored value to the CC).
-     */
-    jsval GetJSValPreserveColor() const {return mJSVal;}
+    jsval GetJSVal() const {return mJSVal;}
 
     XPCVariant(XPCCallContext& ccx, jsval aJSVal);
 
     /**
      * Convert a variant into a jsval.
      *
      * @param ccx the context for the whole procedure
      * @param variant the variant to convert
--- a/js/src/xpconnect/src/xpcpublic.h
+++ b/js/src/xpconnect/src/xpcpublic.h
@@ -43,19 +43,16 @@
 #include "jsapi.h"
 #include "jsobj.h"
 #include "jsgc.h"
 
 #include "nsISupports.h"
 #include "nsIPrincipal.h"
 #include "nsWrapperCache.h"
 
-static const uint32 XPC_GC_COLOR_BLACK = 0;
-static const uint32 XPC_GC_COLOR_GRAY = 1;
-
 class nsIPrincipal;
 
 nsresult
 xpc_CreateGlobalObject(JSContext *cx, JSClass *clasp,
                        nsIPrincipal *principal, nsISupports *ptr,
                        bool wantXrays, JSObject **global,
                        JSCompartment **compartment);
 
@@ -109,26 +106,16 @@ inline JSObject *
 xpc_GetGlobalForObject(JSObject *obj)
 {
     while(JSObject *parent = obj->getParent())
         obj = parent;
     return obj;
 }
 
 inline JSObject*
-nsWrapperCache::GetWrapper() const
-{
-  JSObject* object = GetWrapperPreserveColor();
-  if (object) {
-    object->unmark(XPC_GC_COLOR_GRAY);
-  }
-  return object;
-}
-
-inline JSObject*
 xpc_GetCachedSlimWrapper(nsWrapperCache *cache, JSObject *scope, jsval *vp)
 {
     if (cache) {
         JSObject* wrapper = cache->GetWrapper();
         // FIXME: Bug 585786, the check for IS_SLIM_WRAPPER_OBJECT should go
         //        away
         if (wrapper &&
             IS_SLIM_WRAPPER_OBJECT(wrapper) &&
--- a/js/src/xpconnect/src/xpcquickstubs.cpp
+++ b/js/src/xpconnect/src/xpcquickstubs.cpp
@@ -811,17 +811,18 @@ inline nsresult
 getNativeFromWrapper(JSContext *cx,
                      XPCWrappedNative *wrapper,
                      const nsIID &iid,
                      void **ppThis,
                      nsISupports **pThisRef,
                      jsval *vp)
 {
     return getNative(wrapper->GetIdentityObject(), wrapper->GetOffsets(),
-                     wrapper->GetFlatJSObject(), iid, ppThis, pThisRef, vp);
+                     wrapper->GetFlatJSObjectAndMark(), iid, ppThis, pThisRef,
+                     vp);
 }
 
 
 nsresult
 getWrapper(JSContext *cx,
            JSObject *obj,
            JSObject *callee,
            XPCWrappedNative **wrapper,
--- a/js/src/xpconnect/src/xpcquickstubs.h
+++ b/js/src/xpconnect/src/xpcquickstubs.h
@@ -576,17 +576,17 @@ castNativeFromWrapper(JSContext *cx,
         if (NS_FAILED(*rv))
             return nsnull;
     }
 
     nsISupports *native;
     if(wrapper)
     {
         native = wrapper->GetIdentityObject();
-        cur = wrapper->GetFlatJSObject();
+        cur = wrapper->GetFlatJSObjectAndMark();
     }
     else
     {
         native = cur ?
                  static_cast<nsISupports*>(xpc_GetJSPrivate(cur)) :
                  nsnull;
     }
 
--- a/js/src/xpconnect/src/xpcvariant.cpp
+++ b/js/src/xpconnect/src/xpcvariant.cpp
@@ -76,66 +76,59 @@ XPCVariant::XPCVariant(XPCCallContext& c
         mReturnRawObject = !wn && !proto;
     }
     else
         mReturnRawObject = JS_FALSE;
 }
 
 XPCTraceableVariant::~XPCTraceableVariant()
 {
-    jsval val = GetJSValPreserveColor();
-
-    NS_ASSERTION(JSVAL_IS_GCTHING(val), "Must be traceable or unlinked");
+    NS_ASSERTION(JSVAL_IS_GCTHING(mJSVal), "Must be traceable or unlinked");
 
-    // If val is JSVAL_STRING, we don't need to clean anything up; simply
-    // removing the string from the root set is good.
-    if(!JSVAL_IS_STRING(val))
+    // If mJSVal is JSVAL_STRING, we don't need to clean anything up;
+    // simply removing the string from the root set is good.
+    if(!JSVAL_IS_STRING(mJSVal))
         nsVariant::Cleanup(&mData);
 
-    if (!JSVAL_IS_NULL(val))
+    if (!JSVAL_IS_NULL(mJSVal))
         RemoveFromRootSet(nsXPConnect::GetRuntimeInstance()->GetMapLock());
 }
 
 void XPCTraceableVariant::TraceJS(JSTracer* trc)
 {
-    jsval val = GetJSValPreserveColor();
-
-    NS_ASSERTION(JSVAL_IS_TRACEABLE(val), "Must be traceable");
+    NS_ASSERTION(JSVAL_IS_TRACEABLE(mJSVal), "Must be traceable");
     JS_SET_TRACING_DETAILS(trc, PrintTraceName, this, 0);
-    JS_CallTracer(trc, JSVAL_TO_TRACEABLE(val), JSVAL_TRACE_KIND(val));
+    JS_CallTracer(trc, JSVAL_TO_TRACEABLE(mJSVal), JSVAL_TRACE_KIND(mJSVal));
 }
 
 #ifdef DEBUG
 // static
 void
 XPCTraceableVariant::PrintTraceName(JSTracer* trc, char *buf, size_t bufsize)
 {
     JS_snprintf(buf, bufsize, "XPCVariant[0x%p].mJSVal", trc->debugPrintArg);
 }
 #endif
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(XPCVariant)
-    jsval val = tmp->GetJSValPreserveColor();
-    if(JSVAL_IS_OBJECT(val))
+    if(JSVAL_IS_OBJECT(tmp->mJSVal))
         cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT,
-                           JSVAL_TO_OBJECT(val));
+                           JSVAL_TO_OBJECT(tmp->mJSVal));
 
     nsVariant::Traverse(tmp->mData, cb);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(XPCVariant)
-    jsval val = tmp->GetJSValPreserveColor();
-
-    // We're sharing val's buffer, clear the pointer to it so Cleanup() won't
-    // try to delete it
-    if(JSVAL_IS_STRING(val))
+    // We're sharing mJSVal's buffer, clear the pointer to it
+    // so Cleanup() won't try to delete it
+    if(JSVAL_IS_STRING(tmp->mJSVal))
         tmp->mData.u.wstr.mWStringValue = nsnull;
     nsVariant::Cleanup(&tmp->mData);
 
-    if(JSVAL_IS_TRACEABLE(val))
+    if(JSVAL_IS_TRACEABLE(tmp->mJSVal))
     {
         XPCTraceableVariant *v = static_cast<XPCTraceableVariant*>(tmp);
         v->RemoveFromRootSet(nsXPConnect::GetRuntimeInstance()->GetMapLock());
     }
     tmp->mJSVal = JSVAL_NULL;
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 // static 
@@ -302,35 +295,34 @@ XPCArrayHomogenizer::GetTypeForArray(XPC
     }
     return JS_TRUE;
 }
 
 JSBool XPCVariant::InitializeData(XPCCallContext& ccx)
 {
     JS_CHECK_RECURSION(ccx.GetJSContext(), return JS_FALSE);
 
-    jsval val = GetJSValPreserveColor();
-
-    if(JSVAL_IS_INT(val))
-        return NS_SUCCEEDED(nsVariant::SetFromInt32(&mData, JSVAL_TO_INT(val)));
-    if(JSVAL_IS_DOUBLE(val))
+    if(JSVAL_IS_INT(mJSVal))
+        return NS_SUCCEEDED(nsVariant::SetFromInt32(&mData, 
+                                                    JSVAL_TO_INT(mJSVal)));
+    if(JSVAL_IS_DOUBLE(mJSVal))
         return NS_SUCCEEDED(nsVariant::SetFromDouble(&mData, 
-                                                     JSVAL_TO_DOUBLE(val)));
-    if(JSVAL_IS_BOOLEAN(val))
+                                                     JSVAL_TO_DOUBLE(mJSVal)));
+    if(JSVAL_IS_BOOLEAN(mJSVal))
         return NS_SUCCEEDED(nsVariant::SetFromBool(&mData, 
-                                                   JSVAL_TO_BOOLEAN(val)));
-    if(JSVAL_IS_VOID(val))
+                                                   JSVAL_TO_BOOLEAN(mJSVal)));
+    if(JSVAL_IS_VOID(mJSVal))
         return NS_SUCCEEDED(nsVariant::SetToVoid(&mData));
-    if(JSVAL_IS_NULL(val))
+    if(JSVAL_IS_NULL(mJSVal))
         return NS_SUCCEEDED(nsVariant::SetToEmpty(&mData));
-    if(JSVAL_IS_STRING(val))
+    if(JSVAL_IS_STRING(mJSVal))
     {
         // Make our string immutable.  This will also ensure null-termination,
         // which nsVariant assumes for its PRUnichar* stuff.
-        JSString* str = JSVAL_TO_STRING(val);
+        JSString* str = JSVAL_TO_STRING(mJSVal);
         if(!JS_MakeStringImmutable(ccx, str))
             return JS_FALSE;
 
         // Don't use nsVariant::SetFromWStringWithSize, because that will copy
         // the data.  Just handle this ourselves.  Note that it's ok to not
         // copy because we added mJSVal as a GC root.
         NS_ASSERTION(mData.mType == nsIDataType::VTYPE_EMPTY,
                      "Why do we already have data?");
@@ -347,19 +339,19 @@ JSBool XPCVariant::InitializeData(XPCCal
         // PRUint32 is not valid on some platforms.
         mData.u.wstr.mWStringLength = (PRUint32)length;
         mData.mType = nsIDataType::VTYPE_WSTRING_SIZE_IS;
         
         return JS_TRUE;
     }
 
     // leaving only JSObject...
-    NS_ASSERTION(JSVAL_IS_OBJECT(val), "invalid type of jsval!");
+    NS_ASSERTION(JSVAL_IS_OBJECT(mJSVal), "invalid type of jsval!");
     
-    JSObject* jsobj = JSVAL_TO_OBJECT(val);
+    JSObject* jsobj = JSVAL_TO_OBJECT(mJSVal);
 
     // Let's see if it is a xpcJSID.
 
     const nsID* id = xpc_JSObjectToID(ccx, jsobj);
     if(id)
         return NS_SUCCEEDED(nsVariant::SetFromID(&mData, *id));
     
     // Let's see if it is a js array object.
@@ -377,17 +369,17 @@ JSBool XPCVariant::InitializeData(XPCCal
         
         nsXPTType type;
         nsID id;
 
         if(!XPCArrayHomogenizer::GetTypeForArray(ccx, jsobj, len, &type, &id))
             return JS_FALSE; 
 
         if(!XPCConvert::JSArray2Native(ccx, &mData.u.array.mArrayValue, 
-                                       val, len, len,
+                                       mJSVal, len, len,
                                        type, type.IsPointer(),
                                        &id, nsnull))
             return JS_FALSE;
 
         mData.mType = nsIDataType::VTYPE_ARRAY;
         if(type.IsInterfacePointer())
             mData.u.array.mArrayInterfaceID = id;
         mData.u.array.mArrayCount = len;
--- a/js/src/xpconnect/src/xpcwrappedjs.cpp
+++ b/js/src/xpconnect/src/xpcwrappedjs.cpp
@@ -76,17 +76,17 @@ NS_CYCLE_COLLECTION_CLASSNAME(nsXPCWrapp
     // nsXPCWrappedJS keeps its own refcount artificially at or above 1, see the
     // comment above nsXPCWrappedJS::AddRef.
     cb.NoteXPCOMChild(s);
 
     if(refcnt > 1)
         // nsXPCWrappedJS roots its mJSObj when its refcount is > 1, see
         // the comment above nsXPCWrappedJS::AddRef.
         cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT,
-                           tmp->GetJSObjectPreserveColor());
+                           tmp->GetJSObject());
 
     nsXPCWrappedJS* root = tmp->GetRootWrapper();
     if(root == tmp)
         // The root wrapper keeps the aggregated native object alive.
         cb.NoteXPCOMChild(tmp->GetAggregatedNativeObject());
     else
         // Non-root wrappers keep their root alive.
         cb.NoteXPCOMChild(static_cast<nsIXPConnectWrappedJS*>(root));
@@ -257,17 +257,17 @@ do_decrement:
     return cnt;
 }
 
 void
 nsXPCWrappedJS::TraceJS(JSTracer* trc)
 {
     NS_ASSERTION(mRefCnt >= 2 && IsValid(), "must be strongly referenced");
     JS_SET_TRACING_DETAILS(trc, PrintTraceName, this, 0);
-    JS_CallTracer(trc, GetJSObjectPreserveColor(), JSTRACE_OBJECT);
+    JS_CallTracer(trc, mJSObj, JSTRACE_OBJECT);
 }
 
 #ifdef DEBUG
 // static
 void
 nsXPCWrappedJS::PrintTraceName(JSTracer* trc, char *buf, size_t bufsize)
 {
     const nsXPCWrappedJS* self = static_cast<const nsXPCWrappedJS*>
@@ -285,19 +285,19 @@ nsXPCWrappedJS::GetWeakReference(nsIWeak
 
     return nsSupportsWeakReference::GetWeakReference(aInstancePtr);
 }
 
 NS_IMETHODIMP
 nsXPCWrappedJS::GetJSObject(JSObject** aJSObj)
 {
     NS_PRECONDITION(aJSObj, "bad param");
-    NS_PRECONDITION(IsValid(), "bad wrapper");
+    NS_PRECONDITION(mJSObj, "bad wrapper");
 
-    if(!(*aJSObj = GetJSObject()))
+    if(!(*aJSObj = mJSObj))
         return NS_ERROR_OUT_OF_MEMORY;
     return NS_OK;
 }
 
 // static
 nsresult
 nsXPCWrappedJS::GetNewOrUsed(XPCCallContext& ccx,
                              JSObject* aJSObj,
@@ -622,18 +622,17 @@ nsXPCWrappedJS::SystemIsBeingShutDown(JS
 /* readonly attribute nsISimpleEnumerator enumerator; */
 NS_IMETHODIMP 
 nsXPCWrappedJS::GetEnumerator(nsISimpleEnumerator * *aEnumerate)
 {
     XPCCallContext ccx(NATIVE_CALLER);
     if(!ccx.IsValid())
         return NS_ERROR_UNEXPECTED;
 
-    return nsXPCWrappedJSClass::BuildPropertyEnumerator(ccx, GetJSObject(),
-                                                        aEnumerate);
+    return nsXPCWrappedJSClass::BuildPropertyEnumerator(ccx, mJSObj, aEnumerate);
 }
 
 /* nsIVariant getProperty (in AString name); */
 NS_IMETHODIMP 
 nsXPCWrappedJS::GetProperty(const nsAString & name, nsIVariant **_retval)
 {
     XPCCallContext ccx(NATIVE_CALLER);
     if(!ccx.IsValid())
@@ -642,17 +641,17 @@ nsXPCWrappedJS::GetProperty(const nsAStr
     nsStringBuffer* buf;
     jsval jsstr = XPCStringConvert::ReadableToJSVal(ccx, name, &buf);
     if(JSVAL_IS_NULL(jsstr))
         return NS_ERROR_OUT_OF_MEMORY;
     if(buf)
         buf->AddRef();
 
     return nsXPCWrappedJSClass::
-        GetNamedPropertyAsVariant(ccx, GetJSObject(), jsstr, _retval);
+        GetNamedPropertyAsVariant(ccx, mJSObj, jsstr, _retval);
 }
 
 /***************************************************************************/
 
 NS_IMETHODIMP
 nsXPCWrappedJS::DebugDump(PRInt16 depth)
 {
 #ifdef DEBUG
--- a/js/src/xpconnect/src/xpcwrappednative.cpp
+++ b/js/src/xpconnect/src/xpcwrappednative.cpp
@@ -117,18 +117,20 @@ NS_CYCLE_COLLECTION_CLASSNAME(XPCWrapped
         //
         // If our refcount is <= 1, our reference to the flat JS object is
         // considered "weak", and we're *not* going to traverse it.
         //
         // This reasoning is in line with the slightly confusing lifecycle rules
         // for XPCWrappedNatives, described in a larger comment below and also
         // on our wiki at http://wiki.mozilla.org/XPConnect_object_wrapping 
 
-        JSObject *obj = tmp->GetFlatJSObjectPreserveColor();
-        cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT, obj);
+        JSObject *obj = nsnull;
+        nsresult rv = tmp->GetJSObject(&obj);
+        if(NS_SUCCEEDED(rv))
+            cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT, obj);
     }
 
     XPCJSRuntime *rt = tmp->GetRuntime();
     TraverseExpandoObjectClosure closure = {
          rt->GetXPConnect()->GetCycleCollectionContext()->GetJSContext(),
          tmp,
          cb
     };
@@ -327,17 +329,17 @@ XPCWrappedNative::GetNewOrUsed(XPCCallCo
                                xpcObjectHelper& helper,
                                XPCWrappedNativeScope* Scope,
                                XPCNativeInterface* Interface,
                                JSBool isGlobal,
                                XPCWrappedNative** resultWrapper)
 {
     nsWrapperCache *cache = helper.GetWrapperCache();
 
-    NS_ASSERTION(!cache || !cache->GetWrapperPreserveColor(),
+    NS_ASSERTION(!cache || !cache->GetWrapper(),
                  "We assume the caller already checked if it could get the "
                  "wrapper from the cache.");
 
     nsresult rv;
 
     NS_ASSERTION(!Scope->GetRuntime()->GetThreadRunningGC(), 
                  "XPCWrappedNative::GetNewOrUsed called during GC");
 
@@ -390,17 +392,17 @@ XPCWrappedNative::GetNewOrUsed(XPCCallCo
                 return rv;
             }
             DEBUG_CheckWrapperThreadSafety(wrapper);
             *resultWrapper = wrapper;
             return NS_OK;
         }
     }
 #ifdef DEBUG
-    else if(!cache->GetWrapperPreserveColor())
+    else if(!cache->GetWrapper())
     {   // scoped lock
         XPCAutoLock lock(mapLock);
         NS_ASSERTION(!map->Find(identity),
                      "There's a wrapper in the hashtable but it wasn't cached?");
     }
 #endif
 
     // There is a chance that the object wants to have the self-same JSObject
@@ -668,23 +670,23 @@ FinishCreate(XPCCallContext& ccx,
 
     if(wrapperToKill)
     {
         // Second reference will be released by the FlatJSObject's finializer.
         wrapperToKill->Release();
     }
     else if(wrapper)
     {
-        JSObject *flat = wrapper->GetFlatJSObject();
-        NS_ASSERTION(!cache || !cache->GetWrapperPreserveColor() ||
-                     flat == cache->GetWrapperPreserveColor(),
+        JSObject *flat = wrapper->GetFlatJSObjectAndMark();
+        NS_ASSERTION(!cache || !cache->GetWrapper() ||
+                     flat == cache->GetWrapper(),
                      "This object has a cached wrapper that's different from "
                      "the JSObject held by its native wrapper?");
 
-        if(cache && !cache->GetWrapperPreserveColor())
+        if(cache && !cache->GetWrapper())
             cache->SetWrapper(flat);
 
         // Our newly created wrapper is the one that we just added to the table.
         // All is well. Call PostCreate as necessary.
         XPCNativeScriptableInfo* si = wrapper->GetScriptableInfo();
         if(si && si->GetFlags().WantPostCreate())
         {
             nsresult rv = si->GetCallback()->PostCreate(wrapper, ccx, flat);
@@ -1504,17 +1506,17 @@ XPCWrappedNative::ReparentWrapperIfFound
     }
     else
     {
         rv = XPCWrappedNative::GetUsedOnly(ccx, aCOMObj, aOldScope, iface,
                                            getter_AddRefs(wrapper));
         if(NS_FAILED(rv))
             return rv;
 
-        flat = wrapper->GetFlatJSObject();
+        flat = wrapper->GetFlatJSObjectAndMark();
     }
 
     if(!flat)
     {
         *aWrapper = nsnull;
         return NS_OK;
     }
 
@@ -3101,17 +3103,17 @@ CallMethodHelper::Invoke()
 }
 
 /***************************************************************************/
 // interface methods
 
 /* readonly attribute JSObjectPtr JSObject; */
 NS_IMETHODIMP XPCWrappedNative::GetJSObject(JSObject * *aJSObject)
 {
-    *aJSObject = GetFlatJSObject();
+    *aJSObject = GetFlatJSObjectAndMark();
     return NS_OK;
 }
 
 /* readonly attribute nsISupports Native; */
 NS_IMETHODIMP XPCWrappedNative::GetNative(nsISupports * *aNative)
 {
     // No need to QI here, we already have the correct nsISupports
     // vtable.
@@ -3119,17 +3121,17 @@ NS_IMETHODIMP XPCWrappedNative::GetNativ
     NS_ADDREF(*aNative);
     return NS_OK;
 }
 
 /* reaonly attribute JSObjectPtr JSObjectPrototype; */
 NS_IMETHODIMP XPCWrappedNative::GetJSObjectPrototype(JSObject * *aJSObjectPrototype)
 {
     *aJSObjectPrototype = HasProto() ?
-                GetProto()->GetJSProtoObject() : GetFlatJSObject();
+                GetProto()->GetJSProtoObject() : GetFlatJSObjectAndMark();
     return NS_OK;
 }
 
 #ifndef XPCONNECT_STANDALONE
 nsIPrincipal*
 XPCWrappedNative::GetObjectPrincipal() const
 {
     nsIPrincipal* principal = GetScope()->GetPrincipal();
@@ -3203,17 +3205,17 @@ NS_IMETHODIMP XPCWrappedNative::RefreshP
 
     if(!HasProto())
         return NS_OK;
 
     if(!mFlatJSObject)
         return UnexpectedFailure(NS_ERROR_FAILURE);
 
     JSAutoEnterCompartment ac;
-    if(!ac.enter(ccx, GetFlatJSObject()))
+    if(!ac.enter(ccx, GetFlatJSObjectAndMark()))
         return UnexpectedFailure(NS_ERROR_FAILURE);
 
     AutoMarkingWrappedNativeProtoPtr oldProto(ccx);
     AutoMarkingWrappedNativeProtoPtr newProto(ccx);
 
     oldProto = GetProto();
 
     XPCNativeScriptableInfo *info = oldProto->GetScriptableInfo();
@@ -3227,17 +3229,17 @@ NS_IMETHODIMP XPCWrappedNative::RefreshP
     if(!newProto)
         return UnexpectedFailure(NS_ERROR_FAILURE);
 
     // If nothing needs to change then we're done.
 
     if(newProto.get() == oldProto.get())
         return NS_OK;
 
-    if(!JS_SetPrototype(ccx, GetFlatJSObject(),
+    if(!JS_SetPrototype(ccx, GetFlatJSObjectAndMark(),
                         newProto->GetJSProtoObject()))
         return UnexpectedFailure(NS_ERROR_FAILURE);
 
     SetProto(newProto);
 
     if(mScriptableInfo == oldProto->GetScriptableInfo())
         mScriptableInfo = newProto->GetScriptableInfo();
 
--- a/js/src/xpconnect/src/xpcwrappednativescope.cpp
+++ b/js/src/xpconnect/src/xpcwrappednativescope.cpp
@@ -358,17 +358,17 @@ XPCWrappedNativeScope::GetPrototypeNoHel
 static JSDHashOperator
 WrappedNativeJSGCThingTracer(JSDHashTable *table, JSDHashEntryHdr *hdr,
                              uint32 number, void *arg)
 {
     XPCWrappedNative* wrapper = ((Native2WrappedNativeMap::Entry*)hdr)->value;
     if(wrapper->HasExternalReference() && !wrapper->IsWrapperExpired())
     {
         JSTracer* trc = (JSTracer *)arg;
-        JS_CALL_OBJECT_TRACER(trc, wrapper->GetFlatJSObjectPreserveColor(),
+        JS_CALL_OBJECT_TRACER(trc, wrapper->GetFlatJSObjectNoMark(),
                               "XPCWrappedNative::mFlatJSObject");
     }
 
     return JS_DHASH_NEXT;
 }
 
 // static
 void
--- a/modules/plugin/base/src/nsJSNPRuntime.cpp
+++ b/modules/plugin/base/src/nsJSNPRuntime.cpp
@@ -51,17 +51,16 @@
 #include "nsDOMJSUtils.h"
 #include "nsIDocument.h"
 #include "nsIJSRuntimeService.h"
 #include "nsIJSContextStack.h"
 #include "nsIXPConnect.h"
 #include "nsIDOMElement.h"
 #include "prmem.h"
 #include "nsIContent.h"
-#include "xpcpublic.h"
 
 using namespace mozilla::plugins::parent;
 
 #ifdef MOZ_IPC
 #include "mozilla/plugins/PluginScriptableObjectParent.h"
 using mozilla::plugins::PluginScriptableObjectParent;
 using mozilla::plugins::ParentNPObject;
 #endif