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:
Olli Pettay 2017-04-19 13:06:36 +03:00
parent b84117e652
commit 4419d4789a
4 changed files with 51 additions and 6 deletions

View File

@ -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();
}

View File

@ -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)

View File

@ -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

View File

@ -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];
};