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