From 97ff991f463ef129340c0ec917d8cbf70e57856e Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Thu, 19 Jul 2012 11:28:35 +0200 Subject: [PATCH] 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 39514943da3..f33df64df2e 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 e2d347c6d77..efa6f52984d 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 70bdfa7c1b9..8ff7ad2991a 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 04d77d5b61f..13748b9d825 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 ] -- 2.11.4.GIT