Bug 1439538 - Convert nsHostResolver::m{High,Medium,Low,Eviction}Q to LinkedList<RefPtr<nsHostRecord>> draft
authorValentin Gosu <valentin.gosu@gmail.com>
Tue, 20 Feb 2018 17:41:50 +0100
changeset 757282 658375deb3f408777ae5c28341ade34a571c093a
parent 757244 2c000486eac466da6623e4d7f7f1fd4e318f60e8
push id99741
push uservalentin.gosu@gmail.com
push dateTue, 20 Feb 2018 16:42:20 +0000
bugs1439538
milestone60.0a1
Bug 1439538 - Convert nsHostResolver::m{High,Medium,Low,Eviction}Q to LinkedList<RefPtr<nsHostRecord>> MozReview-Commit-ID: CDMadOtmDHQ
netwerk/dns/nsHostResolver.cpp
netwerk/dns/nsHostResolver.h
--- a/netwerk/dns/nsHostResolver.cpp
+++ b/netwerk/dns/nsHostResolver.cpp
@@ -82,30 +82,16 @@ LazyLogModule gHostResolverLog("nsHostRe
 }
 
 #define LOG_HOST(host, interface) host,                                        \
                  (interface && interface[0] != '\0') ? " on interface " : "",  \
                  (interface && interface[0] != '\0') ? interface : ""
 
 //----------------------------------------------------------------------------
 
-static inline void
-MoveCList(PRCList &from, PRCList &to)
-{
-    if (!PR_CLIST_IS_EMPTY(&from)) {
-        to.next = from.next;
-        to.prev = from.prev;
-        to.next->prev = &to;
-        to.prev->next = &to;
-        PR_INIT_CLIST(&from);
-    }
-}
-
-//----------------------------------------------------------------------------
-
 #if defined(RES_RETRY_ON_FAILURE)
 
 // this class represents the resolver state for a given thread.  if we
 // encounter a lookup failure, then we can invoke the Reset method on an
 // instance of this class to reset the resolver (in case /etc/resolv.conf
 // for example changed).  this is mainly an issue on GNU systems since glibc
 // only reads in /etc/resolv.conf once per thread.  it may be an issue on
 // other systems as well.
@@ -215,17 +201,16 @@ nsHostRecord::nsHostRecord(const nsHostK
     , mDoomed(false)
     , mDidCallbacks(false)
     , mGetTtl(false)
     , mTrrAUsed(INIT)
     , mTrrAAAAUsed(INIT)
     , mBlacklistedCount(0)
     , mResolveAgain(false)
 {
-    PR_INIT_CLIST(this);
 }
 
 void
 nsHostRecord::Cancel()
 {
     if (mTrrA) {
         mTrrA->Cancel();
     }
@@ -530,20 +515,16 @@ nsHostResolver::nsHostResolver(uint32_t 
     , mEvictionQSize(0)
     , mShutdown(true)
     , mNumIdleThreads(0)
     , mThreadCount(0)
     , mActiveAnyThreadCount(0)
     , mPendingCount(0)
 {
     mCreationTime = PR_Now();
-    PR_INIT_CLIST(&mHighQ);
-    PR_INIT_CLIST(&mMediumQ);
-    PR_INIT_CLIST(&mLowQ);
-    PR_INIT_CLIST(&mEvictionQ);
 
     mLongIdleTimeout  = PR_SecondsToInterval(LongIdleTimeoutSeconds);
     mShortIdleTimeout = PR_SecondsToInterval(ShortIdleTimeoutSeconds);
 }
 
 nsHostResolver::~nsHostResolver() = default;
 
 nsresult
@@ -585,25 +566,22 @@ nsHostResolver::Init()
         res_ninit(&_res);
     }
 #endif
 
     return NS_OK;
 }
 
 void
-nsHostResolver::ClearPendingQueue(PRCList *aPendingQ)
+nsHostResolver::ClearPendingQueue(LinkedList<RefPtr<nsHostRecord>>& aPendingQ)
 {
     // loop through pending queue, erroring out pending lookups.
-    if (!PR_CLIST_IS_EMPTY(aPendingQ)) {
-        PRCList *node = aPendingQ->next;
-        while (node != aPendingQ) {
-            RefPtr<nsHostRecord> rec = dont_AddRef(static_cast<nsHostRecord *>(node));
+    if (!aPendingQ.isEmpty()) {
+        for (RefPtr<nsHostRecord> rec : aPendingQ) {
             rec->Cancel();
-            node = node->next;
             CompleteLookup(rec, NS_ERROR_ABORT, nullptr, rec->pb);
         }
     }
 }
 
 //
 // FlushCache() is what we call when the network has changed. We must not
 // trust names that were resolved before this change. They may resolve
@@ -617,34 +595,32 @@ nsHostResolver::ClearPendingQueue(PRCLis
 void
 nsHostResolver::FlushCache()
 {
     MutexAutoLock lock(mLock);
     mEvictionQSize = 0;
 
     // Clear the evictionQ and remove all its corresponding entries from
     // the cache first
-    if (!PR_CLIST_IS_EMPTY(&mEvictionQ)) {
-        PRCList *node = mEvictionQ.next;
-        while (node != &mEvictionQ) {
-            nsHostRecord *rec = static_cast<nsHostRecord *>(node);
+    if (!mEvictionQ.isEmpty()) {
+        for (RefPtr<nsHostRecord> rec : mEvictionQ) {
             rec->Cancel();
-            node = node->next;
-            PR_REMOVE_AND_INIT_LINK(rec);
             mRecordDB.Remove(*static_cast<nsHostKey *>(rec));
-            NS_RELEASE(rec);
         }
+        mEvictionQ.clear();
     }
 
     // Refresh the cache entries that are resolving RIGHT now, remove the rest.
     for (auto iter = mRecordDB.Iter(); !iter.Done(); iter.Next()) {
         nsHostRecord* record = iter.UserData();
         // Try to remove the record, or mark it for refresh.
         if (record->RemoveOrRefresh()) {
-            PR_REMOVE_LINK(record);
+            if (record->isInList()) {
+                record->remove();
+            }
             iter.Remove();
         }
     }
 }
 
 void
 nsHostResolver::Shutdown()
 {
@@ -652,55 +628,54 @@ nsHostResolver::Shutdown()
 
     {
         DebugOnly<nsresult> rv = Preferences::UnregisterCallback(
             &DnsPrefChanged, kPrefGetTtl, this);
         NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                              "Could not unregister DNS TTL pref callback.");
     }
 
-    PRCList pendingQHigh, pendingQMed, pendingQLow, evictionQ;
-    PR_INIT_CLIST(&pendingQHigh);
-    PR_INIT_CLIST(&pendingQMed);
-    PR_INIT_CLIST(&pendingQLow);
-    PR_INIT_CLIST(&evictionQ);
+    LinkedList<RefPtr<nsHostRecord>> pendingQHigh, pendingQMed, pendingQLow, evictionQ;
 
     {
         MutexAutoLock lock(mLock);
 
         mShutdown = true;
 
-        MoveCList(mHighQ, pendingQHigh);
-        MoveCList(mMediumQ, pendingQMed);
-        MoveCList(mLowQ, pendingQLow);
-        MoveCList(mEvictionQ, evictionQ);
+        // Move queues to temporary lists.
+        pendingQHigh = mozilla::Move(mHighQ);
+        pendingQMed = mozilla::Move(mMediumQ);
+        pendingQLow = mozilla::Move(mLowQ);
+        evictionQ = mozilla::Move(mEvictionQ);
+
         mEvictionQSize = 0;
         mPendingCount = 0;
 
         if (mNumIdleThreads)
             mIdleThreadCV.NotifyAll();
 
         // empty host database
         mRecordDB.Clear();
     }
 
-    ClearPendingQueue(&pendingQHigh);
-    ClearPendingQueue(&pendingQMed);
-    ClearPendingQueue(&pendingQLow);
+    ClearPendingQueue(pendingQHigh);
+    ClearPendingQueue(pendingQMed);
+    ClearPendingQueue(pendingQLow);
 
-    if (!PR_CLIST_IS_EMPTY(&evictionQ)) {
-        PRCList *node = evictionQ.next;
-        while (node != &evictionQ) {
-            nsHostRecord *rec = static_cast<nsHostRecord *>(node);
+    if (!evictionQ.isEmpty()) {
+        for (RefPtr<nsHostRecord> rec : evictionQ) {
             rec->Cancel();
-            node = node->next;
-            NS_RELEASE(rec);
         }
     }
 
+    pendingQHigh.clear();
+    pendingQMed.clear();
+    pendingQLow.clear();
+    evictionQ.clear();
+
     for (auto iter = mRecordDB.Iter(); !iter.Done(); iter.Next()) {
         iter.UserData()->Cancel();
     }
 #ifdef NS_BUILD_REFCNT_LOGGING
 
     // Logically join the outstanding worker threads with a timeout.
     // Use this approach instead of PR_JoinThread() because that does
     // not allow a timeout which may be necessary for a semi-responsive
@@ -716,25 +691,16 @@ nsHostResolver::Shutdown()
 
     {
         mozilla::DebugOnly<nsresult> rv = GetAddrInfoShutdown();
         NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                              "Failed to shutdown GetAddrInfo");
     }
 }
 
-void
-nsHostResolver::MoveQueue(nsHostRecord *aRec, PRCList &aDestQ)
-{
-    NS_ASSERTION(aRec->onQueue, "Moving Host Record Not Currently Queued");
-
-    PR_REMOVE_LINK(aRec);
-    PR_APPEND_LINK(aRec, &aDestQ);
-}
-
 nsresult
 nsHostResolver::GetHostRecord(const char *host,
                               uint16_t flags, uint16_t af, bool pb,
                               const nsCString &netInterface,
                               const nsCString &originSuffix,
                               nsHostRecord **result)
 {
     MutexAutoLock lock(mLock);
@@ -978,23 +944,27 @@ nsHostResolver::ResolveHost(const char  
 
                     // Consider the case where we are on a pending queue of
                     // lower priority than the request is being made at.
                     // In that case we should upgrade to the higher queue.
 
                     if (IsHighPriority(flags) &&
                         !IsHighPriority(rec->flags)) {
                         // Move from (low|med) to high.
-                        MoveQueue(rec, mHighQ);
+                        NS_ASSERTION(rec->onQueue, "Moving Host Record Not Currently Queued");
+                        rec->remove();
+                        mHighQ.insertBack(rec);
                         rec->flags = flags;
                         ConditionallyCreateThread(rec);
                     } else if (IsMediumPriority(flags) &&
                                IsLowPriority(rec->flags)) {
                         // Move from low to med.
-                        MoveQueue(rec, mMediumQ);
+                        NS_ASSERTION(rec->onQueue, "Moving Host Record Not Currently Queued");
+                        rec->remove();
+                        mMediumQ.insertBack(rec);
                         rec->flags = flags;
                         mIdleThreadCV.Notify();
                     }
                 }
             }
         }
     }
 
@@ -1092,34 +1062,35 @@ nsHostResolver::TrrLookup_unlocked(nsHos
 {
     MutexAutoLock lock(mLock);
     return TrrLookup(rec, pushedTRR);
 }
 
 // returns error if no TRR resolve is issued
 // it is impt this is not called while a native lookup is going on
 nsresult
-nsHostResolver::TrrLookup(nsHostRecord *rec, TRR *pushedTRR)
+nsHostResolver::TrrLookup(nsHostRecord *aRec, TRR *pushedTRR)
 {
+    RefPtr<nsHostRecord> rec(aRec);
     mLock.AssertCurrentThreadOwns();
     MOZ_ASSERT(!TRROutstanding());
     MOZ_ASSERT(!rec->mResolving);
 
     if (!gTRRService || !gTRRService->Enabled()) {
         LOG(("TrrLookup:: %s service not enabled\n", rec->host.get()));
         return NS_ERROR_UNKNOWN_HOST;
     }
 
-    if (rec->next != rec) {
+    if (rec->isInList()) {
         // we're already on the eviction queue. This is a renewal
         MOZ_ASSERT(mEvictionQSize);
-        AssertOnQ(rec, &mEvictionQ);
-        PR_REMOVE_AND_INIT_LINK(rec);
+        AssertOnQ(rec, mEvictionQ);
+
+        rec->remove();
         mEvictionQSize--;
-        rec->Release();
     }
 
     rec->mTRRSuccess = 0; // bump for each successful TRR response
     rec->mTrrAUsed = nsHostRecord::INIT;
     rec->mTrrAAAAUsed = nsHostRecord::INIT;
 
     if (gTRRService && gTRRService->IsTRRBlacklisted(rec->host, rec->pb, true)) {
         Telemetry::Accumulate(Telemetry::DNS_TRR_BLACKLISTED, true);
@@ -1167,58 +1138,57 @@ nsHostResolver::TrrLookup(nsHostRecord *
             }
         }
     } while (sendAgain);
 
     return madeQuery ? NS_OK : NS_ERROR_UNKNOWN_HOST;
 }
 
 void
-nsHostResolver::AssertOnQ(nsHostRecord *rec, PRCList *q)
+nsHostResolver::AssertOnQ(nsHostRecord *rec, LinkedList<RefPtr<nsHostRecord>>& q)
 {
 #ifdef DEBUG
-    MOZ_ASSERT(!PR_CLIST_IS_EMPTY(q));
-    nsHostRecord *i = static_cast<nsHostRecord *>(PR_LIST_HEAD(q));
-    while (i != rec) {
-        MOZ_ASSERT(i->next != q);
-        i = static_cast<nsHostRecord *>(i->next);
+    MOZ_ASSERT(!q.isEmpty());
+    MOZ_ASSERT(rec->isInList());
+    for (RefPtr<nsHostRecord> r: q) {
+        if (rec == r) {
+            return;
+        }
     }
+    MOZ_ASSERT(false, "Did not find element");
 #endif
 }
 
 nsresult
-nsHostResolver::NativeLookup(nsHostRecord *rec)
+nsHostResolver::NativeLookup(nsHostRecord *aRec)
 {
     mLock.AssertCurrentThreadOwns();
+    RefPtr<nsHostRecord> rec(aRec);
 
     rec->mNativeStart = TimeStamp::Now();
 
     // Add rec to one of the pending queues, possibly removing it from mEvictionQ.
-    // If rec is on mEvictionQ, then we can just move the owning
-    // reference over to the new active queue.
-    if (rec->next == rec) { // not on a pending queue
-        NS_ADDREF(rec);
-    } else {
+    if (rec->isInList()) {
         MOZ_ASSERT(mEvictionQSize);
-        AssertOnQ(rec, &mEvictionQ);
-        PR_REMOVE_AND_INIT_LINK(rec); // was on the eviction queue
+        AssertOnQ(rec, mEvictionQ);
+        rec->remove(); // was on the eviction queue
         mEvictionQSize--;
     }
 
     switch (nsHostRecord::GetPriority(rec->flags)) {
         case nsHostRecord::DNS_PRIORITY_HIGH:
-            PR_APPEND_LINK(rec, &mHighQ);
+            mHighQ.insertBack(rec);
             break;
 
         case nsHostRecord::DNS_PRIORITY_MEDIUM:
-            PR_APPEND_LINK(rec, &mMediumQ);
+            mMediumQ.insertBack(rec);
             break;
 
         case nsHostRecord::DNS_PRIORITY_LOW:
-            PR_APPEND_LINK(rec, &mLowQ);
+            mLowQ.insertBack(rec);
             break;
     }
     mPendingCount++;
 
     rec->mNative = true;
     rec->mNativeUsed = true;
     rec->onQueue = true;
     rec->mResolving++;
@@ -1300,21 +1270,21 @@ nsHostResolver::ConditionallyRefreshReco
             Telemetry::Accumulate(Telemetry::DNS_LOOKUP_METHOD2,
                 METHOD_RENEWAL);
         }
     }
     return NS_OK;
 }
 
 void
-nsHostResolver::DeQueue(PRCList &aQ, nsHostRecord **aResult)
+nsHostResolver::DeQueue(LinkedList<RefPtr<nsHostRecord>>& aQ, nsHostRecord **aResult)
 {
-    *aResult = static_cast<nsHostRecord *>(aQ.next);
-    PR_REMOVE_AND_INIT_LINK(*aResult);
+    RefPtr<nsHostRecord> rec = aQ.popFirst();
     mPendingCount--;
+    rec.forget(aResult);
     (*aResult)->onQueue = false;
 }
 
 bool
 nsHostResolver::GetHostToLookup(nsHostRecord **result)
 {
     bool timedOut = false;
     PRIntervalTime epoch, now, timeout;
@@ -1324,32 +1294,32 @@ nsHostResolver::GetHostToLookup(nsHostRe
     timeout = (mNumIdleThreads >= HighThreadThreshold) ? mShortIdleTimeout : mLongIdleTimeout;
     epoch = PR_IntervalNow();
 
     while (!mShutdown) {
         // remove next record from Q; hand over owning reference. Check high, then med, then low
 
 #define SET_GET_TTL(var, val) (var)->mGetTtl = sGetTtlEnabled && (val)
 
-        if (!PR_CLIST_IS_EMPTY(&mHighQ)) {
+        if (!mHighQ.isEmpty()) {
             DeQueue (mHighQ, result);
             SET_GET_TTL(*result, false);
             return true;
         }
 
         if (mActiveAnyThreadCount < HighThreadThreshold) {
-            if (!PR_CLIST_IS_EMPTY(&mMediumQ)) {
+            if (!mMediumQ.isEmpty()) {
                 DeQueue (mMediumQ, result);
                 mActiveAnyThreadCount++;
                 (*result)->usingAnyThread = true;
                 SET_GET_TTL(*result, true);
                 return true;
             }
 
-            if (!PR_CLIST_IS_EMPTY(&mLowQ)) {
+            if (!mLowQ.isEmpty()) {
                 DeQueue (mLowQ, result);
                 mActiveAnyThreadCount++;
                 (*result)->usingAnyThread = true;
                 SET_GET_TTL(*result, true);
                 return true;
             }
         }
 
@@ -1655,35 +1625,31 @@ nsHostResolver::CompleteLookup(nsHostRec
         }
         rec->mDidCallbacks = true;
     }
 
     if (!rec->mResolving && !mShutdown) {
         rec->ResolveComplete();
 
         // add to mEvictionQ
-        MOZ_ASSERT(rec->next == rec && rec->prev == rec); // not on a queue
-        PR_APPEND_LINK(rec, &mEvictionQ);
-        rec->AddRef();
+        MOZ_ASSERT(!rec->isInList());
+        mEvictionQ.insertBack(rec);
         if (mEvictionQSize < mMaxCacheEntries) {
             mEvictionQSize++;
         } else {
             // remove first element on mEvictionQ
-            nsHostRecord *head =
-                static_cast<nsHostRecord *>(PR_LIST_HEAD(&mEvictionQ));
-            PR_REMOVE_AND_INIT_LINK(head);
-            mRecordDB.Remove(*static_cast<nsHostKey *>(head));
+            RefPtr<nsHostRecord> head = mEvictionQ.popFirst();
+            mRecordDB.Remove(*static_cast<nsHostKey *>(head.get()));
 
             if (!head->negative) {
                 // record the age of the entry upon eviction.
                 TimeDuration age = TimeStamp::NowLoRes() - head->mValidStart;
                 Telemetry::Accumulate(Telemetry::DNS_CLEANUP_AGE,
                                       static_cast<uint32_t>(age.ToSeconds() / 60));
             }
-            head->Release(); // release reference owned by mEvictionQ
         }
     }
 
 #ifdef DNSQUERY_AVAILABLE
     // Unless the result is from TRR, resolve again to get TTL
     bool fromTRR = false;
     {
         MutexAutoLock lock(rec->addr_info_lock);
@@ -1740,19 +1706,18 @@ nsHostResolver::CancelAsyncRequest(const
                 break;
             }
         }
 
         // If there are no more callbacks, remove the hash table entry
         if (recPtr && recPtr->mCallbacks.isEmpty()) {
             mRecordDB.Remove(*static_cast<nsHostKey *>(recPtr));
             // If record is on a Queue, remove it and then deref it
-            if (recPtr->next != recPtr) {
-                PR_REMOVE_AND_INIT_LINK(recPtr);
-                NS_RELEASE(recPtr);
+            if (recPtr->isInList()) {
+                recPtr->remove();
             }
         }
     }
 }
 
 size_t
 nsHostResolver::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const
 {
--- a/netwerk/dns/nsHostResolver.h
+++ b/netwerk/dns/nsHostResolver.h
@@ -2,17 +2,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsHostResolver_h__
 #define nsHostResolver_h__
 
 #include "nscore.h"
-#include "prclist.h"
 #include "prnetdb.h"
 #include "PLDHashTable.h"
 #include "mozilla/CondVar.h"
 #include "mozilla/Mutex.h"
 #include "nsISupportsImpl.h"
 #include "nsIDNSListener.h"
 #include "nsIDNSService.h"
 #include "nsTArray.h"
@@ -70,17 +69,19 @@ struct nsHostKey
     bool operator==(const nsHostKey& other) const;
     size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
     PLDHashNumber Hash() const;
 };
 
 /**
  * nsHostRecord - ref counted object type stored in host resolver cache.
  */
-class nsHostRecord : public PRCList, public nsHostKey
+class nsHostRecord :
+    public mozilla::LinkedListElement<RefPtr<nsHostRecord>>,
+    public nsHostKey
 {
     typedef mozilla::Mutex Mutex;
 
 public:
     NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsHostRecord)
 
     /* a fully resolved host record has either a non-null |addr_info| or |addr|
      * field.  if |addr_info| is null, it implies that the |host| is an IP
@@ -389,37 +390,40 @@ public:
 
 private:
    explicit nsHostResolver(uint32_t maxCacheEntries,
                            uint32_t defaultCacheEntryLifetime,
                            uint32_t defaultGracePeriod);
    virtual ~nsHostResolver();
 
     nsresult Init();
-    void AssertOnQ(nsHostRecord *, PRCList *);
+    // In debug builds it asserts that the element is in the list.
+    void AssertOnQ(nsHostRecord *, mozilla::LinkedList<RefPtr<nsHostRecord>>&);
     mozilla::net::ResolverMode Mode();
     nsresult NativeLookup(nsHostRecord *);
     nsresult TrrLookup(nsHostRecord *, mozilla::net::TRR *pushedTRR = nullptr);
 
     // Kick-off a name resolve operation, using native resolver and/or TRR
     nsresult NameLookup(nsHostRecord *);
     bool     GetHostToLookup(nsHostRecord **m);
 
-    void     DeQueue(PRCList &aQ, nsHostRecord **aResult);
-    void     ClearPendingQueue(PRCList *aPendingQueue);
+    // Removes the first element from the list and returns it AddRef-ed in aResult
+    // Should not be called for an empty linked list.
+    void     DeQueue(mozilla::LinkedList<RefPtr<nsHostRecord>>& aQ, nsHostRecord **aResult);
+    // Cancels host records in the pending queue and also
+    // calls CompleteLookup with the NS_ERROR_ABORT result code.
+    void     ClearPendingQueue(mozilla::LinkedList<RefPtr<nsHostRecord>>& aPendingQ);
     nsresult ConditionallyCreateThread(nsHostRecord *rec);
 
     /**
      * Starts a new lookup in the background for entries that are in the grace
      * period with a failed connect or all cached entries are negative.
      */
     nsresult ConditionallyRefreshRecord(nsHostRecord *rec, const char *host);
 
-    static void  MoveQueue(nsHostRecord *aRec, PRCList &aDestQ);
-
     static void ThreadFunc(void *);
 
     enum {
         METHOD_HIT = 1,
         METHOD_RENEWAL = 2,
         METHOD_NEGATIVE_HIT = 3,
         METHOD_LITERAL = 4,
         METHOD_OVERFLOW = 5,
@@ -428,20 +432,20 @@ private:
     };
 
     uint32_t      mMaxCacheEntries;
     uint32_t      mDefaultCacheLifetime; // granularity seconds
     uint32_t      mDefaultGracePeriod; // granularity seconds
     mutable Mutex mLock;    // mutable so SizeOfIncludingThis can be const
     CondVar       mIdleThreadCV;
     nsRefPtrHashtable<nsGenericHashKey<nsHostKey>, nsHostRecord> mRecordDB;
-    PRCList       mHighQ;
-    PRCList       mMediumQ;
-    PRCList       mLowQ;
-    PRCList       mEvictionQ;
+    mozilla::LinkedList<RefPtr<nsHostRecord>> mHighQ;
+    mozilla::LinkedList<RefPtr<nsHostRecord>> mMediumQ;
+    mozilla::LinkedList<RefPtr<nsHostRecord>> mLowQ;
+    mozilla::LinkedList<RefPtr<nsHostRecord>> mEvictionQ;
     uint32_t      mEvictionQSize;
     PRTime        mCreationTime;
     PRIntervalTime mLongIdleTimeout;
     PRIntervalTime mShortIdleTimeout;
 
     mozilla::Atomic<bool>     mShutdown;
     mozilla::Atomic<uint32_t> mNumIdleThreads;
     mozilla::Atomic<uint32_t> mThreadCount;