Bug 809756 - Backout bug 803665, bug 803668, bug 803666 and bug 803669 on a CLOSED TREE.
authorMs2ger <ms2ger@gmail.com>
Thu, 08 Nov 2012 09:20:25 +0100
changeset 112670 82c59210f11fbad3621810e0787de8db6c026c83
parent 112552 eb636c95b1c0858336d2a9d5d6ba08113c62efdb
child 112671 e0d7b394462b18bea7f70c5f6aa297800371d666
push id23833
push useremorley@mozilla.com
push dateThu, 08 Nov 2012 10:20:57 +0000
treeherdermozilla-central@e0d7b394462b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs809756, 803665, 803668, 803666, 803669
milestone19.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 809756 - Backout bug 803665, bug 803668, bug 803666 and bug 803669 on a CLOSED TREE.
dom/base/nsGlobalWindow.cpp
dom/base/nsGlobalWindow.h
intl/strres/src/nsStringBundle.cpp
intl/strres/src/nsStringBundleService.h
parser/htmlparser/public/nsScannerString.h
parser/htmlparser/src/nsScannerString.cpp
uriloader/base/nsDocLoader.cpp
uriloader/base/nsDocLoader.h
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -528,33 +528,27 @@ public:
 
 private:
   nsGlobalWindow* mWindow;
 };
 
 NS_IMPL_ISUPPORTS2(nsGlobalWindowObserver, nsIObserver, nsIInterfaceRequestor)
 
 nsTimeout::nsTimeout()
-  : mCleared(false),
-    mRunning(false),
-    mIsInterval(false),
-    mPublicId(0),
-    mInterval(0),
-    mFiringDepth(0),
-    mNestingLevel(0),
-    mPopupState(openAllowed)
 {
 #ifdef DEBUG_jst
   {
     extern int gTimeoutCnt;
 
     ++gTimeoutCnt;
   }
 #endif
 
+  memset(this, 0, sizeof(*this));
+
   MOZ_COUNT_CTOR(nsTimeout);
 }
 
 nsTimeout::~nsTimeout()
 {
 #ifdef DEBUG_jst
   {
     extern int gTimeoutCnt;
@@ -724,16 +718,19 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalW
     mStopAbuseDialogs(false),
     mDialogsPermanentlyDisabled(false)
 {
   nsLayoutStatics::AddRef();
 
   // Initialize the PRCList (this).
   PR_INIT_CLIST(this);
 
+  // Initialize timeout storage
+  PR_INIT_CLIST(&mTimeouts);
+
   if (aOuterWindow) {
     // |this| is an inner window, add this inner window to the outer
     // window list of inners.
     PR_INSERT_AFTER(this, aOuterWindow);
 
     mObserver = new nsGlobalWindowObserver(this);
     if (mObserver) {
       NS_ADDREF(mObserver);
@@ -1312,19 +1309,19 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mPerformance, nsPerformance)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mInnerWindowHolder)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOuterWindow)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mListenerManager,
                                                   nsEventListenerManager)
 
-  for (nsTimeout* timeout = tmp->mTimeouts.getFirst();
-       timeout;
-       timeout = timeout->getNext()) {
+  for (nsTimeout* timeout = tmp->FirstTimeout();
+       tmp->IsTimeout(timeout);
+       timeout = timeout->Next()) {
     cb.NoteNativeChild(timeout, NS_CYCLE_COLLECTION_PARTICIPANT(nsTimeout));
   }
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLocalStorage)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mSessionStorage)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mApplicationCache)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocumentPrincipal)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDoc)
@@ -1419,19 +1416,19 @@ nsGlobalWindow::IsBlackForCC()
     (mDoc &&
      nsCCUncollectableMarker::InGeneration(mDoc->GetMarkedCCGeneration())) ||
     (nsCCUncollectableMarker::sGeneration && IsBlack());
 }
 
 void
 nsGlobalWindow::UnmarkGrayTimers()
 {
-  for (nsTimeout* timeout = mTimeouts.getFirst();
-       timeout;
-       timeout = timeout->getNext()) {
+  for (nsTimeout* timeout = FirstTimeout();
+       timeout && IsTimeout(timeout);
+       timeout = timeout->Next()) {
     if (timeout->mScriptHandler) {
       JSObject* o = timeout->mScriptHandler->GetScriptObject();
       xpc_UnmarkGrayObject(o);
     }
   }
 }
 
 //*****************************************************************************
@@ -2311,17 +2308,18 @@ nsGlobalWindow::DetachFromDocShell()
   NS_ASSERTION(IsOuterWindow(), "Uh, DetachFromDocShell() called on inner window!");
 
   // DetachFromDocShell means the window is being torn down. Drop our
   // reference to the script context, allowing it to be deleted
   // later. Meanwhile, keep our weak reference to the script object
   // (mJSObject) so that it can be retrieved later (until it is
   // finalized by the JS GC).
 
-  NS_ASSERTION(mTimeouts.isEmpty(), "Uh, outer window holds timeouts!");
+  NS_ASSERTION(PR_CLIST_IS_EMPTY(&mTimeouts),
+               "Uh, outer window holds timeouts!");
 
   // Call FreeInnerObjects on all inner windows, not just the current
   // one, since some could be held by WindowStateHolder objects that
   // are GC-owned.
   for (nsRefPtr<nsGlobalWindow> inner = (nsGlobalWindow *)PR_LIST_HEAD(this);
        inner != this;
        inner = (nsGlobalWindow*)PR_NEXT_LINK(inner)) {
     NS_ASSERTION(!inner->mOuterWindow || inner->mOuterWindow == this,
@@ -9896,17 +9894,17 @@ nsGlobalWindow::RunTimeout(nsTimeout *aT
     deadline = now;
   }
 
   // The timeout list is kept in deadline order. Discover the latest
   // timeout whose deadline has expired. On some platforms, native
   // timeout events fire "early", so we need to test the timer as well
   // as the deadline.
   last_expired_timeout = nullptr;
-  for (timeout = mTimeouts.getFirst(); timeout; timeout = timeout->getNext()) {
+  for (timeout = FirstTimeout(); IsTimeout(timeout); timeout = timeout->Next()) {
     if (((timeout == aTimeout) || (timeout->mWhen <= deadline)) &&
         (timeout->mFiringDepth == 0)) {
       // Mark any timeouts that are on the list to be fired with the
       // firing depth so that we can reentrantly run timeouts
       timeout->mFiringDepth = firingDepth;
       last_expired_timeout = timeout;
     }
   }
@@ -9930,34 +9928,34 @@ nsGlobalWindow::RunTimeout(nsTimeout *aT
 
   // Insert a dummy timeout into the list of timeouts between the
   // portion of the list that we are about to process now and those
   // timeouts that will be processed in a future call to
   // win_run_timeout(). This dummy timeout serves as the head of the
   // list for any timeouts inserted as a result of running a timeout.
   dummy_timeout.mFiringDepth = firingDepth;
   dummy_timeout.mWhen = now;
-  last_expired_timeout->setNext(&dummy_timeout);
+  PR_INSERT_AFTER(&dummy_timeout, last_expired_timeout);
 
   // Don't let ClearWindowTimeouts throw away our stack-allocated
   // dummy timeout.
   dummy_timeout.AddRef();
   dummy_timeout.AddRef();
 
   last_insertion_point = mTimeoutInsertionPoint;
   // If we ever start setting mTimeoutInsertionPoint to a non-dummy timeout,
   // the logic in ResetTimersForNonBackgroundWindow will need to change.
   mTimeoutInsertionPoint = &dummy_timeout;
 
   Telemetry::AutoCounter<Telemetry::DOM_TIMERS_FIRED_PER_NATIVE_TIMEOUT> timeoutsRan;
 
-  for (timeout = mTimeouts.getFirst();
+  for (timeout = FirstTimeout();
        timeout != &dummy_timeout && !IsFrozen();
        timeout = nextTimeout) {
-    nextTimeout = timeout->getNext();
+    nextTimeout = timeout->Next();
 
     if (timeout->mFiringDepth != firingDepth) {
       // We skip the timeout since it's on the list to run at another
       // depth.
 
       continue;
     }
 
@@ -10011,32 +10009,32 @@ nsGlobalWindow::RunTimeout(nsTimeout *aT
     }
 
     // If we have a regular interval timer, we re-schedule the
     // timeout, accounting for clock drift.
     bool needsReinsertion = RescheduleTimeout(timeout, now, !aTimeout);
 
     // Running a timeout can cause another timeout to be deleted, so
     // we need to reset the pointer to the following timeout.
-    nextTimeout = timeout->getNext();
-
-    timeout->remove();
+    nextTimeout = timeout->Next();
+
+    PR_REMOVE_LINK(timeout);
 
     if (needsReinsertion) {
       // Insert interval timeout onto list sorted in deadline order.
       // AddRefs timeout.
       InsertTimeoutIntoList(timeout);
     }
 
     // Release the timeout struct since it's possibly out of the list
     timeout->Release();
   }
 
   // Take the dummy timeout off the head of the list
-  dummy_timeout.remove();
+  PR_REMOVE_LINK(&dummy_timeout);
 
   mTimeoutInsertionPoint = last_insertion_point;
 }
 
 nsrefcnt
 nsTimeout::Release()
 {
   if (--mRefCnt > 0)
@@ -10064,27 +10062,29 @@ nsTimeout::AddRef()
 nsresult
 nsGlobalWindow::ClearTimeoutOrInterval(int32_t aTimerID)
 {
   FORWARD_TO_INNER(ClearTimeoutOrInterval, (aTimerID), NS_ERROR_NOT_INITIALIZED);
 
   uint32_t public_id = (uint32_t)aTimerID;
   nsTimeout *timeout;
 
-  for (timeout = mTimeouts.getFirst(); timeout; timeout = timeout->getNext()) {
+  for (timeout = FirstTimeout();
+       IsTimeout(timeout);
+       timeout = timeout->Next()) {
     if (timeout->mPublicId == public_id) {
       if (timeout->mRunning) {
         /* We're running from inside the timeout. Mark this
            timeout for deferred deletion by the code in
            RunTimeout() */
         timeout->mIsInterval = false;
       }
       else {
         /* Delete the timeout from the pending timeout list */
-        timeout->remove();
+        PR_REMOVE_LINK(timeout);
 
         if (timeout->mTimer) {
           timeout->mTimer->Cancel();
           timeout->mTimer = nullptr;
           timeout->Release();
         }
         timeout->Release();
       }
@@ -10109,23 +10109,23 @@ nsresult nsGlobalWindow::ResetTimersForN
   // If mTimeoutInsertionPoint is non-null, we're in the middle of firing
   // timers and the timers we're planning to fire all come before
   // mTimeoutInsertionPoint; mTimeoutInsertionPoint itself is a dummy timeout
   // with an mWhen that may be semi-bogus.  In that case, we don't need to do
   // anything with mTimeoutInsertionPoint or anything before it, so should
   // start at the timer after mTimeoutInsertionPoint, if there is one.
   // Otherwise, start at the beginning of the list.
   for (nsTimeout *timeout = mTimeoutInsertionPoint ?
-         mTimeoutInsertionPoint->getNext() : mTimeouts.getFirst();
-       timeout; ) {
+         mTimeoutInsertionPoint->Next() : FirstTimeout();
+       IsTimeout(timeout); ) {
     // It's important that this check be <= so that we guarantee that
     // taking NS_MAX with |now| won't make a quantity equal to
     // timeout->mWhen below.
     if (timeout->mWhen <= now) {
-      timeout = timeout->getNext();
+      timeout = timeout->Next();
       continue;
     }
 
     if (timeout->mWhen - now >
         TimeDuration::FromMilliseconds(gMinBackgroundTimeoutValue)) {
       // No need to loop further.  Timeouts are sorted in mWhen order
       // and the ones after this point were all set up for at least
       // gMinBackgroundTimeoutValue ms and hence were not clamped.
@@ -10152,62 +10152,62 @@ nsresult nsGlobalWindow::ResetTimersForN
       TimeDuration delay = firingTime - now;
       timeout->mWhen = firingTime;
 
       // Since we reset mWhen we need to move |timeout| to the right
       // place in the list so that it remains sorted by mWhen.
       
       // Get the pointer to the next timeout now, before we move the
       // current timeout in the list.
-      nsTimeout* nextTimeout = timeout->getNext();
+      nsTimeout* nextTimeout = timeout->Next();
 
       // It is safe to remove and re-insert because mWhen is now
       // strictly smaller than it used to be, so we know we'll insert
       // |timeout| before nextTimeout.
-      NS_ASSERTION(!nextTimeout ||
+      NS_ASSERTION(!IsTimeout(nextTimeout) ||
                    timeout->mWhen < nextTimeout->mWhen, "How did that happen?");
-      timeout->remove();
+      PR_REMOVE_LINK(timeout);
       // InsertTimeoutIntoList will addref |timeout| and reset
       // mFiringDepth.  Make sure to undo that after calling it.
       uint32_t firingDepth = timeout->mFiringDepth;
       InsertTimeoutIntoList(timeout);
       timeout->mFiringDepth = firingDepth;
       timeout->Release();
 
       nsresult rv = timeout->InitTimer(TimerCallback, delay.ToMilliseconds());
 
       if (NS_FAILED(rv)) {
         NS_WARNING("Error resetting non background timer for DOM timeout!");
         return rv;
       }
 
       timeout = nextTimeout;
     } else {
-      timeout = timeout->getNext();
+      timeout = timeout->Next();
     }
   }
 
   return NS_OK;
 }
 
 void
 nsGlobalWindow::ClearAllTimeouts()
 {
   nsTimeout *timeout, *nextTimeout;
 
-  for (timeout = mTimeouts.getFirst(); timeout; timeout = nextTimeout) {
+  for (timeout = FirstTimeout(); IsTimeout(timeout); timeout = nextTimeout) {
     /* If RunTimeout() is higher up on the stack for this
        window, e.g. as a result of document.write from a timeout,
        then we need to reset the list insertion point for
        newly-created timeouts in case the user adds a timeout,
        before we pop the stack back to RunTimeout. */
     if (mRunningTimeout == timeout)
       mTimeoutInsertionPoint = nullptr;
 
-    nextTimeout = timeout->getNext();
+    nextTimeout = timeout->Next();
 
     if (timeout->mTimer) {
       timeout->mTimer->Cancel();
       timeout->mTimer = nullptr;
 
       // Drop the count since the timer isn't going to hold on
       // anymore.
       timeout->Release();
@@ -10217,46 +10217,42 @@ nsGlobalWindow::ClearAllTimeouts()
     // cleared and taken out of the list of timeouts
     timeout->mCleared = true;
 
     // Drop the count since we're removing it from the list.
     timeout->Release();
   }
 
   // Clear out our list
-  mTimeouts.clear();
+  PR_INIT_CLIST(&mTimeouts);
 }
 
 void
 nsGlobalWindow::InsertTimeoutIntoList(nsTimeout *aTimeout)
 {
   NS_ASSERTION(IsInnerWindow(),
                "InsertTimeoutIntoList() called on outer window!");
 
   // Start at mLastTimeout and go backwards.  Don't go further than
   // mTimeoutInsertionPoint, though.  This optimizes for the common case of
   // insertion at the end.
   nsTimeout* prevSibling;
-  for (prevSibling = mTimeouts.getLast();
-       prevSibling && prevSibling != mTimeoutInsertionPoint &&
+  for (prevSibling = LastTimeout();
+       IsTimeout(prevSibling) && prevSibling != mTimeoutInsertionPoint &&
          // This condition needs to match the one in SetTimeoutOrInterval that
          // determines whether to set mWhen or mTimeRemaining.
          ((IsFrozen() || mTimeoutsSuspendDepth) ?
           prevSibling->mTimeRemaining > aTimeout->mTimeRemaining :
           prevSibling->mWhen > aTimeout->mWhen);
-       prevSibling = prevSibling->getPrevious()) {
+       prevSibling = prevSibling->Prev()) {
     /* Do nothing; just searching */
   }
 
   // Now link in aTimeout after prevSibling.
-  if (prevSibling) {
-    prevSibling->setNext(aTimeout);
-  } else {
-    mTimeouts.insertFront(aTimeout);
-  }
+  PR_INSERT_AFTER(aTimeout, prevSibling);
 
   aTimeout->mFiringDepth = 0;
 
   // Increment the timeout's reference count since it's now held on to
   // by the list
   aTimeout->AddRef();
 }
 
@@ -10538,17 +10534,17 @@ nsGlobalWindow::SuspendTimeouts(uint32_t
     }
 
     // Suspend all of the workers for this window.
     nsIScriptContext *scx = GetContextInternal();
     JSContext *cx = scx ? scx->GetNativeContext() : nullptr;
     mozilla::dom::workers::SuspendWorkersForWindow(cx, this);
 
     TimeStamp now = TimeStamp::Now();
-    for (nsTimeout *t = mTimeouts.getFirst(); t; t = t->getNext()) {
+    for (nsTimeout *t = FirstTimeout(); IsTimeout(t); t = t->Next()) {
       // Set mTimeRemaining to be the time remaining for this timer.
       if (t->mWhen > now)
         t->mTimeRemaining = t->mWhen - now;
       else
         t->mTimeRemaining = TimeDuration(0);
   
       // Drop the XPCOM timer; we'll reschedule when restoring the state.
       if (t->mTimer) {
@@ -10626,17 +10622,17 @@ nsGlobalWindow::ResumeTimeouts(bool aTha
     // (stored in timeout->mTimeRemaining).
 
     TimeStamp now = TimeStamp::Now();
 
 #ifdef DEBUG
     bool _seenDummyTimeout = false;
 #endif
 
-    for (nsTimeout *t = mTimeouts.getFirst(); t; t = t->getNext()) {
+    for (nsTimeout *t = FirstTimeout(); IsTimeout(t); t = t->Next()) {
       // There's a chance we're being called with RunTimeout on the stack in which
       // case we have a dummy timeout in the list that *must not* be resumed. It
       // can be identified by a null mWindow.
       if (!t->mWindow) {
 #ifdef DEBUG
         NS_ASSERTION(!_seenDummyTimeout, "More than one dummy timeout?!");
         _seenDummyTimeout = true;
 #endif
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -54,17 +54,16 @@
 #include "nsIDOMStorageObsolete.h"
 #include "nsIDOMStorageEvent.h"
 #include "nsIDOMStorageIndexedDB.h"
 #include "nsIDOMOfflineResourceList.h"
 #include "nsIArray.h"
 #include "nsIContent.h"
 #include "nsIIDBFactory.h"
 #include "nsFrameMessageManager.h"
-#include "mozilla/LinkedList.h"
 #include "mozilla/TimeStamp.h"
 #include "nsIDOMTouchEvent.h"
 #include "nsIInlineEventHandlers.h"
 #include "nsWrapperCacheInlines.h"
 #include "nsIDOMApplicationRegistry.h"
 #include "nsIIdleObserver.h"
 #include "nsIDOMWakeLock.h"
 
@@ -130,26 +129,36 @@ NS_CreateJSTimeoutHandler(nsGlobalWindow
                           int32_t *aInterval,
                           nsIScriptTimeoutHandler **aRet);
 
 /*
  * Timeout struct that holds information about each script
  * timeout.  Holds a strong reference to an nsIScriptTimeoutHandler, which
  * abstracts the language specific cruft.
  */
-struct nsTimeout : mozilla::LinkedListElement<nsTimeout>
+struct nsTimeout : PRCList
 {
   nsTimeout();
   ~nsTimeout();
 
   NS_DECL_CYCLE_COLLECTION_LEGACY_NATIVE_CLASS(nsTimeout)
 
   nsrefcnt Release();
   nsrefcnt AddRef();
 
+  nsTimeout* Next() {
+    // Note: might not actually return an nsTimeout.  Use IsTimeout to check.
+    return static_cast<nsTimeout*>(PR_NEXT_LINK(this));
+  }
+
+  nsTimeout* Prev() {
+    // Note: might not actually return an nsTimeout.  Use IsTimeout to check.
+    return static_cast<nsTimeout*>(PR_PREV_LINK(this));
+  }
+
   nsresult InitTimer(nsTimerCallbackFunc aFunc, uint64_t delay) {
     return mTimer->InitWithFuncCallback(aFunc, this, delay,
                                         nsITimer::TYPE_ONE_SHOT);
   }
 
   // Window for which this timeout fires
   nsRefPtr<nsGlobalWindow> mWindow;
 
@@ -858,16 +867,30 @@ protected:
   void Thaw()
   {
     mIsFrozen = false;
     NotifyDOMWindowThawed(this);
   }
 
   bool IsInModalState();
 
+  nsTimeout* FirstTimeout() {
+    // Note: might not actually return an nsTimeout.  Use IsTimeout to check.
+    return static_cast<nsTimeout*>(PR_LIST_HEAD(&mTimeouts));
+  }
+
+  nsTimeout* LastTimeout() {
+    // Note: might not actually return an nsTimeout.  Use IsTimeout to check.
+    return static_cast<nsTimeout*>(PR_LIST_TAIL(&mTimeouts));
+  }
+
+  bool IsTimeout(PRCList* aList) {
+    return aList != &mTimeouts;
+  }
+
   // Convenience functions for the many methods that need to scale
   // from device to CSS pixels or vice versa.  Note: if a presentation
   // context is not available, they will assume a 1:1 ratio.
   int32_t DevToCSSIntPixels(int32_t px);
   int32_t CSSToDevIntPixels(int32_t px);
   nsIntSize DevToCSSIntPixels(nsIntSize px);
   nsIntSize CSSToDevIntPixels(nsIntSize px);
 
@@ -1025,17 +1048,17 @@ protected:
   nsCOMPtr<nsIXPConnectJSObjectHolder> mInnerWindowHolder;
 
   // These member variable are used only on inner windows.
   nsRefPtr<nsEventListenerManager> mListenerManager;
   // mTimeouts is generally sorted by mWhen, unless mTimeoutInsertionPoint is
   // non-null.  In that case, the dummy timeout pointed to by
   // mTimeoutInsertionPoint may have a later mWhen than some of the timeouts
   // that come after it.
-  mozilla::LinkedList<nsTimeout> mTimeouts;
+  PRCList                       mTimeouts;
   // If mTimeoutInsertionPoint is non-null, insertions should happen after it.
   // This is a dummy timeout at the moment; if that ever changes, the logic in
   // ResetTimersForNonBackgroundWindow needs to change.
   nsTimeout*                    mTimeoutInsertionPoint;
   uint32_t                      mTimeoutPublicIdCounter;
   uint32_t                      mTimeoutFiringDepth;
   nsRefPtr<nsLocation>          mLocation;
   nsRefPtr<nsHistory>           mHistory;
--- a/intl/strres/src/nsStringBundle.cpp
+++ b/intl/strres/src/nsStringBundle.cpp
@@ -496,30 +496,32 @@ nsresult nsExtensibleStringBundle::GetSi
   *aResult = nullptr;
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 /////////////////////////////////////////////////////////////////////////////////////////
 
 #define MAX_CACHED_BUNDLES 16
 
-struct bundleCacheEntry_t : public LinkedListElement<bundleCacheEntry_t> {
+struct bundleCacheEntry_t {
+  PRCList list;
   nsCStringKey *mHashKey;
   // do not use a nsCOMPtr - this is a struct not a class!
   nsIStringBundle* mBundle;
 };
 
 
 nsStringBundleService::nsStringBundleService() :
   mBundleMap(MAX_CACHED_BUNDLES, true)
 {
 #ifdef DEBUG_tao_
   printf("\n++ nsStringBundleService::nsStringBundleService ++\n");
 #endif
 
+  PR_INIT_CLIST(&mBundleCache);
   PL_InitArenaPool(&mCacheEntryPool, "srEntries",
                    sizeof(bundleCacheEntry_t)*MAX_CACHED_BUNDLES,
                    sizeof(bundleCacheEntry_t));
 
   mErrorService = do_GetService(kErrorServiceCID);
   NS_ASSERTION(mErrorService, "Couldn't get error service");
 
 }
@@ -575,20 +577,26 @@ nsStringBundleService::Observe(nsISuppor
 }
 
 void
 nsStringBundleService::flushBundleCache()
 {
   // release all bundles in the cache
   mBundleMap.Reset();
   
-  while (!mBundleCache.isEmpty()) {
-    bundleCacheEntry_t *cacheEntry = mBundleCache.popFirst();
+  PRCList *current = PR_LIST_HEAD(&mBundleCache);
+  while (current != &mBundleCache) {
+    bundleCacheEntry_t *cacheEntry = (bundleCacheEntry_t*)current;
 
     recycleEntry(cacheEntry);
+    PRCList *oldItem = current;
+    current = PR_NEXT_LINK(current);
+    
+    // will be freed in PL_FreeArenaPool
+    PR_REMOVE_LINK(oldItem);
   }
   PL_FreeArenaPool(&mCacheEntryPool);
 }
 
 NS_IMETHODIMP
 nsStringBundleService::FlushBundles()
 {
   flushBundleCache();
@@ -603,34 +611,35 @@ nsStringBundleService::getStringBundle(c
 
   bundleCacheEntry_t* cacheEntry =
     (bundleCacheEntry_t*)mBundleMap.Get(&completeKey);
   
   if (cacheEntry) {
     // cache hit!
     // remove it from the list, it will later be reinserted
     // at the head of the list
-    cacheEntry->remove();
+    PR_REMOVE_LINK((PRCList*)cacheEntry);
     
   } else {
 
     // hasn't been cached, so insert it into the hash table
     nsStringBundle* bundle = new nsStringBundle(aURLSpec, mOverrideStrings);
     if (!bundle) return NS_ERROR_OUT_OF_MEMORY;
     NS_ADDREF(bundle);
     
     cacheEntry = insertIntoCache(bundle, &completeKey);
     NS_RELEASE(bundle);         // cache should now be holding a ref
                                 // in the cacheEntry
   }
 
   // at this point the cacheEntry should exist in the hashtable,
   // but is not in the LRU cache.
   // put the cache entry at the front of the list
-  mBundleCache.insertFront(cacheEntry);
+  
+  PR_INSERT_LINK((PRCList *)cacheEntry, &mBundleCache);
 
   // finally, return the value
   *aResult = cacheEntry->mBundle;
   NS_ADDREF(*aResult);
 
   return NS_OK;
 }
 
@@ -640,33 +649,33 @@ nsStringBundleService::insertIntoCache(n
 {
   bundleCacheEntry_t *cacheEntry;
   
   if (mBundleMap.Count() < MAX_CACHED_BUNDLES) {
     // cache not full - create a new entry
     
     void *cacheEntryArena;
     PL_ARENA_ALLOCATE(cacheEntryArena, &mCacheEntryPool, sizeof(bundleCacheEntry_t));
-    cacheEntry = new (cacheEntryArena) bundleCacheEntry_t();
+    cacheEntry = (bundleCacheEntry_t*)cacheEntryArena;
       
   } else {
     // cache is full
     // take the last entry in the list, and recycle it.
-    cacheEntry = mBundleCache.getLast();
+    cacheEntry = (bundleCacheEntry_t*)PR_LIST_TAIL(&mBundleCache);
       
     // remove it from the hash table and linked list
     NS_ASSERTION(mBundleMap.Exists(cacheEntry->mHashKey),
                  "Element will not be removed!");
 #ifdef DEBUG_alecf
     NS_WARNING(nsPrintfCString("Booting %s to make room for %s\n",
                                cacheEntry->mHashKey->GetString(),
                                aHashKey->GetString()).get());
 #endif
     mBundleMap.Remove(cacheEntry->mHashKey);
-    cacheEntry->remove();
+    PR_REMOVE_LINK((PRCList*)cacheEntry);
 
     // free up excess memory
     recycleEntry(cacheEntry);
   }
     
   // at this point we have a new cacheEntry that doesn't exist
   // in the hashtable, so set up the cacheEntry
   cacheEntry->mBundle = aBundle;
--- a/intl/strres/src/nsStringBundleService.h
+++ b/intl/strres/src/nsStringBundleService.h
@@ -1,29 +1,28 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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 nsStringBundleService_h__
 #define nsStringBundleService_h__
 
+#include "prclist.h"
 #include "plarena.h"
 
 #include "nsCOMPtr.h"
 #include "nsHashtable.h"
 #include "nsIPersistentProperties2.h"
 #include "nsIStringBundle.h"
 #include "nsIObserver.h"
 #include "nsWeakReference.h"
 #include "nsIErrorService.h"
 #include "nsIStringBundleOverride.h"
 
-#include "mozilla/LinkedList.h"
-
 struct bundleCacheEntry_t;
 
 class nsStringBundleService : public nsIStringBundleService,
                               public nsIObserver,
                               public nsSupportsWeakReference
 {
 public:
   nsStringBundleService();
@@ -44,16 +43,16 @@ private:
   void flushBundleCache();
   
   bundleCacheEntry_t *insertIntoCache(nsIStringBundle *aBundle,
                                       nsCStringKey *aHashKey);
 
   static void recycleEntry(bundleCacheEntry_t*);
   
   nsHashtable mBundleMap;
-  mozilla::LinkedList<bundleCacheEntry_t> mBundleCache;
+  PRCList mBundleCache;
   PLArenaPool mCacheEntryPool;
 
   nsCOMPtr<nsIErrorService>     mErrorService;
   nsCOMPtr<nsIStringBundleOverride> mOverrideStrings;
 };
 
 #endif
--- a/parser/htmlparser/public/nsScannerString.h
+++ b/parser/htmlparser/public/nsScannerString.h
@@ -4,17 +4,17 @@
  * 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 nsScannerString_h___
 #define nsScannerString_h___
 
 #include "nsString.h"
 #include "nsUnicharUtils.h" // for nsCaseInsensitiveStringComparator
-#include "mozilla/LinkedList.h"
+#include "prclist.h"
 
 
   /**
    * NOTE: nsScannerString (and the other classes defined in this file) are
    * not related to nsAString or any of the other xpcom/string classes.
    *
    * nsScannerString is based on the nsSlidingString implementation that used
    * to live in xpcom/string.  Now that nsAString is limited to representing
@@ -55,36 +55,36 @@ class nsScannerBufferList
   {
     public:
 
         /**
          * Buffer objects are directly followed by a data segment.  The start
          * of the data segment is determined by increment the |this| pointer
          * by 1 unit.
          */
-      class Buffer : public mozilla::LinkedListElement<Buffer>
+      class Buffer : public PRCList
         {
           public:
 
             void IncrementUsageCount() { ++mUsageCount; }
             void DecrementUsageCount() { --mUsageCount; }
 
             bool IsInUse() const { return mUsageCount != 0; }
 
             const PRUnichar* DataStart() const { return (const PRUnichar*) (this+1); }
                   PRUnichar* DataStart()       { return (      PRUnichar*) (this+1); }
 
             const PRUnichar* DataEnd() const { return mDataEnd; }
                   PRUnichar* DataEnd()       { return mDataEnd; }
 
-            const Buffer* Next() const { return getNext(); }
-                  Buffer* Next()       { return getNext(); }
+            const Buffer* Next() const { return static_cast<const Buffer*>(next); }
+                  Buffer* Next()       { return static_cast<Buffer*>(next); }
 
-            const Buffer* Prev() const { return getPrevious(); }
-                  Buffer* Prev()       { return getPrevious(); }
+            const Buffer* Prev() const { return static_cast<const Buffer*>(prev); }
+                  Buffer* Prev()       { return static_cast<Buffer*>(prev); }
 
             uint32_t DataLength() const { return mDataEnd - DataStart(); }
             void SetDataLength(uint32_t len) { mDataEnd = DataStart() + len; }
 
           private:
 
             friend class nsScannerBufferList;
 
@@ -121,42 +121,43 @@ class nsScannerBufferList
         };
 
       static Buffer* AllocBufferFromString( const nsAString& );
       static Buffer* AllocBuffer( uint32_t capacity ); // capacity = number of chars
 
       nsScannerBufferList( Buffer* buf )
         : mRefCnt(0)
         {
-          mBuffers.insertBack(buf);
+          PR_INIT_CLIST(&mBuffers);
+          PR_APPEND_LINK(buf, &mBuffers);
         }
 
       void  AddRef()  { ++mRefCnt; }
       void  Release() { if (--mRefCnt == 0) delete this; }
 
-      void  Append( Buffer* buf ) { mBuffers.insertBack(buf); } 
-      void  InsertAfter( Buffer* buf, Buffer* prev ) { prev->setNext(buf); }
+      void  Append( Buffer* buf ) { PR_APPEND_LINK(buf, &mBuffers); } 
+      void  InsertAfter( Buffer* buf, Buffer* prev ) { PR_INSERT_AFTER(buf, prev); }
       void  SplitBuffer( const Position& );
       void  DiscardUnreferencedPrefix( Buffer* );
 
-            Buffer* Head()       { return mBuffers.getFirst(); }
-      const Buffer* Head() const { return mBuffers.getFirst(); }
+            Buffer* Head()       { return static_cast<Buffer*>(PR_LIST_HEAD(&mBuffers)); }
+      const Buffer* Head() const { return static_cast<const Buffer*>(PR_LIST_HEAD(&mBuffers)); }
 
-            Buffer* Tail()       { return mBuffers.getLast(); }
-      const Buffer* Tail() const { return mBuffers.getLast(); }
+            Buffer* Tail()       { return static_cast<Buffer*>(PR_LIST_TAIL(&mBuffers)); }
+      const Buffer* Tail() const { return static_cast<const Buffer*>(PR_LIST_TAIL(&mBuffers)); }
 
     private:
 
       friend class nsScannerSubstring;
 
       ~nsScannerBufferList() { ReleaseAll(); }
       void ReleaseAll();
 
       int32_t mRefCnt;
-      mozilla::LinkedList<Buffer> mBuffers;
+      PRCList mBuffers;
   };
 
 
   /**
    * nsScannerFragment represents a "slice" of a Buffer object.
    */
 struct nsScannerFragment
   {
--- a/parser/htmlparser/src/nsScannerString.cpp
+++ b/parser/htmlparser/src/nsScannerString.cpp
@@ -14,56 +14,69 @@
 
 #define MAX_CAPACITY ((UINT32_MAX / sizeof(PRUnichar)) - \
                       (sizeof(Buffer) + sizeof(PRUnichar)))
 
 nsScannerBufferList::Buffer*
 nsScannerBufferList::AllocBufferFromString( const nsAString& aString )
   {
     uint32_t len = aString.Length();
-    Buffer* buf = AllocBuffer(len);
 
+    if (len > MAX_CAPACITY)
+      return nullptr;
+
+    Buffer* buf = (Buffer*) malloc(sizeof(Buffer) + (len + 1) * sizeof(PRUnichar));
     if (buf)
       {
+        // leave PRCList members of Buffer uninitialized
+
+        buf->mUsageCount = 0;
+        buf->mDataEnd = buf->DataStart() + len;
+
         nsAString::const_iterator source;
         aString.BeginReading(source);
         nsCharTraits<PRUnichar>::copy(buf->DataStart(), source.get(), len);
+
+        // XXX null terminate.  this shouldn't be required, but we do it because
+        // nsScanner erroneously thinks it can dereference DataEnd :-(
+        *buf->mDataEnd = PRUnichar(0);
       }
     return buf;
   }
 
 nsScannerBufferList::Buffer*
 nsScannerBufferList::AllocBuffer( uint32_t capacity )
   {
     if (capacity > MAX_CAPACITY)
       return nullptr;
 
-    void* ptr = malloc(sizeof(Buffer) + (capacity + 1) * sizeof(PRUnichar));
-    if (!ptr)
-      return nullptr;
-
-    Buffer* buf = new (ptr) Buffer();
+    Buffer* buf = (Buffer*) malloc(sizeof(Buffer) + (capacity + 1) * sizeof(PRUnichar));
+    if (buf)
+      {
+        // leave PRCList members of Buffer uninitialized
 
-    buf->mUsageCount = 0;
-    buf->mDataEnd = buf->DataStart() + capacity;
+        buf->mUsageCount = 0;
+        buf->mDataEnd = buf->DataStart() + capacity;
 
-    // XXX null terminate.  this shouldn't be required, but we do it because
-    // nsScanner erroneously thinks it can dereference DataEnd :-(
-    *buf->mDataEnd = PRUnichar(0);
+        // XXX null terminate.  this shouldn't be required, but we do it because
+        // nsScanner erroneously thinks it can dereference DataEnd :-(
+        *buf->mDataEnd = PRUnichar(0);
+      }
     return buf;
   }
 
 void
 nsScannerBufferList::ReleaseAll()
   {
-    while (!mBuffers.isEmpty())
+    while (!PR_CLIST_IS_EMPTY(&mBuffers))
       {
-        Buffer* node = mBuffers.popFirst();
+        PRCList* node = PR_LIST_HEAD(&mBuffers);
+        PR_REMOVE_LINK(node);
         //printf(">>> freeing buffer @%p\n", node);
-        free(node);
+        free(static_cast<Buffer*>(node));
       }
   }
 
 void
 nsScannerBufferList::SplitBuffer( const Position& pos )
   {
     // splitting to the right keeps the work string and any extant token
     // pointing to and holding a reference count on the same buffer.
@@ -88,20 +101,20 @@ nsScannerBufferList::SplitBuffer( const 
       }
   }
 
 void
 nsScannerBufferList::DiscardUnreferencedPrefix( Buffer* aBuf )
   {
     if (aBuf == Head())
       {
-        while (!mBuffers.isEmpty() && !Head()->IsInUse())
+        while (!PR_CLIST_IS_EMPTY(&mBuffers) && !Head()->IsInUse())
           {
             Buffer* buffer = Head();
-            buffer->remove();
+            PR_REMOVE_LINK(buffer);
             free(buffer);
           }
       }
   }
 
 size_t
 nsScannerBufferList::Position::Distance( const Position& aStart, const Position& aEnd )
   {
@@ -258,17 +271,17 @@ nsScannerSubstring::EndReading( nsScanne
 
 bool
 nsScannerSubstring::GetNextFragment( nsScannerFragment& frag ) const
   {
     // check to see if we are at the end of the buffer list
     if (frag.mBuffer == mEnd.mBuffer)
       return false;
 
-    frag.mBuffer = frag.mBuffer->getNext();
+    frag.mBuffer = static_cast<const Buffer*>(PR_NEXT_LINK(frag.mBuffer));
 
     if (frag.mBuffer == mStart.mBuffer)
       frag.mFragmentStart = mStart.mPosition;
     else
       frag.mFragmentStart = frag.mBuffer->DataStart();
 
     if (frag.mBuffer == mEnd.mBuffer)
       frag.mFragmentEnd = mEnd.mPosition;
@@ -280,17 +293,17 @@ nsScannerSubstring::GetNextFragment( nsS
 
 bool
 nsScannerSubstring::GetPrevFragment( nsScannerFragment& frag ) const
   {
     // check to see if we are at the beginning of the buffer list
     if (frag.mBuffer == mStart.mBuffer)
       return false;
 
-    frag.mBuffer = frag.mBuffer->getPrevious();
+    frag.mBuffer = static_cast<const Buffer*>(PR_PREV_LINK(frag.mBuffer));
 
     if (frag.mBuffer == mStart.mBuffer)
       frag.mFragmentStart = mStart.mPosition;
     else
       frag.mFragmentStart = frag.mBuffer->DataStart();
 
     if (frag.mBuffer == mEnd.mBuffer)
       frag.mFragmentEnd = mEnd.mPosition;
--- a/uriloader/base/nsDocLoader.cpp
+++ b/uriloader/base/nsDocLoader.cpp
@@ -57,31 +57,74 @@ void GetURIStringFromRequest(nsIRequest*
 {
     if (request)
         request->GetName(name);
     else
         name.AssignLiteral("???");
 }
 #endif /* DEBUG */
 
+struct nsStatusInfo : public PRCList
+{
+  nsString mStatusMessage;
+  nsresult mStatusCode;
+  // Weak mRequest is ok; we'll be told if it decides to go away.
+  nsIRequest * const mRequest;
+
+  nsStatusInfo(nsIRequest *aRequest) :
+    mRequest(aRequest)
+  {
+    MOZ_COUNT_CTOR(nsStatusInfo);
+    PR_INIT_CLIST(this);
+  }
+  ~nsStatusInfo()
+  {
+    MOZ_COUNT_DTOR(nsStatusInfo);
+    PR_REMOVE_LINK(this);
+  }
+};
+
+struct nsRequestInfo : public PLDHashEntryHdr
+{
+  nsRequestInfo(const void *key)
+    : mKey(key), mCurrentProgress(0), mMaxProgress(0), mUploading(false)
+    , mLastStatus(nullptr)
+  {
+    MOZ_COUNT_CTOR(nsRequestInfo);
+  }
+
+  ~nsRequestInfo()
+  {
+    MOZ_COUNT_DTOR(nsRequestInfo);
+  }
+
+  nsIRequest* Request() {
+    return static_cast<nsIRequest*>(const_cast<void*>(mKey));
+  }
+
+  const void* mKey; // Must be first for the pldhash stubs to work
+  int64_t mCurrentProgress;
+  int64_t mMaxProgress;
+  bool mUploading;
+
+  nsAutoPtr<nsStatusInfo> mLastStatus;
+};
 
 
-bool
-nsDocLoader::RequestInfoHashInitEntry(PLDHashTable* table,
-                                      PLDHashEntryHdr* entry,
-                                      const void* key)
+static bool
+RequestInfoHashInitEntry(PLDHashTable *table, PLDHashEntryHdr *entry,
+                         const void *key)
 {
   // Initialize the entry with placement new
   new (entry) nsRequestInfo(key);
   return true;
 }
 
-void
-nsDocLoader::RequestInfoHashClearEntry(PLDHashTable* table,
-                                       PLDHashEntryHdr* entry)
+static void
+RequestInfoHashClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
 {
   nsRequestInfo* info = static_cast<nsRequestInfo *>(entry);
   info->~nsRequestInfo();
 }
 
 struct nsListenerInfo {
   nsListenerInfo(nsIWeakReference *aListener, unsigned long aNotifyMask) 
     : mWeakListener(aListener),
@@ -130,16 +173,18 @@ nsDocLoader::nsDocLoader()
 
   if (!PL_DHashTableInit(&mRequestInfoHash, &hash_table_ops, nullptr,
                          sizeof(nsRequestInfo), 16)) {
     mRequestInfoHash.ops = nullptr;
   }
 
   ClearInternalProgress();
 
+  PR_INIT_CLIST(&mStatusInfoList);
+
   PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, 
          ("DocLoader:%p: created.\n", this));
 }
 
 nsresult
 nsDocLoader::SetDocLoaderParent(nsDocLoader *aParent)
 {
   mParent = aParent;
@@ -842,18 +887,19 @@ void nsDocLoader::doStopURLLoad(nsIReque
   FireOnStateChange(this,
                     request,
                     nsIWebProgressListener::STATE_STOP |
                     nsIWebProgressListener::STATE_IS_REQUEST,
                     aStatus);
 
   // Fire a status change message for the most recent unfinished
   // request to make sure that the displayed status is not outdated.
-  if (!mStatusInfoList.isEmpty()) {
-    nsStatusInfo* statusInfo = mStatusInfoList.getFirst();
+  if (!PR_CLIST_IS_EMPTY(&mStatusInfoList)) {
+    nsStatusInfo* statusInfo =
+      static_cast<nsStatusInfo*>(PR_LIST_HEAD(&mStatusInfoList));
     FireOnStatusChange(this, statusInfo->mRequest,
                        statusInfo->mStatusCode,
                        statusInfo->mStatusMessage.get());
   }
 }
 
 void nsDocLoader::doStopDocumentLoad(nsIRequest *request,
                                          nsresult aStatus)
@@ -1128,22 +1174,22 @@ NS_IMETHODIMP nsDocLoader::OnStatus(nsIR
     // don't display, for example, "Transferring" messages for requests that are
     // already done.
     if (info) {
       if (!info->mLastStatus) {
         info->mLastStatus = new nsStatusInfo(aRequest);
       } else {
         // We're going to move it to the front of the list, so remove
         // it from wherever it is now.
-        info->mLastStatus->remove();
+        PR_REMOVE_LINK(info->mLastStatus);
       }
       info->mLastStatus->mStatusMessage = msg;
       info->mLastStatus->mStatusCode = aStatus;
       // Put the info at the front of the list
-      mStatusInfoList.insertFront(info->mLastStatus);
+      PR_INSERT_LINK(info->mLastStatus, &mStatusInfoList);
     }
     FireOnStatusChange(this, aRequest, aStatus, msg);
   }
   return NS_OK;
 }
 
 void nsDocLoader::ClearInternalProgress()
 {
@@ -1484,20 +1530,20 @@ nsresult nsDocLoader::AddRequestInfo(nsI
   return NS_OK;
 }
 
 void nsDocLoader::RemoveRequestInfo(nsIRequest *aRequest)
 {
   PL_DHashTableOperate(&mRequestInfoHash, aRequest, PL_DHASH_REMOVE);
 }
 
-nsDocLoader::nsRequestInfo* nsDocLoader::GetRequestInfo(nsIRequest* aRequest)
+nsRequestInfo * nsDocLoader::GetRequestInfo(nsIRequest *aRequest)
 {
-  nsRequestInfo* info =
-    static_cast<nsRequestInfo*>
+  nsRequestInfo *info =
+    static_cast<nsRequestInfo *>
                (PL_DHashTableOperate(&mRequestInfoHash, aRequest,
                                         PL_DHASH_LOOKUP));
 
   if (PL_DHASH_ENTRY_IS_FREE(info)) {
     // Nothing found in the hash, return null.
 
     return nullptr;
   }
@@ -1523,22 +1569,22 @@ void nsDocLoader::ClearRequestInfoHash(v
 
     return;
   }
 
   PL_DHashTableEnumerate(&mRequestInfoHash, RemoveInfoCallback, nullptr);
 }
 
 // PLDHashTable enumeration callback that calculates the max progress.
-PLDHashOperator
-nsDocLoader::CalcMaxProgressCallback(PLDHashTable* table, PLDHashEntryHdr* hdr,
-                                     uint32_t number, void* arg)
+static PLDHashOperator
+CalcMaxProgressCallback(PLDHashTable *table, PLDHashEntryHdr *hdr,
+                        uint32_t number, void *arg)
 {
-  const nsRequestInfo* info = static_cast<const nsRequestInfo*>(hdr);
-  int64_t* max = static_cast<int64_t* >(arg);
+  const nsRequestInfo *info = static_cast<const nsRequestInfo *>(hdr);
+  int64_t *max = static_cast<int64_t *>(arg);
 
   if (info->mMaxProgress < info->mCurrentProgress) {
     *max = int64_t(-1);
 
     return PL_DHASH_STOP;
   }
 
   *max += info->mMaxProgress;
--- a/uriloader/base/nsDocLoader.h
+++ b/uriloader/base/nsDocLoader.h
@@ -22,20 +22,20 @@
 #include "nsIProgressEventSink.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIChannelEventSink.h"
 #include "nsISecurityEventSink.h"
 #include "nsISupportsPriority.h"
 #include "nsCOMPtr.h"
 #include "pldhash.h"
+#include "prclist.h"
 #include "nsAutoPtr.h"
 
-#include "mozilla/LinkedList.h"
-
+struct nsRequestInfo;
 struct nsListenerInfo;
 
 /****************************************************************************
  * nsDocLoader implementation...
  ****************************************************************************/
 
 #define NS_THIS_DOCLOADER_IMPL_CID                    \
  { /* b4ec8387-98aa-4c08-93b6-6d23069c06f2 */         \
@@ -189,64 +189,16 @@ protected:
     // Inform a parent docloader that aChild is done calling its onload
     // handler.
     void ChildDoneWithOnload(nsIDocumentLoader* aChild) {
         mChildrenInOnload.RemoveObject(aChild);
         DocLoaderIsEmpty(true);
     }        
 
 protected:
-    struct nsStatusInfo : public mozilla::LinkedListElement<nsStatusInfo>
-    {
-        nsString mStatusMessage;
-        nsresult mStatusCode;
-        // Weak mRequest is ok; we'll be told if it decides to go away.
-        nsIRequest * const mRequest;
-
-        nsStatusInfo(nsIRequest* aRequest) :
-            mRequest(aRequest)
-        {
-            MOZ_COUNT_CTOR(nsStatusInfo);
-        }
-        ~nsStatusInfo()
-        {
-            MOZ_COUNT_DTOR(nsStatusInfo);
-        }
-    };
-
-    struct nsRequestInfo : public PLDHashEntryHdr
-    {
-        nsRequestInfo(const void* key)
-            : mKey(key), mCurrentProgress(0), mMaxProgress(0), mUploading(false)
-            , mLastStatus(nullptr)
-        {
-            MOZ_COUNT_CTOR(nsRequestInfo);
-        }
-
-        ~nsRequestInfo()
-        {
-            MOZ_COUNT_DTOR(nsRequestInfo);
-        }
-
-        nsIRequest* Request() {
-            return static_cast<nsIRequest*>(const_cast<void*>(mKey));
-        }
-
-        const void* mKey; // Must be first for the pldhash stubs to work
-        int64_t mCurrentProgress;
-        int64_t mMaxProgress;
-        bool mUploading;
-
-        nsAutoPtr<nsStatusInfo> mLastStatus;
-    };
-
-    static bool RequestInfoHashInitEntry(PLDHashTable* table, PLDHashEntryHdr* entry,
-                                         const void* key);
-    static void RequestInfoHashClearEntry(PLDHashTable* table, PLDHashEntryHdr* entry);
-
     // IMPORTANT: The ownership implicit in the following member
     // variables has been explicitly checked and set using nsCOMPtr
     // for owning pointers and raw COM interface pointers for weak
     // (ie, non owning) references. If you add any members to this
     // class, please make the ownership explicit (pinkerton, scc).
   
     nsCOMPtr<nsIRequest>       mDocumentRequest;       // [OWNER] ???compare with document
 
@@ -266,17 +218,17 @@ protected:
     int64_t mMaxSelfProgress;
 
     int64_t mCurrentTotalProgress;
     int64_t mMaxTotalProgress;
 
     PLDHashTable mRequestInfoHash;
     int64_t mCompletedTotalProgress;
 
-    mozilla::LinkedList<nsStatusInfo> mStatusInfoList;
+    PRCList mStatusInfoList;
 
     /*
      * This flag indicates that the loader is loading a document.  It is set
      * from the call to LoadDocument(...) until the OnConnectionsComplete(...)
      * notification is fired...
      */
     bool mIsLoadingDocument;
 
@@ -311,19 +263,16 @@ private:
 
     int64_t GetMaxTotalProgress();
 
     nsresult AddRequestInfo(nsIRequest* aRequest);
     void RemoveRequestInfo(nsIRequest* aRequest);
     nsRequestInfo *GetRequestInfo(nsIRequest* aRequest);
     void ClearRequestInfoHash();
     int64_t CalculateMaxProgress();
-    static PLDHashOperator CalcMaxProgressCallback(PLDHashTable* table,
-                                                   PLDHashEntryHdr* hdr,
-                                                   uint32_t number, void* arg);
 ///    void DumpChannelInfo(void);
 
     // used to clear our internal progress state between loads...
     void ClearInternalProgress(); 
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsDocLoader, NS_THIS_DOCLOADER_IMPL_CID)