Bug 942240 - Improve the skippability of nsGlobalWindow, r=mccr8

--HG--
extra : rebase_source : ed7e687229a92075657d9b665fbc7af42d9eb5cc
This commit is contained in:
Olli Pettay 2013-11-24 21:35:34 +02:00
parent 552ae51362
commit fa64f21519
9 changed files with 95 additions and 27 deletions

View File

@ -30,6 +30,7 @@
#include "mozilla/dom/Element.h"
#include "xpcpublic.h"
#include "nsObserverService.h"
#include "nsFocusManager.h"
using namespace mozilla::dom;
@ -210,6 +211,16 @@ MarkContentViewer(nsIContentViewer* aViewer, bool aCleanupJS,
EnumerateAll(MarkUserData, &nsCCUncollectableMarker::sGeneration);
}
}
if (doc) {
nsPIDOMWindow* inner = doc->GetInnerWindow();
if (inner) {
inner->MarkUncollectableForCCGeneration(nsCCUncollectableMarker::sGeneration);
}
nsPIDOMWindow* outer = doc->GetWindow();
if (outer) {
outer->MarkUncollectableForCCGeneration(nsCCUncollectableMarker::sGeneration);
}
}
}
void MarkDocShell(nsIDocShellTreeNode* aNode, bool aCleanupJS,
@ -336,6 +347,8 @@ nsCCUncollectableMarker::Observe(nsISupports* aSubject, const char* aTopic,
++sGeneration;
}
nsFocusManager::MarkUncollectableForCCGeneration(sGeneration);
nsresult rv;
// Iterate all toplevel windows

View File

@ -3436,6 +3436,43 @@ nsFocusManager::SetFocusedWindowInternal(nsPIDOMWindow* aWindow)
mFocusedWindow = aWindow;
}
void
nsFocusManager::MarkUncollectableForCCGeneration(uint32_t aGeneration)
{
if (!sInstance) {
return;
}
if (sInstance->mActiveWindow) {
sInstance->mActiveWindow->
MarkUncollectableForCCGeneration(aGeneration);
}
if (sInstance->mFocusedWindow) {
sInstance->mFocusedWindow->
MarkUncollectableForCCGeneration(aGeneration);
}
if (sInstance->mWindowBeingLowered) {
sInstance->mWindowBeingLowered->
MarkUncollectableForCCGeneration(aGeneration);
}
if (sInstance->mFocusedContent) {
sInstance->mFocusedContent->OwnerDoc()->
MarkUncollectableForCCGeneration(aGeneration);
}
if (sInstance->mFirstBlurEvent) {
sInstance->mFirstBlurEvent->OwnerDoc()->
MarkUncollectableForCCGeneration(aGeneration);
}
if (sInstance->mFirstFocusEvent) {
sInstance->mFirstFocusEvent->OwnerDoc()->
MarkUncollectableForCCGeneration(aGeneration);
}
if (sInstance->mMouseDownEventHandlingDocument) {
sInstance->mMouseDownEventHandlingDocument->
MarkUncollectableForCCGeneration(aGeneration);
}
}
nsresult
NS_NewFocusManager(nsIFocusManager** aResult)
{

View File

@ -121,6 +121,7 @@ public:
static bool sMouseFocusesFormControl;
static void MarkUncollectableForCCGeneration(uint32_t aGeneration);
protected:
nsFocusManager();

View File

@ -550,7 +550,8 @@ nsPIDOMWindow::nsPIDOMWindow(nsPIDOMWindow *aOuterWindow)
mIsActive(false), mIsBackground(false),
mInnerWindow(nullptr), mOuterWindow(aOuterWindow),
// Make sure no actual window ends up with mWindowID == 0
mWindowID(++gNextWindowID), mHasNotifiedGlobalCreated(false)
mWindowID(++gNextWindowID), mHasNotifiedGlobalCreated(false),
mMarkedCCGeneration(0)
{}
nsPIDOMWindow::~nsPIDOMWindow() {}
@ -1619,7 +1620,7 @@ MarkXBLHandlers(nsXBLPrototypeHandler* aKey, JS::Heap<JSObject*>& aData, void* a
}
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsGlobalWindow)
if (tmp->IsBlackForCC()) {
if (tmp->IsBlackForCC(false)) {
if (tmp->mCachedXBLPrototypeHandlers) {
tmp->mCachedXBLPrototypeHandlers->Enumerate(MarkXBLHandlers, nullptr);
}
@ -1632,11 +1633,11 @@ NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsGlobalWindow)
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsGlobalWindow)
return tmp->IsBlackForCC();
return tmp->IsBlackForCC(true);
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsGlobalWindow)
return tmp->IsBlackForCC();
return tmp->IsBlackForCC(false);
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
inline void
@ -1659,10 +1660,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindow)
NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsGlobalWindow, tmp->mRefCnt.get())
}
if (!cb.WantAllTraces() && tmp->IsBlackForCC()) {
return NS_SUCCESS_INTERRUPTED_TRAVERSE;
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContext)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mControllers)
@ -1791,12 +1788,16 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsGlobalWindow)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
bool
nsGlobalWindow::IsBlackForCC()
nsGlobalWindow::IsBlackForCC(bool aTracingNeeded)
{
return
(mDoc &&
nsCCUncollectableMarker::InGeneration(mDoc->GetMarkedCCGeneration())) ||
(nsCCUncollectableMarker::sGeneration && IsBlack());
if (!nsCCUncollectableMarker::sGeneration) {
return false;
}
return (nsCCUncollectableMarker::InGeneration(GetMarkedCCGeneration()) ||
IsBlack()) &&
(!aTracingNeeded ||
HasNothingToTrace(static_cast<nsIDOMEventTarget*>(this)));
}
void

View File

@ -355,7 +355,7 @@ public:
void PoisonOuterWindowProxy(JSObject *aObject);
virtual void OnFinalize(JSObject* aObject);
virtual bool IsBlackForCC();
virtual bool IsBlackForCC(bool aTracingNeeded = true);
// nsIScriptObjectPrincipal
virtual nsIPrincipal* GetPrincipal();

View File

@ -27,8 +27,8 @@ NS_HandleScriptError(nsIScriptGlobalObject *aScriptGlobal,
#define NS_ISCRIPTGLOBALOBJECT_IID \
{ 0xa6c0bfae, 0x8be4, 0x4747, \
{ 0xaf, 0x1a, 0xe3, 0xf0, 0x3f, 0xb6, 0x0e, 0xb8 } }
{ 0x30c64680, 0x909a, 0x4435, \
{ 0x90, 0x3b, 0x29, 0x3e, 0xb5, 0x5d, 0xc7, 0xa0 } }
/**
* The global object which keeps a script context for each supported script
@ -80,7 +80,7 @@ public:
return NS_OK;
}
virtual bool IsBlackForCC() { return false; }
virtual bool IsBlackForCC(bool aTracingNeeded = true) { return false; }
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptGlobalObject,

View File

@ -60,8 +60,8 @@ enum UIStateChangeType
};
#define NS_PIDOMWINDOW_IID \
{ 0x4f4eadf9, 0xe795, 0x48e5, \
{ 0x89, 0x4b, 0x04, 0x40, 0xb2, 0x5d, 0xa6, 0xfa } }
{ 0xf26953de, 0xa799, 0x4a92, \
{ 0x87, 0x49, 0x7c, 0x37, 0xe5, 0x90, 0x3f, 0x37 } }
class nsPIDOMWindow : public nsIDOMWindowInternal
{
@ -653,6 +653,15 @@ public:
// WebIDL-ish APIs
nsPerformance* GetPerformance();
void MarkUncollectableForCCGeneration(uint32_t aGeneration)
{
mMarkedCCGeneration = aGeneration;
}
uint32_t GetMarkedCCGeneration()
{
return mMarkedCCGeneration;
}
protected:
// The nsPIDOMWindow constructor. The aOuterWindow argument should
// be null if and only if the created window itself is an outer
@ -736,6 +745,8 @@ protected:
// This is only used by the inner window. Set to true once we've sent
// the (chrome|content)-document-global-created notification.
bool mHasNotifiedGlobalCreated;
uint32_t mMarkedCCGeneration;
};

View File

@ -156,6 +156,8 @@ public:
*/
bool IsBlackAndDoesNotNeedTracing(nsISupports* aThis);
bool HasNothingToTrace(nsISupports* aThis);
// Only meant to be called by code that preserves a wrapper.
void SetPreservingWrapper(bool aPreserve)
{

View File

@ -36,17 +36,20 @@ SearchGray(void* aGCThing, const char* aName, void* aClosure)
}
}
inline bool
nsWrapperCache::HasNothingToTrace(nsISupports* aThis)
{
nsXPCOMCycleCollectionParticipant* participant = nullptr;
CallQueryInterface(aThis, &participant);
bool hasGrayObjects = false;
participant->Trace(aThis, TraceCallbackFunc(SearchGray), &hasGrayObjects);
return !hasGrayObjects;
}
inline bool
nsWrapperCache::IsBlackAndDoesNotNeedTracing(nsISupports* aThis)
{
if (IsBlack()) {
nsXPCOMCycleCollectionParticipant* participant = nullptr;
CallQueryInterface(aThis, &participant);
bool hasGrayObjects = false;
participant->Trace(aThis, TraceCallbackFunc(SearchGray), &hasGrayObjects);
return !hasGrayObjects;
}
return false;
return IsBlack() && HasNothingToTrace(aThis);
}
inline void