Fix for bug 799465 (Add complete support for non-nsISupports objects in new DOM bindings) - fix CC traversal and wrapper preservation. r=bz.

--HG--
rename : dom/tests/mochitest/chrome/file_bug800817.xul => dom/tests/mochitest/chrome/file_bug799299.xul
rename : dom/tests/mochitest/chrome/test_bug800817.xul => dom/tests/mochitest/chrome/test_bug799299.xul
extra : rebase_source : bed68ffa15fe5933994c33fbd94ad2b597b5b1b9
This commit is contained in:
Peter Van der Beken 2012-09-26 20:12:15 +02:00
parent 62ddd9835d
commit 86dcdcb94b
7 changed files with 56 additions and 25 deletions

View File

@ -1295,8 +1295,9 @@ public:
#ifdef DEBUG
static bool AreJSObjectsHeld(void* aScriptObjectHolder);
static void CheckCCWrapperTraversal(nsISupports* aScriptObjectHolder,
nsWrapperCache* aCache);
static void CheckCCWrapperTraversal(void* aScriptObjectHolder,
nsWrapperCache* aCache,
nsScriptObjectTracer* aTracer);
#endif
static void PreserveWrapper(nsISupports* aScriptObjectHolder,
@ -1309,15 +1310,23 @@ public:
MOZ_ASSERT(ccISupports);
nsXPCOMCycleCollectionParticipant* participant;
CallQueryInterface(ccISupports, &participant);
HoldJSObjects(ccISupports, participant);
PreserveWrapper(ccISupports, aCache, participant);
}
}
static void PreserveWrapper(void* aScriptObjectHolder,
nsWrapperCache* aCache,
nsScriptObjectTracer* aTracer)
{
if (!aCache->PreservingWrapper()) {
HoldJSObjects(aScriptObjectHolder, aTracer);
aCache->SetPreservingWrapper(true);
#ifdef DEBUG
// Make sure the cycle collector will be able to traverse to the wrapper.
CheckCCWrapperTraversal(ccISupports, aCache);
CheckCCWrapperTraversal(aScriptObjectHolder, aCache, aTracer);
#endif
}
}
static void ReleaseWrapper(nsISupports* aScriptObjectHolder,
static void ReleaseWrapper(void* aScriptObjectHolder,
nsWrapperCache* aCache);
static void TraceWrapper(nsWrapperCache* aCache, TraceCallback aCallback,
void *aClosure);

View File

@ -6394,26 +6394,24 @@ DebugWrapperTraceCallback(void *p, const char *name, void *closure)
// static
void
nsContentUtils::CheckCCWrapperTraversal(nsISupports* aScriptObjectHolder,
nsWrapperCache* aCache)
nsContentUtils::CheckCCWrapperTraversal(void* aScriptObjectHolder,
nsWrapperCache* aCache,
nsScriptObjectTracer* aTracer)
{
JSObject* wrapper = aCache->GetWrapper();
if (!wrapper) {
return;
}
nsXPCOMCycleCollectionParticipant* participant;
CallQueryInterface(aScriptObjectHolder, &participant);
DebugWrapperTraversalCallback callback(wrapper);
participant->Traverse(aScriptObjectHolder, callback);
aTracer->Traverse(aScriptObjectHolder, callback);
NS_ASSERTION(callback.mFound,
"Cycle collection participant didn't traverse to preserved "
"wrapper! This will probably crash.");
callback.mFound = false;
participant->Trace(aScriptObjectHolder, DebugWrapperTraceCallback, &callback);
aTracer->Trace(aScriptObjectHolder, DebugWrapperTraceCallback, &callback);
NS_ASSERTION(callback.mFound,
"Cycle collection participant didn't trace preserved wrapper! "
"This will probably crash.");
@ -6932,7 +6930,7 @@ nsContentUtils::GetRootDocument(nsIDocument* aDoc)
// static
void
nsContentUtils::ReleaseWrapper(nsISupports* aScriptObjectHolder,
nsContentUtils::ReleaseWrapper(void* aScriptObjectHolder,
nsWrapperCache* aCache)
{
if (aCache->PreservingWrapper()) {

View File

@ -226,6 +226,9 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsWrapperCache, NS_WRAPPERCACHE_IID)
#define NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER \
nsContentUtils::ReleaseWrapper(s, tmp);
#define NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER_NATIVE \
nsContentUtils::ReleaseWrapper(tmp, tmp);
#define NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(_class) \
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(_class) \
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER \

View File

@ -93,11 +93,16 @@ def DOMClass(descriptor):
protoList.extend(['prototypes::id::_ID_Count'] * (descriptor.config.maxProtoChainLength - len(protoList)))
prototypeChainString = ', '.join(protoList)
nativeHooks = "NULL" if descriptor.workers else "&NativeHooks"
if descriptor.workers or descriptor.nativeOwnership != 'refcounted':
participant = "nullptr"
else:
participant = "NS_CYCLE_COLLECTION_PARTICIPANT(%s)" % descriptor.nativeType
return """{
{ %s },
%s, %s
%s, %s, %s
}""" % (prototypeChainString, toStringBool(descriptor.nativeOwnership == 'nsisupports'),
nativeHooks)
nativeHooks,
participant)
class CGDOMJSClass(CGThing):
"""
@ -633,12 +638,13 @@ class CGAddPropertyHook(CGAbstractClassHook):
'JSBool', args)
def generate_code(self):
# FIXME https://bugzilla.mozilla.org/show_bug.cgi?id=774279
# Using a real trace hook might enable us to deal with non-nsISupports
# wrappercached things here.
assert self.descriptor.nativeOwnership == 'nsisupports'
return """ nsContentUtils::PreserveWrapper(reinterpret_cast<nsISupports*>(self), self);
return true;"""
assert not self.descriptor.workers and self.descriptor.wrapperCache
if self.descriptor.nativeOwnership == 'nsisupports':
preserveArgs = "reinterpret_cast<nsISupports*>(self), self"
else:
preserveArgs = "self, self, NS_CYCLE_COLLECTION_PARTICIPANT(%s)" % self.descriptor.nativeType
return """ nsContentUtils::PreserveWrapper(%s);
return true;""" % preserveArgs
def DeferredFinalizeSmartPtr(descriptor):
if descriptor.nativeOwnership == 'owned':

View File

@ -266,7 +266,9 @@ class Descriptor(DescriptorProvider):
self.customTrace = desc.get('customTrace', self.workers)
self.customFinalize = desc.get('customFinalize', self.workers)
self.wrapperCache = (not self.interface.isCallback() and
(self.workers or desc.get('wrapperCache', True)))
(self.workers or
(self.nativeOwnership != 'owned' and
desc.get('wrapperCache', True))))
if not self.wrapperCache and self.prefable:
raise TypeError("Descriptor for %s is prefable but not wrappercached" %

View File

@ -11,6 +11,8 @@
#include "mozilla/dom/PrototypeList.h" // auto-generated
class nsCycleCollectionParticipant;
// We use slot 0 for holding the raw object. This is safe for both
// globals and non-globals.
#define DOM_OBJECT_SLOT 0
@ -66,6 +68,11 @@ struct DOMClass
const bool mDOMObjectIsISupports;
const NativePropertyHooks* mNativeHooks;
// This stores the CC participant for the native, null if this class is for a
// worker or for a native inheriting from nsISupports (we can get the CC
// participant by QI'ing in that case).
nsCycleCollectionParticipant* mParticipant;
};
// Special JSClass for reflected DOM objects.

View File

@ -847,10 +847,16 @@ NoteGCThingXPCOMChildren(js::Class *clasp, JSObject *obj,
static_cast<nsISupports*>(js::GetProxyPrivate(obj).toPrivate());
cb.NoteXPCOMChild(identity);
} else {
nsISupports *identity;
if (UnwrapDOMObjectToISupports(obj, identity)) {
const DOMClass* domClass;
DOMObjectSlot slot = GetDOMClass(obj, domClass);
if (slot != eNonDOMObject) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "UnwrapDOMObject(obj)");
cb.NoteXPCOMChild(identity);
if (domClass->mDOMObjectIsISupports) {
cb.NoteXPCOMChild(UnwrapDOMObject<nsISupports>(obj, slot));
} else if (domClass->mParticipant) {
cb.NoteNativeChild(UnwrapDOMObject<void>(obj, slot),
domClass->mParticipant);
}
}
}
}