diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -166,27 +166,31 @@ static PRLogModuleInfo* gJSDiagnostics;
 #define NS_COLLECTED_OBJECTS_LIMIT  5000
 // CC will be called if GC has been called at least this number of times and
 // there are at least NS_MIN_SUSPECT_CHANGES new suspected objects.
 #define NS_MAX_GC_COUNT             5
 #define NS_MIN_SUSPECT_CHANGES      10
 // CC will be called if there are at least NS_MAX_SUSPECT_CHANGES new suspected
 // objects.
 #define NS_MAX_SUSPECT_CHANGES      100
+// CC will be called if there are at least NS_MAX_NEW_WRAPPED_NATIVES
+// new XPCWrapperNative objects since the previous CC call.
+#define NS_MAX_NEW_WRAPPED_NATIVES  5000
 
 // if you add statics here, add them to the list in nsJSRuntime::Startup
 
 static PRUint32 sDelayedCCollectCount;
 static PRUint32 sCCollectCount;
 static PRBool sUserIsActive;
 static PRTime sPreviousCCTime;
 static PRUint32 sCollectedObjectsCounts;
 static PRUint32 sSavedGCCount;
 static PRUint32 sCCSuspectChanges;
 static PRUint32 sCCSuspectedCount;
+static PRInt32 sWrappedNatives;
 static nsITimer *sGCTimer;
 static PRBool sReadyForGC;
 
 // The number of currently pending document loads. This count isn't
 // guaranteed to always reflect reality and can't easily as we don't
 // have an easy place to know when a load ends or is interrupted in
 // all cases. This counter also gets reset if we end up GC'ing while
 // we're waiting for a slow page to load. IOW, this count may be 0
@@ -3508,16 +3512,20 @@ nsJSContext::CC()
   sPreviousCCTime = PR_Now();
   sDelayedCCollectCount = 0;
   sCCSuspectChanges = 0;
   // nsCycleCollector_collect() will run a ::JS_GC() indirectly, so
   // we do not explicitly call ::JS_GC() here.
   sCollectedObjectsCounts = nsCycleCollector_collect();
   sCCSuspectedCount = nsCycleCollector_suspectedCount();
   sSavedGCCount = JS_GetGCParameter(nsJSRuntime::sRuntime, JSGC_NUMBER);
+  nsIXPConnect* xpc = nsContentUtils::XPConnect();
+  if (xpc) {
+    sWrappedNatives = xpc->GetWrappedNativeCount();
+  }
 #ifdef DEBUG_smaug
   printf("Collected %u objects, %u suspected objects, took %lldms\n",
          sCollectedObjectsCounts, sCCSuspectedCount,
          (PR_Now() - sPreviousCCTime) / PR_USEC_PER_MSEC);
 #endif
 }
 
 static inline uint32
@@ -3554,33 +3562,44 @@ nsJSContext::MaybeCC(PRBool aHigherProba
             sCCSuspectedCount);
 #endif
     // Update only when suspected count has increased.
     if (suspected > sCCSuspectedCount) {
       sCCSuspectChanges += (suspected - sCCSuspectedCount);
       sCCSuspectedCount = suspected;
     }
   }
-#ifdef DEBUG_smaug
-  printf("sCCSuspectChanges %u, GC runs %u\n",
-         sCCSuspectChanges, GetGCRunsSinceLastCC());
-#endif
 
   // Increase the probability also if the previous call to cycle collector
   // collected something.
   if (aHigherProbability ||
       sCollectedObjectsCounts > NS_COLLECTED_OBJECTS_LIMIT) {
     sDelayedCCollectCount *= NS_PROBABILITY_MULTIPLIER;
   }
 
+  nsIXPConnect* xpc = nsContentUtils::XPConnect();
+  PRInt32 newWrappedNatives = 0;
+  if (xpc) {
+    PRInt32 count = xpc->GetWrappedNativeCount();
+    if (count > sWrappedNatives) {
+      newWrappedNatives = count - sWrappedNatives;
+    }
+  }
+#ifdef DEBUG_smaug
+  printf("sCCSuspectChanges %u, GC runs %u, sWrappedNatives %i (new %i) \n",
+         sCCSuspectChanges, GetGCRunsSinceLastCC(), sWrappedNatives,
+         newWrappedNatives);
+#endif
+
   if (!sGCTimer &&
-      (sDelayedCCollectCount > NS_MAX_DELAYED_CCOLLECT) &&
-      ((sCCSuspectChanges > NS_MIN_SUSPECT_CHANGES &&
-        GetGCRunsSinceLastCC() > NS_MAX_GC_COUNT) ||
-       (sCCSuspectChanges > NS_MAX_SUSPECT_CHANGES))) {
+      (((sDelayedCCollectCount > NS_MAX_DELAYED_CCOLLECT) &&
+       ((sCCSuspectChanges > NS_MIN_SUSPECT_CHANGES &&
+         GetGCRunsSinceLastCC() > NS_MAX_GC_COUNT) ||
+        (sCCSuspectChanges > NS_MAX_SUSPECT_CHANGES))) ||
+       (newWrappedNatives > NS_MAX_NEW_WRAPPED_NATIVES))) {
     return IntervalCC();
   }
   return PR_FALSE;
 }
 
 //static
 void
 nsJSContext::CCIfUserInactive()
@@ -3799,16 +3818,17 @@ nsJSRuntime::Startup()
   sDelayedCCollectCount = 0;
   sCCollectCount = 0;
   sUserIsActive = PR_FALSE;
   sPreviousCCTime = 0;
   sCollectedObjectsCounts = 0;
   sSavedGCCount = 0;
   sCCSuspectChanges = 0;
   sCCSuspectedCount = 0;
+  sWrappedNatives = 0;
   sGCTimer = nsnull;
   sReadyForGC = PR_FALSE;
   sLoadInProgressGCTimer = PR_FALSE;
   sPendingLoadCount = 0;
   gNameSpaceManager = nsnull;
   sRuntimeService = nsnull;
   sRuntime = nsnull;
   gOldJSGCCallback = nsnull;
diff --git a/js/src/xpconnect/idl/nsIXPConnect.idl b/js/src/xpconnect/idl/nsIXPConnect.idl
--- a/js/src/xpconnect/idl/nsIXPConnect.idl
+++ b/js/src/xpconnect/idl/nsIXPConnect.idl
@@ -389,17 +389,17 @@ interface nsIXPCFunctionThisTranslator :
 %{ C++
 // For use with the service manager
 // {CB6593E0-F9B2-11d2-BDD6-000064657374}
 #define NS_XPCONNECT_CID \
 { 0xcb6593e0, 0xf9b2, 0x11d2, \
     { 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
 %}
 
-[uuid(c29f5d27-21b1-4b87-8282-d724d535ef7b)]
+[uuid(80711095-3b9a-4d87-bfbb-8a74c164b3f7)]
 interface nsIXPConnect : nsISupports
 {
 %{ C++
   NS_DEFINE_STATIC_CID_ACCESSOR(NS_XPCONNECT_CID)
 %}
 
     /**
      * Initializes classes on a global object that has already been created.
@@ -854,10 +854,15 @@ interface nsIXPConnect : nsISupports
      * Get the object principal for this wrapper.  Note that this may well end
      * up being null; in that case one should seek principals elsewhere.  Null
      * here does NOT indicate system principal or no principals at all, just
      * that this wrapper doesn't have an intrinsic one.
      */
     virtual nsIPrincipal* GetPrincipal(JSObject* obj,
                                        PRBool allowShortCircuit) const = 0;
 #endif
+
+    /**
+     * Returns the number of alive XPCWrappedNative objects.
+     */
+    virtual PRInt32 GetWrappedNativeCount() const = 0;
 %}
 };
diff --git a/js/src/xpconnect/src/nsXPConnect.cpp b/js/src/xpconnect/src/nsXPConnect.cpp
--- a/js/src/xpconnect/src/nsXPConnect.cpp
+++ b/js/src/xpconnect/src/nsXPConnect.cpp
@@ -2692,16 +2692,22 @@ nsXPConnect::GetPrincipal(JSObject* obj,
                 return result;
             }
         }
     }
 
     return nsnull;
 }
 
+PRInt32
+nsXPConnect::GetWrappedNativeCount() const
+{
+  return XPCWrappedNative::sXPCWrappedNativeCount;
+}
+
 /* These are here to be callable from a debugger */
 JS_BEGIN_EXTERN_C
 JS_EXPORT_API(void) DumpJSStack()
 {
     nsresult rv;
     nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
     if(NS_SUCCEEDED(rv) && xpc)
         xpc->DebugDumpJSStack(PR_TRUE, PR_TRUE, PR_FALSE);
diff --git a/js/src/xpconnect/src/xpcprivate.h b/js/src/xpconnect/src/xpcprivate.h
--- a/js/src/xpconnect/src/xpcprivate.h
+++ b/js/src/xpconnect/src/xpcprivate.h
@@ -551,16 +551,19 @@ public:
     static nsCycleCollectionParticipant *JSContextParticipant();
 
 #ifndef XPCONNECT_STANDALONE
     virtual nsIPrincipal* GetPrincipal(JSObject* obj,
                                        PRBool allowShortCircuit) const;
 
     void RecordTraversal(void *p, nsISupports *s);
 #endif
+
+    virtual PRInt32 GetWrappedNativeCount() const;
+
     static PRBool ReportAllJSExceptions()
     {
       return gReportAllJSExceptions > 0;
     }
 
 #ifdef XPC_IDISPATCH_SUPPORT
 public:
     static PRBool IsIDispatchEnabled();
@@ -2388,16 +2391,17 @@ public:
 
     XPCLock*
     GetLock() const {return IsValid() && HasProto() ?
                                 GetProto()->GetLock() : nsnull;}
 
     XPCNativeSet*
     GetSet() const {XPCAutoLock al(GetLock()); return mSet;}
 
+    static PRInt32 sXPCWrappedNativeCount;
 private:
     void
     SetSet(XPCNativeSet* set) {XPCAutoLock al(GetLock()); mSet = set;}
 
     inline void
     ExpireWrapper()
         {mMaybeScope = (XPCWrappedNativeScope*)
                        (XPC_SCOPE_WORD(mMaybeScope) | XPC_WRAPPER_EXPIRED);}
diff --git a/js/src/xpconnect/src/xpcwrappednative.cpp b/js/src/xpconnect/src/xpcwrappednative.cpp
--- a/js/src/xpconnect/src/xpcwrappednative.cpp
+++ b/js/src/xpconnect/src/xpcwrappednative.cpp
@@ -836,31 +836,34 @@ XPCWrappedNative::GetUsedOnly(XPCCallCon
         NS_ASSERTION(NS_FAILED(rv), "returning NS_OK on failure");
         return rv;
     }
 
     *resultWrapper = wrapper;
     return NS_OK;
 }
 
+PRInt32 XPCWrappedNative::sXPCWrappedNativeCount = 0;
+
 // This ctor is used if this object will have a proto.
 XPCWrappedNative::XPCWrappedNative(already_AddRefed<nsISupports> aIdentity,
                                    XPCWrappedNativeProto* aProto)
     : mMaybeProto(aProto),
       mSet(aProto->GetSet()),
       mFlatJSObject((JSObject*)JSVAL_ONE), // non-null to pass IsValid() test
       mScriptableInfo(nsnull),
       mWrapperWord(0)
 {
     mIdentity = aIdentity.get();
 
     NS_ASSERTION(mMaybeProto, "bad ctor param");
     NS_ASSERTION(mSet, "bad ctor param");
 
     DEBUG_TrackNewWrapper(this);
+    PR_AtomicIncrement(&sXPCWrappedNativeCount);
 }
 
 // This ctor is used if this object will NOT have a proto.
 XPCWrappedNative::XPCWrappedNative(already_AddRefed<nsISupports> aIdentity,
                                    XPCWrappedNativeScope* aScope,
                                    XPCNativeSet* aSet)
 
     : mMaybeScope(TagScope(aScope)),
@@ -870,21 +873,23 @@ XPCWrappedNative::XPCWrappedNative(alrea
       mWrapperWord(0)
 {
     mIdentity = aIdentity.get();
 
     NS_ASSERTION(aScope, "bad ctor param");
     NS_ASSERTION(aSet, "bad ctor param");
 
     DEBUG_TrackNewWrapper(this);
+    PR_AtomicIncrement(&sXPCWrappedNativeCount);
 }
 
 XPCWrappedNative::~XPCWrappedNative()
 {
     DEBUG_TrackDeleteWrapper(this);
+    PR_AtomicDecrement(&sXPCWrappedNativeCount);
 
     XPCWrappedNativeProto* proto = GetProto();
 
     if(mScriptableInfo &&
        (!HasProto() ||
         (proto && proto->GetScriptableInfo() != mScriptableInfo)))
     {
         delete mScriptableInfo;
