Bug 720536 - unmark ELM listeners, r=mccr8
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Thu, 26 Jan 2012 15:45:12 +0100
changeset 86669 4fc8228cbfa50e55afca11118c3c9d76cf7e426c
parent 86668 ee2d438cdd77712ae9e9b8f0a945144c7e6796ae
child 86670 2bfef4ad7ad37a71fd5f5b3e8dfc0cc4650f7d31
push id805
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 18:17:35 +0000
treeherdermozilla-aurora@6fb3bf232436 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmccr8
bugs720536
milestone12.0a1
Bug 720536 - unmark ELM listeners, r=mccr8
content/events/src/nsDOMEventTargetHelper.h
content/events/src/nsEventListenerManager.cpp
content/events/src/nsEventListenerManager.h
--- a/content/events/src/nsDOMEventTargetHelper.h
+++ b/content/events/src/nsDOMEventTargetHelper.h
@@ -99,9 +99,16 @@ public:
   }
 protected:
   nsRefPtr<nsEventListenerManager> mListenerManager;
   // These may be null (native callers or xpcshell).
   nsCOMPtr<nsIScriptContext> mScriptContext;
   nsCOMPtr<nsPIDOMWindow>    mOwner; // Inner window.
 };
 
+#define NS_UNMARK_LISTENER_WRAPPER(_event)                       \
+  if (tmp->mOn##_event##Listener) {                              \
+    nsCOMPtr<nsIXPConnectWrappedJS> wjs =                        \
+      do_QueryInterface(tmp->mOn##_event##Listener->GetInner()); \
+    xpc_UnmarkGrayObject(wjs);                                   \
+  }
+
 #endif // nsDOMEventTargetHelper_h_
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -77,16 +77,17 @@
 #include "nsDOMJSUtils.h"
 #include "nsDOMScriptObjectHolder.h"
 #include "nsDataHashtable.h"
 #include "nsCOMArray.h"
 #include "nsEventListenerService.h"
 #include "nsDOMEvent.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsJSEnvironment.h"
+#include "xpcpublic.h"
 #include "sampler.h"
 
 using namespace mozilla::dom;
 
 #define EVENT_TYPE_EQUALS( ls, type, userType ) \
   (ls->mEventType == type && \
   (ls->mEventType != NS_USER_DEFINED_EVENT || ls->mTypeAtom == userType))
 
@@ -235,19 +236,24 @@ nsEventListenerManager::AddEventListener
 
   mNoListenerForEvent = NS_EVENT_TYPE_NULL;
   mNoListenerForEventAtom = nsnull;
 
   ls = mListeners.AppendElement();
   ls->mListener = aListener;
   ls->mEventType = aType;
   ls->mTypeAtom = aTypeAtom;
+  ls->mWrappedJS = false;
   ls->mFlags = aFlags;
   ls->mHandlerIsString = false;
 
+  nsCOMPtr<nsIXPConnectWrappedJS> wjs = do_QueryInterface(aListener);
+  if (wjs) {
+    ls->mWrappedJS = true;
+  }
   if (aFlags & NS_EVENT_FLAG_SYSTEM_EVENT) {
     mMayHaveSystemGroupListeners = true;
   }
   if (aFlags & NS_EVENT_FLAG_CAPTURE) {
     mMayHaveCapturingListeners = true;
   }
 
   if (aType == NS_AFTERPAINT) {
@@ -1008,8 +1014,25 @@ nsEventListenerManager::SizeOf() const
     size += sizeof(ls);
     nsIJSEventListener* jsl = ls.GetJSListener();
     if (jsl) {
       size += jsl->SizeOf();
     }
   }
   return size;
 }
+
+void
+nsEventListenerManager::UnmarkGrayJSListeners()
+{
+  PRUint32 count = mListeners.Length();
+  for (PRUint32 i = 0; i < count; ++i) {
+    const nsListenerStruct& ls = mListeners.ElementAt(i);
+    nsIJSEventListener* jsl = ls.GetJSListener();
+    if (jsl) {
+      xpc_UnmarkGrayObject(jsl->GetHandler());
+      xpc_UnmarkGrayObject(jsl->GetEventScope());
+    } else if (ls.mWrappedJS) {
+      nsCOMPtr<nsIXPConnectWrappedJS> wjs = do_QueryInterface(ls.mListener);
+      xpc_UnmarkGrayObject(wjs);
+    }
+  }
+}
--- a/content/events/src/nsEventListenerManager.h
+++ b/content/events/src/nsEventListenerManager.h
@@ -65,16 +65,17 @@ class nsIDocument;
 
 struct nsListenerStruct
 {
   nsRefPtr<nsIDOMEventListener> mListener;
   PRUint32                      mEventType;
   nsCOMPtr<nsIAtom>             mTypeAtom;
   PRUint16                      mFlags;
   bool                          mHandlerIsString;
+  bool                          mWrappedJS;
 
   nsIJSEventListener* GetJSListener() const {
     return (mFlags & NS_PRIV_EVENT_FLAG_SCRIPT) ?
       static_cast<nsIJSEventListener *>(mListener.get()) : nsnull;
   }
 
   ~nsListenerStruct()
   {
@@ -238,16 +239,19 @@ public:
    * Returns true if there may be a touch event listener registered,
    * false if there definitely isn't.
    */
   bool MayHaveTouchEventListener() { return mMayHaveTouchEventListener; }
 
   bool MayHaveMouseEnterLeaveEventListener() { return mMayHaveMouseEnterLeaveEventListener; }
 
   PRInt64 SizeOf() const;
+
+  void UnmarkGrayJSListeners();
+
 protected:
   nsresult HandleEventSubType(nsListenerStruct* aListenerStruct,
                               nsIDOMEventListener* aListener,
                               nsIDOMEvent* aDOMEvent,
                               nsIDOMEventTarget* aCurrentTarget,
                               PRUint32 aPhaseFlags,
                               nsCxPusher* aPusher);