Fix for bug 437449 (top crash [@ nsCycleCollector::MarkRoots(GCGraphBuilder&)][@ nsBaseContentList::cycleCollection::Traverse(void*, nsCycleCollectionTraversalCallback&)]). r=jst, a=blocking1.9.2+.

--HG--
extra : rebase_source : 5358561a463757cbfb77c542760dc1ea95fc6b82
This commit is contained in:
Peter Van der Beken 2009-11-29 09:32:39 +01:00
parent fa805f174f
commit 41824cb4bf
8 changed files with 136 additions and 46 deletions

View File

@ -1163,6 +1163,11 @@ public:
*/
static nsresult DropJSObjects(void* aScriptObjectHolder);
#ifdef DEBUG
static void CheckCCWrapperTraversal(nsISupports* aScriptObjectHolder,
nsWrapperCache* aCache);
#endif
static void PreserveWrapper(nsISupports* aScriptObjectHolder,
nsWrapperCache* aCache)
{
@ -1171,6 +1176,10 @@ public:
CallQueryInterface(aScriptObjectHolder, &participant);
HoldJSObjects(aScriptObjectHolder, participant);
aCache->SetPreservingWrapper(PR_TRUE);
#ifdef DEBUG
// Make sure the cycle collector will be able to traverse to the wrapper.
CheckCCWrapperTraversal(aScriptObjectHolder, aCache);
#endif
}
}
static void ReleaseWrapper(nsISupports* aScriptObjectHolder,

View File

@ -5174,6 +5174,84 @@ nsContentUtils::WrapNative(JSContext *cx, JSObject *scope, nsISupports *native,
return rv;
}
#ifdef DEBUG
class DebugWrapperTraversalCallback : public nsCycleCollectionTraversalCallback
{
public:
DebugWrapperTraversalCallback(void* aWrapper) : mFound(PR_FALSE),
mWrapper(aWrapper)
{
mFlags = WANT_ALL_TRACES;
}
NS_IMETHOD_(void) DescribeNode(CCNodeType type,
nsrefcnt refcount,
size_t objsz,
const char* objname)
{
}
NS_IMETHOD_(void) NoteXPCOMRoot(nsISupports *root)
{
}
NS_IMETHOD_(void) NoteRoot(PRUint32 langID, void* root,
nsCycleCollectionParticipant* helper)
{
}
NS_IMETHOD_(void) NoteScriptChild(PRUint32 langID, void* child)
{
if (langID == nsIProgrammingLanguage::JAVASCRIPT) {
mFound = child == mWrapper;
}
}
NS_IMETHOD_(void) NoteXPCOMChild(nsISupports *child)
{
}
NS_IMETHOD_(void) NoteNativeChild(void* child,
nsCycleCollectionParticipant* helper)
{
}
NS_IMETHOD_(void) NoteNextEdgeName(const char* name)
{
}
PRBool mFound;
private:
void* mWrapper;
};
static void
DebugWrapperTraceCallback(PRUint32 langID, void *p, void *closure)
{
DebugWrapperTraversalCallback* callback =
static_cast<DebugWrapperTraversalCallback*>(closure);
callback->NoteScriptChild(langID, p);
}
// static
void
nsContentUtils::CheckCCWrapperTraversal(nsISupports* aScriptObjectHolder,
nsWrapperCache* aCache)
{
nsXPCOMCycleCollectionParticipant* participant;
CallQueryInterface(aScriptObjectHolder, &participant);
DebugWrapperTraversalCallback callback(aCache->GetWrapper());
participant->Traverse(aScriptObjectHolder, callback);
NS_ASSERTION(callback.mFound,
"Cycle collection participant didn't traverse to preserved "
"wrapper! This will probably crash.");
callback.mFound = PR_FALSE;
participant->Trace(aScriptObjectHolder, DebugWrapperTraceCallback, &callback);
NS_ASSERTION(callback.mFound,
"Cycle collection participant didn't trace preserved wrapper! "
"This will probably crash.");
}
#endif
mozAutoRemovableBlockerRemover::mozAutoRemovableBlockerRemover(nsIDocument* aDocument)
{
mNestingLevel = nsContentUtils::GetRemovableScriptBlockerLevel();

View File

@ -1767,6 +1767,8 @@ nsDOMClassInfo::~nsDOMClassInfo()
}
}
NS_DEFINE_STATIC_IID_ACCESSOR(nsDOMClassInfo, NS_DOMCLASSINFO_IID)
NS_IMPL_ADDREF(nsDOMClassInfo)
NS_IMPL_RELEASE(nsDOMClassInfo)
@ -1774,6 +1776,11 @@ NS_INTERFACE_MAP_BEGIN(nsDOMClassInfo)
NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCScriptable)
if (aIID.Equals(NS_GET_IID(nsDOMClassInfo))) {
*aInstancePtr = static_cast<nsIXPCScriptable*>(this);
return NS_OK;
}
else
NS_INTERFACE_MAP_END
@ -4454,10 +4461,13 @@ nsDOMClassInfo::GetClassInfoInstance(nsDOMClassInfoData* aData)
void
nsDOMClassInfo::PreserveNodeWrapper(nsIXPConnectWrappedNative *aWrapper)
{
nsWrapperCache* cache = nsnull;
CallQueryInterface(aWrapper->Native(), &cache);
if (cache) {
nsContentUtils::PreserveWrapper(aWrapper->Native(), cache);
nsCOMPtr<nsIClassInfo> ci = do_QueryInterface(aWrapper->Native());
if (ci) {
nsDOMClassInfo* domci = nsnull;
CallQueryInterface(ci, &domci);
if (domci) {
domci->PreserveWrapper(aWrapper->Native());
}
}
}
@ -7236,8 +7246,7 @@ NS_IMETHODIMP
nsNodeSH::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsval id, jsval *vp, PRBool *_retval)
{
nsINode* node = static_cast<nsINode*>(GetNative(wrapper, obj));
nsContentUtils::PreserveWrapper(node, node);
nsNodeSH::PreserveWrapper(GetNative(wrapper, obj));
return nsEventReceiverSH::AddProperty(wrapper, cx, obj, id, vp, _retval);
}
@ -7254,8 +7263,7 @@ nsNodeSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
if (id == sOnload_id || id == sOnerror_id) {
// Make sure that this node can't go away while waiting for a
// network load that could fire an event handler.
nsINode* node = static_cast<nsINode*>(GetNative(wrapper, obj));
nsContentUtils::PreserveWrapper(node, node);
nsNodeSH::PreserveWrapper(GetNative(wrapper, obj));
}
return nsEventReceiverSH::NewResolve(wrapper, cx, obj, id, flags, objp,
@ -7326,6 +7334,13 @@ nsNodeSH::GetFlags(PRUint32 *aFlags)
return NS_OK;
}
void
nsNodeSH::PreserveWrapper(nsISupports *aNative)
{
nsINode *node = static_cast<nsINode*>(aNative);
nsContentUtils::PreserveWrapper(aNative, node);
}
// EventReceiver helper
// static
@ -7694,13 +7709,18 @@ nsEventTargetSH::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
return NS_OK;
}
nsISupports *target = GetNative(wrapper, obj);
nsContentUtils::PreserveWrapper(target,
nsXHREventTarget::FromSupports(target));
nsEventTargetSH::PreserveWrapper(GetNative(wrapper, obj));
return NS_OK;
}
void
nsEventTargetSH::PreserveWrapper(nsISupports *aNative)
{
nsXHREventTarget *target = nsXHREventTarget::FromSupports(aNative);
nsContentUtils::PreserveWrapper(aNative, target);
}
// Element helper

View File

@ -102,10 +102,16 @@ typedef PRUptrdiff PtrBits;
#define IS_EXTERNAL(_ptr) (PtrBits(_ptr) & 0x1)
#define NS_DOMCLASSINFO_IID \
{ 0x7da6858c, 0x5c12, 0x4588, \
{ 0x82, 0xbe, 0x01, 0xa2, 0x45, 0xc5, 0xc0, 0xb0 } }
class nsDOMClassInfo : public nsIXPCScriptable,
public nsIClassInfo
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_DOMCLASSINFO_IID)
nsDOMClassInfo(nsDOMClassInfoData* aData);
virtual ~nsDOMClassInfo();
@ -217,6 +223,10 @@ protected:
const nsDOMClassInfoData* mData;
virtual void PreserveWrapper(nsISupports *aNative)
{
}
static nsresult Init();
static nsresult RegisterClassName(PRInt32 aDOMClassInfoID);
static nsresult RegisterClassProtos(PRInt32 aDOMClassInfoID);
@ -475,6 +485,8 @@ public:
NS_IMETHOD AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsval id, jsval *vp, PRBool *_retval);
virtual void PreserveWrapper(nsISupports *aNative);
static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
{
return new nsEventTargetSH(aData);
@ -658,6 +670,8 @@ public:
JSObject *obj, jsval id, jsval *vp, PRBool *_retval);
NS_IMETHOD GetFlags(PRUint32 *aFlags);
virtual void PreserveWrapper(nsISupports *aNative);
static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
{
return new nsNodeSH(aData);

View File

@ -139,7 +139,6 @@ nsComputedDOMStyle::nsComputedDOMStyle()
nsComputedDOMStyle::~nsComputedDOMStyle()
{
ClearWrapper();
}
void
@ -154,20 +153,7 @@ nsComputedDOMStyle::Shutdown()
}
NS_IMPL_CYCLE_COLLECTION_CLASS(nsComputedDOMStyle)
NS_IMPL_CYCLE_COLLECTION_ROOT_BEGIN(nsComputedDOMStyle)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_ROOT_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsComputedDOMStyle)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContent)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsComputedDOMStyle)
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsComputedDOMStyle)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mContent)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_1(nsComputedDOMStyle, mContent)
// QueryInterface implementation for nsComputedDOMStyle
NS_INTERFACE_TABLE_HEAD(nsComputedDOMStyle)

View File

@ -61,7 +61,7 @@ class nsComputedDOMStyle : public nsICSSDeclaration,
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsComputedDOMStyle)
NS_DECL_CYCLE_COLLECTION_CLASS(nsComputedDOMStyle)
NS_IMETHOD Init(nsIDOMElement *aElement,
const nsAString& aPseudoElt,

View File

@ -72,24 +72,7 @@ nsDOMCSSAttributeDeclaration::~nsDOMCSSAttributeDeclaration()
MOZ_COUNT_DTOR(nsDOMCSSAttributeDeclaration);
}
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMCSSAttributeDeclaration)
NS_IMPL_CYCLE_COLLECTION_ROOT_BEGIN(nsDOMCSSAttributeDeclaration)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_ROOT_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMCSSAttributeDeclaration)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContent)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsDOMCSSAttributeDeclaration)
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMCSSAttributeDeclaration)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mContent)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_1(nsDOMCSSAttributeDeclaration, mContent)
NS_INTERFACE_MAP_BEGIN(nsDOMCSSAttributeDeclaration)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY

View File

@ -61,7 +61,7 @@ public:
~nsDOMCSSAttributeDeclaration();
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsDOMCSSAttributeDeclaration)
NS_DECL_CYCLE_COLLECTION_CLASS(nsDOMCSSAttributeDeclaration)
// If GetCSSDeclaration returns non-null, then the decl it returns
// is owned by our current style rule.