mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Bug 1356556, use of weak references in nsHTMLDNSPrefetch is malloc heavy, so instead use raw pointers and a flag to tell that Link's destructor needs to clear the raw pointer, r=bz
--HG-- extra : rebase_source : f5a60230bfd5c19c82a70069ae59baae69c1f302
This commit is contained in:
parent
b84117e652
commit
4419d4789a
@ -34,6 +34,7 @@ Link::Link(Element *aElement)
|
||||
, mNeedsRegistration(false)
|
||||
, mRegistered(false)
|
||||
, mHasPendingLinkUpdate(false)
|
||||
, mInDNSPrefetch(false)
|
||||
{
|
||||
MOZ_ASSERT(mElement, "Must have an element");
|
||||
}
|
||||
@ -45,11 +46,17 @@ Link::Link()
|
||||
, mNeedsRegistration(false)
|
||||
, mRegistered(false)
|
||||
, mHasPendingLinkUpdate(false)
|
||||
, mInDNSPrefetch(false)
|
||||
{
|
||||
}
|
||||
|
||||
Link::~Link()
|
||||
{
|
||||
// !mElement is for mock_Link.
|
||||
MOZ_ASSERT(!mElement || !mElement->IsInComposedDoc());
|
||||
if (IsInDNSPrefetch()) {
|
||||
nsHTMLDNSPrefetch::LinkDestroyed(this);
|
||||
}
|
||||
UnregisterFromHistory();
|
||||
}
|
||||
|
||||
|
@ -136,6 +136,10 @@ public:
|
||||
// If you change this, change also the method in Element.
|
||||
virtual void NodeInfoChanged(nsIDocument* aOldDoc) = 0;
|
||||
|
||||
bool IsInDNSPrefetch() { return mInDNSPrefetch; }
|
||||
void SetIsInDNSPrefetch() { mInDNSPrefetch = true; }
|
||||
void ClearIsInDNSPrefetch() { mInDNSPrefetch = false; }
|
||||
|
||||
protected:
|
||||
virtual ~Link();
|
||||
|
||||
@ -179,6 +183,8 @@ private:
|
||||
bool mRegistered : 1;
|
||||
|
||||
bool mHasPendingLinkUpdate : 1;
|
||||
|
||||
bool mInDNSPrefetch : 1;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(Link, MOZILLA_DOM_LINK_IMPLEMENTATION_IID)
|
||||
|
@ -247,6 +247,15 @@ nsHTMLDNSPrefetch::CancelPrefetchLow(const nsAString &hostname,
|
||||
aReason);
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLDNSPrefetch::LinkDestroyed(Link* aLink)
|
||||
{
|
||||
MOZ_ASSERT(aLink->IsInDNSPrefetch());
|
||||
if (sPrefetches) {
|
||||
// Clean up all the possible links at once.
|
||||
sPrefetches->RemoveUnboundLinks();
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -291,6 +300,9 @@ void
|
||||
nsHTMLDNSPrefetch::nsDeferrals::Flush()
|
||||
{
|
||||
while (mHead != mTail) {
|
||||
if (mEntries[mTail].mElement) {
|
||||
mEntries[mTail].mElement->ClearIsInDNSPrefetch();
|
||||
}
|
||||
mEntries[mTail].mElement = nullptr;
|
||||
mTail = (mTail + 1) & sMaxDeferredMask;
|
||||
}
|
||||
@ -306,9 +318,10 @@ nsHTMLDNSPrefetch::nsDeferrals::Add(uint16_t flags, Link *aElement)
|
||||
|
||||
if (((mHead + 1) & sMaxDeferredMask) == mTail)
|
||||
return NS_ERROR_DNS_LOOKUP_QUEUE_FULL;
|
||||
|
||||
|
||||
aElement->SetIsInDNSPrefetch();
|
||||
mEntries[mHead].mFlags = flags;
|
||||
mEntries[mHead].mElement = do_GetWeakReference(aElement);
|
||||
mEntries[mHead].mElement = aElement;
|
||||
mHead = (mHead + 1) & sMaxDeferredMask;
|
||||
|
||||
if (!mActiveLoaderCount && !mTimerArmed && mTimer) {
|
||||
@ -328,9 +341,9 @@ nsHTMLDNSPrefetch::nsDeferrals::SubmitQueue()
|
||||
if (!sDNSService) return;
|
||||
|
||||
while (mHead != mTail) {
|
||||
nsCOMPtr<nsIContent> content = do_QueryReferent(mEntries[mTail].mElement);
|
||||
if (content) {
|
||||
nsCOMPtr<Link> link = do_QueryInterface(content);
|
||||
nsCOMPtr<Link> link = mEntries[mTail].mElement;
|
||||
if (link) {
|
||||
link->ClearIsInDNSPrefetch();
|
||||
// Only prefetch here if request was deferred and deferral not cancelled
|
||||
if (link && link->HasDeferredDNSPrefetchRequest()) {
|
||||
nsCOMPtr<nsIURI> hrefURI(link ? link->GetURI() : nullptr);
|
||||
@ -400,6 +413,20 @@ nsHTMLDNSPrefetch::nsDeferrals::Activate()
|
||||
observerService->AddObserver(this, "xpcom-shutdown", true);
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLDNSPrefetch::nsDeferrals::RemoveUnboundLinks()
|
||||
{
|
||||
uint16_t tail = mTail;
|
||||
while (mHead != tail) {
|
||||
if (mEntries[tail].mElement &&
|
||||
!mEntries[tail].mElement->GetElement()->IsInComposedDoc()) {
|
||||
mEntries[tail].mElement->ClearIsInDNSPrefetch();
|
||||
mEntries[tail].mElement = nullptr;
|
||||
}
|
||||
tail = (tail + 1) & sMaxDeferredMask;
|
||||
}
|
||||
}
|
||||
|
||||
// nsITimer related method
|
||||
|
||||
void
|
||||
|
@ -63,6 +63,8 @@ public:
|
||||
static nsresult CancelPrefetchLow(mozilla::dom::Link *aElement,
|
||||
nsresult aReason);
|
||||
|
||||
static void LinkDestroyed(mozilla::dom::Link* aLink);
|
||||
|
||||
private:
|
||||
static nsresult Prefetch(const nsAString &host,
|
||||
const mozilla::OriginAttributes &aOriginAttributes,
|
||||
@ -103,6 +105,8 @@ public:
|
||||
void Activate();
|
||||
nsresult Add(uint16_t flags, mozilla::dom::Link *aElement);
|
||||
|
||||
void RemoveUnboundLinks();
|
||||
|
||||
private:
|
||||
~nsDeferrals();
|
||||
void Flush();
|
||||
@ -123,7 +127,8 @@ public:
|
||||
struct deferred_entry
|
||||
{
|
||||
uint16_t mFlags;
|
||||
nsWeakPtr mElement;
|
||||
// Link implementation clears this raw pointer in its destructor.
|
||||
mozilla::dom::Link* mElement;
|
||||
} mEntries[sMaxDeferred];
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user