Bug 1273251: Part 4 - Drop CallbackObject's JS objects for nuked compartments during CC. r=peterv,mccr8

MozReview-Commit-ID: 6lPdmUtKREt

--HG--
extra : rebase_source : c6a53f914b5bbe829de6f5a080cfb9ee93146bd3
This commit is contained in:
Kris Maglione 2016-11-14 19:49:28 -08:00
Родитель 729b7a2019
Коммит 67fcf5b318
2 изменённых файлов: 58 добавлений и 2 удалений

Просмотреть файл

@ -36,6 +36,44 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CallbackObject)
tmp->DropJSObjects();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIncumbentGlobal)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(CallbackObject)
JSObject* callback = tmp->CallbackPreserveColor();
if (!aRemovingAllowed) {
// If our callback has been cleared, we can't be part of a garbage cycle.
return !callback;
}
// mCallback is always wrapped for the CallbackObject's incumbent global. In
// the case where the real callback is in a different compartment, we have a
// cross-compartment wrapper, and it will automatically be cut when its
// compartment is nuked. In the case where it is in the same compartment, we
// have a reference to the real function. Since that means there are no
// wrappers to cut, we need to check whether the compartment is still alive,
// and drop the references if it is not.
if (MOZ_UNLIKELY(!callback)) {
return true;
}
auto pvt = xpc::CompartmentPrivate::Get(callback);
if (MOZ_LIKELY(tmp->mIncumbentGlobal && pvt) && MOZ_UNLIKELY(pvt->wasNuked)) {
// It's not safe to release our global reference or drop our JS objects at
// this point, so defer their finalization until CC is finished.
AddForDeferredFinalization(new JSObjectsDropper(tmp));
DeferredFinalize(tmp->mIncumbentGlobal.forget().take());
return true;
}
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(CallbackObject)
return !tmp->mCallback;
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(CallbackObject)
return !tmp->mCallback;
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CallbackObject)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIncumbentGlobal)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END

Просмотреть файл

@ -46,7 +46,7 @@ public:
NS_DECLARE_STATIC_IID_ACCESSOR(DOM_CALLBACKOBJECT_IID)
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(CallbackObject)
NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(CallbackObject)
// The caller may pass a global object which will act as an override for the
// incumbent script settings object when the callback is invoked (overriding
@ -179,6 +179,22 @@ protected:
return thisObj == otherObj;
}
class JSObjectsDropper final
{
public:
explicit JSObjectsDropper(CallbackObject* aHolder)
: mHolder(aHolder)
{}
~JSObjectsDropper()
{
mHolder->DropJSObjects();
}
private:
RefPtr<CallbackObject> mHolder;
};
private:
inline void InitNoHold(JSObject* aCallback, JSObject* aCreationStack,
nsIGlobalObject* aIncumbentGlobal)
@ -536,7 +552,9 @@ ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
const char* aName,
uint32_t aFlags = 0)
{
CycleCollectionNoteChild(aCallback, aField.GetISupports(), aName, aFlags);
if (aField) {
CycleCollectionNoteChild(aCallback, aField.GetISupports(), aName, aFlags);
}
}
template<class T, class U>