mshtml: Make node object cycle collector aware.

This commit is contained in:
Jacek Caban 2012-07-19 11:28:35 +02:00 committed by Alexandre Julliard
parent 4c7e608d5c
commit 97ff991f46
4 changed files with 112 additions and 7 deletions

View File

@ -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

View File

@ -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;

View File

@ -345,6 +345,21 @@ static BOOL load_xul(const PRUnichar *gre_path)
NS_DLSYM(NS_StringGetData);
NS_DLSYM(NS_CStringGetData);
#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;
}

View File

@ -3448,6 +3448,13 @@ interface nsIDocumentObserver : nsIMutationObserver
void AttemptToExecuteScript(nsIContent *aContent, nsIParser *aParser, bool *aBlock);
}
[
object,
uuid(c61eac14-5f7a-4481-965e-7eaa6effa85f),
local
]
interface nsCycleCollectionISupports {}
[
object,
uuid(3682dd99-8560-44f4-9b8f-ccce9d7b96fb),