Jacek Caban : mshtml: Make node object cycle collector aware.

Alexandre Julliard julliard at winehq.org
Thu Jul 19 13:23:44 CDT 2012


Module: wine
Branch: master
Commit: 97ff991f463ef129340c0ec917d8cbf70e57856e
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=97ff991f463ef129340c0ec917d8cbf70e57856e

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Thu Jul 19 11:28:35 2012 +0200

mshtml: Make node object cycle collector aware.

---

 dlls/mshtml/htmlnode.c       |   65 ++++++++++++++++++++++++++++++++++++++----
 dlls/mshtml/mshtml_private.h |   30 ++++++++++++++++++-
 dlls/mshtml/nsembed.c        |   17 +++++++++++
 dlls/mshtml/nsiface.idl      |    7 ++++
 4 files changed, 112 insertions(+), 7 deletions(-)

diff --git a/dlls/mshtml/htmlnode.c b/dlls/mshtml/htmlnode.c
index 3951494..f33df64 100644
--- a/dlls/mshtml/htmlnode.c
+++ b/dlls/mshtml/htmlnode.c
@@ -312,7 +312,7 @@ static HRESULT WINAPI HTMLDOMNode_QueryInterface(IHTMLDOMNode *iface,
 static ULONG WINAPI HTMLDOMNode_AddRef(IHTMLDOMNode *iface)
 {
     HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
-    LONG ref = InterlockedIncrement(&This->ref);
+    LONG ref = ccref_incr(&This->ccref, (nsISupports*)&This->IHTMLDOMNode_iface);
 
     TRACE("(%p) ref=%d\n", This, ref);
 
@@ -322,7 +322,7 @@ static ULONG WINAPI HTMLDOMNode_AddRef(IHTMLDOMNode *iface)
 static ULONG WINAPI HTMLDOMNode_Release(IHTMLDOMNode *iface)
 {
     HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
-    LONG ref = InterlockedDecrement(&This->ref);
+    LONG ref = ccref_decr(&This->ccref, (nsISupports*)&This->IHTMLDOMNode_iface);
 
     TRACE("(%p) ref=%d\n", This, ref);
 
@@ -977,6 +977,8 @@ static const IHTMLDOMNode2Vtbl HTMLDOMNode2Vtbl = {
     HTMLDOMNode2_get_ownerDocument
 };
 
+static nsXPCOMCycleCollectionParticipant node_ccp;
+
 HRESULT HTMLDOMNode_QI(HTMLDOMNode *This, REFIID riid, void **ppv)
 {
     *ppv = NULL;
@@ -1001,6 +1003,14 @@ HRESULT HTMLDOMNode_QI(HTMLDOMNode *This, REFIID riid, void **ppv)
     }else if(IsEqualGUID(&IID_IHTMLDOMNode2, riid)) {
         TRACE("(%p)->(IID_IHTMLDOMNode2 %p)\n", This, ppv);
         *ppv = &This->IHTMLDOMNode2_iface;
+    }else if(IsEqualGUID(&IID_nsXPCOMCycleCollectionParticipant, riid)) {
+        TRACE("(%p)->(IID_nsXPCOMCycleCollectionParticipant %p)\n", This, ppv);
+        *ppv = &node_ccp;
+        return NS_OK;
+    }else if(IsEqualGUID(&IID_nsCycleCollectionISupports, riid)) {
+        TRACE("(%p)->(IID_nsCycleCollectionISupports %p)\n", This, ppv);
+        *ppv = &This->IHTMLDOMNode_iface;
+        return NS_OK;
     }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
         return *ppv ? S_OK : E_NOINTERFACE;
     }
@@ -1037,12 +1047,9 @@ void HTMLDOMNode_Init(HTMLDocumentNode *doc, HTMLDOMNode *node, nsIDOMNode *nsno
 {
     node->IHTMLDOMNode_iface.lpVtbl = &HTMLDOMNodeVtbl;
     node->IHTMLDOMNode2_iface.lpVtbl = &HTMLDOMNode2Vtbl;
-    node->ref = 2;
+    ccref_init(&node->ccref, &doc->node != node ? 2 : 1);
     node->doc = doc;
 
-    if(&doc->node != node)
-        node->ref++; /* one extra for list entry reference */
-
     if(nsnode)
         nsIDOMNode_AddRef(nsnode);
     node->nsnode = nsnode;
@@ -1100,6 +1107,52 @@ static HRESULT create_node(HTMLDocumentNode *doc, nsIDOMNode *nsnode, HTMLDOMNod
     return S_OK;
 }
 
+static void NSAPI HTMLDOMNode_unmark_if_purple(void *p)
+{
+    HTMLDOMNode *This = impl_from_IHTMLDOMNode(p);
+    ccref_unmark_if_purple(&This->ccref);
+}
+
+static nsresult NSAPI HTMLDOMNode_traverse(void *ccp, void *p, nsCycleCollectionTraversalCallback *cb)
+{
+    HTMLDOMNode *This = impl_from_IHTMLDOMNode(p);
+
+    TRACE("%p\n", This);
+
+    describe_cc_node(&This->ccref, sizeof(*This), "HTMLDOMNode", cb);
+
+    if(This->nsnode)
+        note_cc_edge((nsISupports*)This->nsnode, "This->nsnode", cb);
+
+    return NS_OK;
+}
+
+static nsresult NSAPI HTMLDOMNode_unlink(void *p)
+{
+    HTMLDOMNode *This = impl_from_IHTMLDOMNode(p);
+
+    TRACE("%p\n", This);
+
+    if(This->nsnode) {
+        nsIDOMNode *nsnode = This->nsnode;
+        This->nsnode = NULL;
+        nsIDOMNode_Release(nsnode);
+    }
+
+    return NS_OK;
+}
+
+void init_node_cc(void)
+{
+    static const CCObjCallback node_ccp_callback = {
+        HTMLDOMNode_unmark_if_purple,
+        HTMLDOMNode_traverse,
+        HTMLDOMNode_unlink
+    };
+
+    ccp_init(&node_ccp, &node_ccp_callback);
+}
+
 /*
  * FIXME
  * List looks really ugly here. We should use a better data structure or
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h
index e2d347c..efa6f52 100644
--- a/dlls/mshtml/mshtml_private.h
+++ b/dlls/mshtml/mshtml_private.h
@@ -225,6 +225,32 @@ struct DispatchEx {
     dispex_dynamic_data_t *dynamic_data;
 };
 
+typedef struct {
+    void *x;
+} nsCycleCollectingAutoRefCnt;
+
+typedef struct {
+    void *x[3];
+} nsXPCOMCycleCollectionParticipant;
+
+typedef struct nsCycleCollectionTraversalCallback nsCycleCollectionTraversalCallback;
+
+typedef struct {
+    void (NSAPI *unmark_if_purple)(void*);
+    nsresult (NSAPI *traverse)(void*,void*,nsCycleCollectionTraversalCallback*);
+    nsresult (NSAPI *unlink)(void*);
+} CCObjCallback;
+
+DEFINE_GUID(IID_nsXPCOMCycleCollectionParticipant, 0x9674489b,0x1f6f,0x4550,0xa7,0x30, 0xcc,0xae,0xdd,0x10,0x4c,0xf9);
+
+nsrefcnt (__cdecl *ccref_incr)(nsCycleCollectingAutoRefCnt*,nsISupports*);
+nsrefcnt (__cdecl *ccref_decr)(nsCycleCollectingAutoRefCnt*,nsISupports*);
+void (__cdecl *ccref_init)(nsCycleCollectingAutoRefCnt*,nsrefcnt);
+void (__cdecl *ccref_unmark_if_purple)(nsCycleCollectingAutoRefCnt*);
+void (__cdecl *ccp_init)(nsXPCOMCycleCollectionParticipant*,const CCObjCallback*);
+void (__cdecl *describe_cc_node)(nsCycleCollectingAutoRefCnt*,size_t,const char*,nsCycleCollectionTraversalCallback*);
+void (__cdecl *note_cc_edge)(nsISupports*,const char*,nsCycleCollectionTraversalCallback*);
+
 void init_dispex(DispatchEx*,IUnknown*,dispex_static_data_t*) DECLSPEC_HIDDEN;
 void release_dispex(DispatchEx*) DECLSPEC_HIDDEN;
 BOOL dispex_query_interface(DispatchEx*,REFIID,void**) DECLSPEC_HIDDEN;
@@ -567,7 +593,7 @@ struct HTMLDOMNode {
     IHTMLDOMNode2 IHTMLDOMNode2_iface;
     const NodeImplVtbl *vtbl;
 
-    LONG ref;
+    nsCycleCollectingAutoRefCnt ccref;
 
     nsIDOMNode *nsnode;
     HTMLDocumentNode *doc;
@@ -723,6 +749,8 @@ void init_nsio(nsIComponentManager*,nsIComponentRegistrar*) DECLSPEC_HIDDEN;
 void release_nsio(void) DECLSPEC_HIDDEN;
 BOOL is_gecko_path(const char*) DECLSPEC_HIDDEN;
 
+void init_node_cc(void);
+
 HRESULT nsuri_to_url(LPCWSTR,BOOL,BSTR*) DECLSPEC_HIDDEN;
 BOOL compare_ignoring_frag(IUri*,IUri*) DECLSPEC_HIDDEN;
 
diff --git a/dlls/mshtml/nsembed.c b/dlls/mshtml/nsembed.c
index 70bdfa7..8ff7ad2 100644
--- a/dlls/mshtml/nsembed.c
+++ b/dlls/mshtml/nsembed.c
@@ -347,6 +347,21 @@ static BOOL load_xul(const PRUnichar *gre_path)
 
 #undef NS_DLSYM
 
+#define NS_DLSYM(func) \
+    func = (void *)GetProcAddress(xul_handle, #func); \
+    if(!func) \
+        ERR("Could not GetProcAddress(" #func ") failed\n")
+
+    NS_DLSYM(ccref_incr);
+    NS_DLSYM(ccref_decr);
+    NS_DLSYM(ccref_init);
+    NS_DLSYM(ccref_unmark_if_purple);
+    NS_DLSYM(ccp_init);
+    NS_DLSYM(describe_cc_node);
+    NS_DLSYM(note_cc_edge);
+
+#undef NS_DLSYM
+
     return TRUE;
 }
 
@@ -561,6 +576,8 @@ static BOOL init_xpcom(const PRUnichar *gre_path)
         nsIComponentRegistrar_Release(registrar);
     }
 
+    init_node_cc();
+
     return TRUE;
 }
 
diff --git a/dlls/mshtml/nsiface.idl b/dlls/mshtml/nsiface.idl
index 04d77d5..13748b9 100644
--- a/dlls/mshtml/nsiface.idl
+++ b/dlls/mshtml/nsiface.idl
@@ -3450,6 +3450,13 @@ interface nsIDocumentObserver : nsIMutationObserver
 
 [
     object,
+    uuid(c61eac14-5f7a-4481-965e-7eaa6effa85f),
+    local
+]
+interface nsCycleCollectionISupports {}
+
+[
+    object,
     uuid(3682dd99-8560-44f4-9b8f-ccce9d7b96fb),
     local
 ]




More information about the wine-cvs mailing list