diff --git a/mozilla/browser/app/profile/firefox.js b/mozilla/browser/app/profile/firefox.js index bb7b5740217..d8f6b828800 100644 --- a/mozilla/browser/app/profile/firefox.js +++ b/mozilla/browser/app/profile/firefox.js @@ -214,6 +214,7 @@ pref("browser.search.update", true); pref("browser.history.grouping", "day"); pref("browser.sessionhistory.max_entries", 50); +pref("browser.sessionhistory.max_viewers", 3); // handle external links // 0=default window, 1=current window/tab, 2=new window, 3=new tab in most recent window diff --git a/mozilla/camino/resources/application/all-camino.js b/mozilla/camino/resources/application/all-camino.js index 87848427253..5be9a9918f3 100644 --- a/mozilla/camino/resources/application/all-camino.js +++ b/mozilla/camino/resources/application/all-camino.js @@ -127,3 +127,6 @@ pref("browser.tabs.loadInBackground", false); // use the html network errors rather than sheets pref("browser.xul.error_pages.enabled", true); + +// turn on bfcache optimizations +pref("browser.sessionhistory.max_viewers", 3); diff --git a/mozilla/docshell/base/nsDocShell.cpp b/mozilla/docshell/base/nsDocShell.cpp index 7693d345a58..59efb574398 100644 --- a/mozilla/docshell/base/nsDocShell.cpp +++ b/mozilla/docshell/base/nsDocShell.cpp @@ -259,8 +259,6 @@ nsDocShell::nsDocShell(): mMarginHeight(0), mItemType(typeContent), mDefaultScrollbarPref(Scrollbar_Auto, Scrollbar_Auto), - mPreviousTransIndex(-1), - mLoadedTransIndex(-1), mEditorData(nsnull), mTreeOwner(nsnull), mChromeEventHandler(nsnull) @@ -1709,20 +1707,6 @@ nsDocShell::SetUseErrorPages(PRBool aUseErrorPages) return NS_OK; } -NS_IMETHODIMP -nsDocShell::GetPreviousTransIndex(PRInt32 *aPreviousTransIndex) -{ - *aPreviousTransIndex = mPreviousTransIndex; - return NS_OK; -} - -NS_IMETHODIMP -nsDocShell::GetLoadedTransIndex(PRInt32 *aLoadedTransIndex) -{ - *aLoadedTransIndex = mLoadedTransIndex; - return NS_OK; -} - //***************************************************************************** // nsDocShell::nsIDocShellTreeItem //***************************************************************************** @@ -2650,19 +2634,6 @@ nsDocShell::DoAddChildSHEntry(nsISHEntry* aNewEntry, PRInt32 aChildOffset) * for this subframe in the CloneAndReplace function. */ - // In this case, we will end up calling AddEntry, which increases the - // current index by 1 - nsCOMPtr rootSH; - GetRootSessionHistory(getter_AddRefs(rootSH)); - if (rootSH) { - rootSH->GetIndex(&mPreviousTransIndex); - mLoadedTransIndex = mPreviousTransIndex + 1; -#ifdef DEBUG_PAGE_CACHE - printf("Previous index: %d, Loaded index: %d\n\n", mPreviousTransIndex, - mLoadedTransIndex); -#endif - } - nsresult rv; nsCOMPtr parent = do_QueryInterface(GetAsSupports(mParent), &rv); @@ -4883,15 +4854,10 @@ nsDocShell::CanSavePresentation(PRUint32 aLoadType, // Avoid doing the work of saving the presentation state in the case where // the content viewer cache is disabled. - nsCOMPtr rootSH; - GetRootSessionHistory(getter_AddRefs(rootSH)); - if (rootSH) { - nsCOMPtr shistInt(do_QueryInterface(rootSH)); - PRInt32 maxViewers; - shistInt->GetHistoryMaxTotalViewers(&maxViewers); - if (maxViewers == 0) + PRInt32 maxViewers = 0; + mPrefs->GetIntPref("browser.sessionhistory.max_viewers", &maxViewers); + if (maxViewers == 0) return PR_FALSE; - } // Don't cache the content viewer if we're in a subframe and the subframe // pref is disabled. @@ -5244,13 +5210,7 @@ nsDocShell::RestoreFromHistory() GetRootSessionHistory(getter_AddRefs(rootSH)); if (rootSH) { nsCOMPtr hist = do_QueryInterface(rootSH); - rootSH->GetIndex(&mPreviousTransIndex); hist->UpdateIndex(); - rootSH->GetIndex(&mLoadedTransIndex); -#ifdef DEBUG_PAGE_CACHE - printf("Previous index: %d, Loaded index: %d\n\n", mPreviousTransIndex, - mLoadedTransIndex); -#endif } // Rather than call Embed(), we will retrieve the viewer from the session @@ -5318,7 +5278,7 @@ nsDocShell::RestoreFromHistory() if (mContentViewer) { mContentViewer->Close(mSavingOldViewer ? mOSHE.get() : nsnull); - viewer->SetPreviousViewer(mContentViewer); + mContentViewer->Destroy(); } mContentViewer.swap(viewer); @@ -7253,15 +7213,8 @@ nsDocShell::OnNewURI(nsIURI * aURI, nsIChannel * aChannel, // SH. if (rootSH && (mLoadType & LOAD_CMD_HISTORY)) { nsCOMPtr shInternal(do_QueryInterface(rootSH)); - if (shInternal) { - rootSH->GetIndex(&mPreviousTransIndex); + if (shInternal) shInternal->UpdateIndex(); - rootSH->GetIndex(&mLoadedTransIndex); -#ifdef DEBUG_PAGE_CACHE - printf("Previous index: %d, Loaded index: %d\n\n", - mPreviousTransIndex, mLoadedTransIndex); -#endif - } } PRBool onLocationChangeNeeded = SetCurrentURI(aURI, aChannel, aFireOnLocationChange); @@ -7471,13 +7424,7 @@ nsDocShell::AddToSessionHistory(nsIURI * aURI, nsCOMPtr shPrivate(do_QueryInterface(mSessionHistory)); NS_ENSURE_TRUE(shPrivate, NS_ERROR_FAILURE); - mSessionHistory->GetIndex(&mPreviousTransIndex); rv = shPrivate->AddEntry(entry, shouldPersist); - mSessionHistory->GetIndex(&mLoadedTransIndex); -#ifdef DEBUG_PAGE_CACHE - printf("Previous index: %d, Loaded index: %d\n\n", - mPreviousTransIndex, mLoadedTransIndex); -#endif } } else { diff --git a/mozilla/docshell/base/nsDocShell.h b/mozilla/docshell/base/nsDocShell.h index 6831eaa7e0b..b2882321ad1 100644 --- a/mozilla/docshell/base/nsDocShell.h +++ b/mozilla/docshell/base/nsDocShell.h @@ -590,11 +590,6 @@ protected: // Somebody give me better name nsCOMPtr mLSHE; - // Index into the SHTransaction list, indicating the previous and current - // transaction at the time that this DocShell begins to load - PRInt32 mPreviousTransIndex; - PRInt32 mLoadedTransIndex; - // Editor stuff nsDocShellEditorData* mEditorData; // editor data, if any diff --git a/mozilla/docshell/base/nsIDocShell.idl b/mozilla/docshell/base/nsIDocShell.idl index c2313b0fa48..f172f89f481 100644 --- a/mozilla/docshell/base/nsIDocShell.idl +++ b/mozilla/docshell/base/nsIDocShell.idl @@ -66,7 +66,7 @@ interface nsISHEntry; interface nsILayoutHistoryState; interface nsISecureBrowserUI; -[scriptable, uuid(9f0c7461-b9a4-47f6-b88c-421dce1bce66)] +[scriptable, uuid(cfe93f8d-bd92-4e77-a9b7-c37296fe0986)] interface nsIDocShell : nsISupports { /** @@ -387,11 +387,5 @@ interface nsIDocShell : nsISupports /* attribute to access whether error pages are enabled */ attribute boolean useErrorPages; - - /* keeps track of the previous SHTransaction index and the current - SHTransaction index at the time that the doc shell begins to load. - Used for ContentViewer eviction */ - readonly attribute long previousTransIndex; - readonly attribute long loadedTransIndex; }; diff --git a/mozilla/docshell/base/nsWebShell.cpp b/mozilla/docshell/base/nsWebShell.cpp index 4332b6d4b1d..79ce7311935 100644 --- a/mozilla/docshell/base/nsWebShell.cpp +++ b/mozilla/docshell/base/nsWebShell.cpp @@ -898,15 +898,8 @@ nsresult nsWebShell::EndPageLoad(nsIWebProgress *aProgress, if (rootSH && (mLoadType & LOAD_CMD_HISTORY)) { nsCOMPtr shInternal(do_QueryInterface(rootSH)); - if (shInternal) { - rootSH->GetIndex(&mPreviousTransIndex); - shInternal->UpdateIndex(); - rootSH->GetIndex(&mLoadedTransIndex); -#ifdef DEBUG_PAGE_CACHE - printf("Previous index: %d, Loaded index: %d\n\n", - mPreviousTransIndex, mLoadedTransIndex); -#endif - } + if (shInternal) + shInternal->UpdateIndex(); } // Make it look like we really did honestly finish loading the diff --git a/mozilla/docshell/build/nsDocShellModule.cpp b/mozilla/docshell/build/nsDocShellModule.cpp index 0a3dceae9e1..b5ef6dc5c3f 100644 --- a/mozilla/docshell/build/nsDocShellModule.cpp +++ b/mozilla/docshell/build/nsDocShellModule.cpp @@ -62,29 +62,6 @@ #include "nsGlobalHistoryAdapter.h" #include "nsGlobalHistory2Adapter.h" -static PRBool gInitialized = PR_FALSE; - -// The one time initialization for this module -// static -PR_STATIC_CALLBACK(nsresult) -Initialize(nsIModule* aSelf) -{ - NS_PRECONDITION(!gInitialized, "docshell module already initialized"); - if (gInitialized) { - return NS_OK; - } - gInitialized = PR_TRUE; - - nsresult rv = nsSHistory::Startup(); - return rv; -} - -PR_STATIC_CALLBACK(void) -Shutdown(nsIModule* aSelf) -{ - gInitialized = PR_FALSE; -} - // docshell NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsWebShell, Init) NS_GENERIC_FACTORY_CONSTRUCTOR(nsDefaultURIFixup) @@ -106,7 +83,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsInternetConfigService) // session history NS_GENERIC_FACTORY_CONSTRUCTOR(nsSHEntry) NS_GENERIC_FACTORY_CONSTRUCTOR(nsSHTransaction) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsSHistory) +NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsSHistory, Init) // Currently no-one is instantiating docshell's directly because // nsWebShell is still our main "shell" class. nsWebShell is a subclass @@ -177,5 +154,5 @@ static const nsModuleComponentInfo gDocShellModuleInfo[] = { // "docshell provider" to illustrate that this thing really *should* // be dispensing docshells rather than webshells. -NS_IMPL_NSGETMODULE_WITH_CTOR_DTOR(docshell_provider, gDocShellModuleInfo, - Initialize, Shutdown) +NS_IMPL_NSGETMODULE(docshell_provider, gDocShellModuleInfo) + diff --git a/mozilla/docshell/shistory/public/nsISHEntry.idl b/mozilla/docshell/shistory/public/nsISHEntry.idl index 05c8a388cea..17af9654397 100644 --- a/mozilla/docshell/shistory/public/nsISHEntry.idl +++ b/mozilla/docshell/shistory/public/nsISHEntry.idl @@ -55,7 +55,7 @@ struct nsRect; %} [ref] native nsRect(nsRect); -[scriptable, uuid(542a98b9-2889-4922-aaf4-02b6056f4136)] +[scriptable, uuid(a19c4489-4a71-42e1-b150-61366547030d)] interface nsISHEntry : nsIHistoryEntry { /** URI for the document */ @@ -177,11 +177,6 @@ interface nsISHEntry : nsIHistoryEntry /** Attribute that indicates if this entry is for a subframe navigation */ void setIsSubFrame(in boolean aFlag); - - /** Return any content viewer present in or below this node in the - nsSHEntry tree. This will differ from contentViewer in the case - where a child nsSHEntry has the content viewer for this tree. */ - nsIContentViewer getAnyContentViewer(out nsISHEntry ownerEntry); }; diff --git a/mozilla/docshell/shistory/public/nsISHistoryInternal.idl b/mozilla/docshell/shistory/public/nsISHistoryInternal.idl index 1c46b1d910d..d4f5272611e 100644 --- a/mozilla/docshell/shistory/public/nsISHistoryInternal.idl +++ b/mozilla/docshell/shistory/public/nsISHistoryInternal.idl @@ -51,7 +51,7 @@ interface nsIDocShell; #define NS_SHISTORY_INTERNAL_CONTRACTID "@mozilla.org/browser/shistory-internal;1" %} -[scriptable, uuid(494fac3c-64f4-41b8-b209-b4ada899613b)] +[scriptable, uuid(DD335421-B8B8-11d3-BDC8-0050040A9B44)] interface nsISHistoryInternal: nsISupports { /** @@ -91,19 +91,10 @@ interface nsISHistoryInternal: nsISupports readonly attribute nsISHistoryListener listener; /** - * Evict content viewers until the number of content viewers per tab - * is no more than gHistoryMaxViewers. Also, count - * total number of content viewers globally and evict one if we are over - * our total max. This is always called in Show(), after we destroy - * the previous viewer. + * Evict content viewers until the number of content viewers is no more than + * browser.sessionhistory.max_viewers. This is done automatically by + * updateIndex(), but should be called explicitly if a new history entry + * is added and later has a content viewer set. */ - void evictContentViewers(in long previousIndex, in long index); - - /** - * Max number of total cached content viewers. If the pref - * browser.sessionhistory.max_total_viewers is negative, then - * this value is calculated based on the total amount of memory. - * Otherwise, it comes straight from the pref. - */ - readonly attribute long historyMaxTotalViewers; + void evictContentViewers(); }; diff --git a/mozilla/docshell/shistory/src/nsSHEntry.cpp b/mozilla/docshell/shistory/src/nsSHEntry.cpp index 74122e47792..361ca62a568 100644 --- a/mozilla/docshell/shistory/src/nsSHEntry.cpp +++ b/mozilla/docshell/shistory/src/nsSHEntry.cpp @@ -199,38 +199,6 @@ nsSHEntry::GetContentViewer(nsIContentViewer **aResult) return NS_OK; } -NS_IMETHODIMP -nsSHEntry::GetAnyContentViewer(nsISHEntry **aOwnerEntry, - nsIContentViewer **aResult) -{ - // Find a content viewer in the root node or any of its children, - // assuming that there is only one content viewer total in any one - // nsSHEntry tree - GetContentViewer(aResult); - if (*aResult) { -#ifdef DEBUG_PAGE_CACHE - printf("Found content viewer\n"); -#endif - *aOwnerEntry = this; - NS_ADDREF(*aOwnerEntry); - return NS_OK; - } - // The root SHEntry doesn't have a ContentViewer, so check child nodes - for (PRInt32 i = 0; i < mChildren.Count(); i++) { - nsISHEntry* child = mChildren[i]; - if (child) { -#ifdef DEBUG_PAGE_CACHE - printf("Evaluating SHEntry child %d\n", i); -#endif - child->GetAnyContentViewer(aOwnerEntry, aResult); - if (*aResult) { - return NS_OK; - } - } - } - return NS_OK; -} - NS_IMETHODIMP nsSHEntry::SetSticky(PRBool aSticky) { diff --git a/mozilla/docshell/shistory/src/nsSHistory.cpp b/mozilla/docshell/shistory/src/nsSHistory.cpp index 47679cb1cf6..da2cebb2cfc 100644 --- a/mozilla/docshell/shistory/src/nsSHistory.cpp +++ b/mozilla/docshell/shistory/src/nsSHistory.cpp @@ -56,24 +56,12 @@ #include "nsIPrefService.h" #include "nsIURI.h" #include "nsIContentViewer.h" -#include "nsIPrefBranch2.h" -#include "prclist.h" - -// For calculating max history entries and max cachable contentviewers -#include "nspr.h" -#include // for log() #define PREF_SHISTORY_SIZE "browser.sessionhistory.max_entries" -#define PREF_SHISTORY_MAX_TOTAL_VIEWERS "browser.sessionhistory.max_total_viewers" +#define PREF_SHISTORY_VIEWERS "browser.sessionhistory.max_viewers" static PRInt32 gHistoryMaxSize = 50; -// Max viewers allowed per SHistory objects -static const PRInt32 gHistoryMaxViewers = 3; -// List of all SHistory objects, used for content viewer cache eviction -static PRCList gSHistoryList; -// Max viewers allowed total, across all SHistory objects - negative default -// means we will calculate how many viewers to cache based on total memory -PRInt32 nsSHistory::sHistoryMaxTotalViewers = -1; +static PRInt32 gHistoryMaxViewers = 0; enum HistCmd{ HIST_CMD_BACK, @@ -82,58 +70,17 @@ enum HistCmd{ HIST_CMD_RELOAD } ; -//***************************************************************************** -//*** nsSHistoryPrefObserver -//***************************************************************************** - -class nsSHistoryPrefObserver : public nsIObserver -{ - -public: - NS_DECL_ISUPPORTS - NS_DECL_NSIOBSERVER - - nsSHistoryPrefObserver() {} - -protected: - ~nsSHistoryPrefObserver() {} -}; - -NS_IMPL_ISUPPORTS1(nsSHistoryPrefObserver, nsIObserver) - -NS_IMETHODIMP -nsSHistoryPrefObserver::Observe(nsISupports *aSubject, const char *aTopic, - const PRUnichar *aData) -{ - if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) { - nsCOMPtr prefs = do_QueryInterface(aSubject); - prefs->GetIntPref(PREF_SHISTORY_MAX_TOTAL_VIEWERS, - &nsSHistory::sHistoryMaxTotalViewers); - if (nsSHistory::sHistoryMaxTotalViewers < 0) { - nsSHistory::sHistoryMaxTotalViewers = nsSHistory::GetMaxTotalViewers(); - } - - nsSHistory::EvictGlobalContentViewer(); - } - - return NS_OK; -} - //***************************************************************************** //*** nsSHistory: Object Management //***************************************************************************** nsSHistory::nsSHistory() : mListRoot(nsnull), mIndex(-1), mLength(0), mRequestedIndex(-1) { - // Add this new SHistory object to the list - PR_APPEND_LINK(this, &gSHistoryList); } nsSHistory::~nsSHistory() { - // Remove this SHistory object from the list - PR_REMOVE_LINK(this); } //***************************************************************************** @@ -154,71 +101,11 @@ NS_INTERFACE_MAP_END // nsSHistory: nsISHistory //***************************************************************************** +/* + * Init method to get pref settings + */ NS_IMETHODIMP -nsSHistory::GetHistoryMaxTotalViewers(PRInt32 *max) -{ - *max = sHistoryMaxTotalViewers; - return NS_OK; -} - -// static -PRUint32 -nsSHistory::GetMaxTotalViewers() -{ - // Calculate an estimate of how many ContentViewers we should cache based - // on RAM. This assumes that the average ContentViewer is 4MB (conservative) - // and caps the max at 8 ContentViewers - // - // TODO: Should we split the cache memory betw. ContentViewer caching and - // nsCacheService? - // - // RAM ContentViewers - // ----------------------- - // 32 Mb 0 - // 64 Mb 1 - // 128 Mb 2 - // 256 Mb 3 - // 512 Mb 5 - // 1024 Mb 8 - // 2048 Mb 8 - // 4096 Mb 8 - PRUint64 bytes = PR_GetPhysicalMemorySize(); - - if (LL_IS_ZERO(bytes)) - return 0; - - // Conversion from unsigned int64 to double doesn't work on all platforms. - // We need to truncate the value at LL_MAXINT to make sure we don't - // overflow. - if (LL_CMP(bytes, >, LL_MAXINT)) - bytes = LL_MAXINT; - - PRUint64 kbytes; - LL_SHR(kbytes, bytes, 10); - - double kBytesD; - LL_L2D(kBytesD, (PRInt64) kbytes); - - // This is essentially the same calculation as for nsCacheService, - // except that we divide the final memory calculation by 4, since - // we assume each ContentViewer takes on average 4MB - PRUint32 viewers = 0; - double x = log(kBytesD)/log(2.0) - 14; - if (x > 0) { - viewers = (PRUint32)(x * x - x + 2.001); // add .001 for rounding - viewers /= 4; - } - - // Cap it off at 8 max - if (viewers > 8) { - viewers = 8; - } - return viewers; -} - -// static -nsresult -nsSHistory::Startup() +nsSHistory::Init() { nsCOMPtr prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); if (prefs) { @@ -231,31 +118,17 @@ nsSHistory::Startup() if (defaultBranch) { defaultBranch->GetIntPref(PREF_SHISTORY_SIZE, &gHistoryMaxSize); } - - // Allow the user to override the max total number of cached viewers, - // but keep the per SHistory cached viewer limit constant - nsCOMPtr branch = do_QueryInterface(prefs); - if (branch) { - branch->GetIntPref(PREF_SHISTORY_MAX_TOTAL_VIEWERS, - &sHistoryMaxTotalViewers); - nsSHistoryPrefObserver* obs = new nsSHistoryPrefObserver(); - if (!obs) { - return NS_ERROR_OUT_OF_MEMORY; - } - branch->AddObserver(PREF_SHISTORY_MAX_TOTAL_VIEWERS, - obs, PR_FALSE); - } - } - // If the pref is negative, that means we calculate how many viewers - // we think we should cache, based on total memory - if (sHistoryMaxTotalViewers < 0) { - sHistoryMaxTotalViewers = GetMaxTotalViewers(); - } - // Initialize the global list of all SHistory objects - PR_INIT_CLIST(&gSHistoryList); + // The size of the content viewer cache does not suffer from this problem, + // so we allow it to be overridden by user prefs. + nsCOMPtr branch = do_QueryInterface(prefs); + if (branch) + branch->GetIntPref(PREF_SHISTORY_VIEWERS, &gHistoryMaxViewers); + } + return NS_OK; } + /* Add an entry to the History list at mIndex and * increment the index to point to the new entry */ @@ -349,6 +222,7 @@ nsSHistory::GetEntryAtIndex(PRInt32 aIndex, PRBool aModifyIndex, nsISHEntry** aR if (NS_SUCCEEDED(rv) && (*aResult)) { // Set mIndex to the requested index, if asked to do so.. if (aModifyIndex) { + EvictContentViewers(mIndex, aIndex); mIndex = aIndex; } } //entry @@ -619,12 +493,10 @@ nsSHistory::GetListener(nsISHistoryListener ** aListener) } NS_IMETHODIMP -nsSHistory::EvictContentViewers(PRInt32 aPreviousIndex, PRInt32 aIndex) +nsSHistory::EvictContentViewers() { - // Check our per SHistory object limit in the currently navigated SHistory - EvictWindowContentViewers(aPreviousIndex, aIndex); - // Check our total limit across all SHistory objects - EvictGlobalContentViewer(); + // This is called after a new entry has been appended to the end of the list. + EvictContentViewers(mIndex - 1, mIndex); return NS_OK; } @@ -736,60 +608,43 @@ nsSHistory::Reload(PRUint32 aReloadFlags) } void -nsSHistory::EvictWindowContentViewers(PRInt32 aFromIndex, PRInt32 aToIndex) +nsSHistory::EvictContentViewers(PRInt32 aFromIndex, PRInt32 aToIndex) { - // To enforce the per SHistory object limit on cached content viewers, we - // need to release all of the content viewers that are no longer in the - // "window" that now ends/begins at aToIndex. + // To enforce the limit on cached content viewers, we need to release all + // of the content viewers that are no longer in the "window" that now + // ends/begins at aToIndex. - // This can happen on the first load of a page in a particular window - if (aFromIndex < 0 || aToIndex < 0) { - return; - } - - // These indices give the range of SHEntries whose content viewers will be - // evicted PRInt32 startIndex, endIndex; if (aToIndex > aFromIndex) { // going forward - endIndex = aToIndex - gHistoryMaxViewers; - if (endIndex <= 0) { - return; - } startIndex = PR_MAX(0, aFromIndex - gHistoryMaxViewers); + endIndex = PR_MAX(0, aToIndex - gHistoryMaxViewers); } else { // going backward - startIndex = aToIndex + gHistoryMaxViewers + 1; - if (startIndex >= mLength) { - return; - } - endIndex = PR_MIN(mLength, aFromIndex + gHistoryMaxViewers); + startIndex = PR_MIN(mLength - 1, aToIndex + gHistoryMaxViewers); + endIndex = PR_MIN(mLength - 1, aFromIndex + gHistoryMaxViewers); } nsCOMPtr trans; GetTransactionAtIndex(startIndex, getter_AddRefs(trans)); - for (PRInt32 i = startIndex; i < endIndex; ++i) { + for (PRInt32 i = startIndex; trans && i < endIndex; ++i) { nsCOMPtr entry; trans->GetSHEntry(getter_AddRefs(entry)); nsCOMPtr viewer; - nsCOMPtr ownerEntry; - entry->GetAnyContentViewer(getter_AddRefs(ownerEntry), - getter_AddRefs(viewer)); + entry->GetContentViewer(getter_AddRefs(viewer)); if (viewer) { - NS_ASSERTION(ownerEntry, - "ContentViewer exists but its SHEntry is null"); #ifdef DEBUG_PAGE_CACHE nsCOMPtr uri; - ownerEntry->GetURI(getter_AddRefs(uri)); + entry->GetURI(getter_AddRefs(uri)); nsCAutoString spec; if (uri) uri->GetSpec(spec); - printf("per SHistory limit: evicting content viewer: %s\n", spec.get()); + printf("Evicting content viewer: %s\n", spec.get()); #endif viewer->Destroy(); - ownerEntry->SetContentViewer(nsnull); - ownerEntry->SyncPresentationState(); + entry->SetContentViewer(nsnull); + entry->SyncPresentationState(); } nsISHTransaction *temp = trans; @@ -797,125 +652,15 @@ nsSHistory::EvictWindowContentViewers(PRInt32 aFromIndex, PRInt32 aToIndex) } } -// static -void -nsSHistory::EvictGlobalContentViewer() -{ - // true until the total number of content viewers is <= total max - // The usual case is that we only need to evict one content viewer. - // However, if somebody resets the pref value, we might occasionally - // need to evict more than one. - PRBool shouldTryEviction = PR_TRUE; - while (shouldTryEviction) { - // Walk through our list of SHistory objects, looking for content - // viewers in the possible active window of all of the SHEntry objects. - // Keep track of the SHEntry object that has a ContentViewer and is - // farthest from the current focus in any SHistory object. The - // ContentViewer associated with that SHEntry will be evicted - PRInt32 distanceFromFocus = 0; - nsCOMPtr evictFromSHE; - nsCOMPtr evictViewer; - PRInt32 totalContentViewers = 0; - nsSHistory* shist = NS_STATIC_CAST(nsSHistory*, - PR_LIST_HEAD(&gSHistoryList)); - while (shist != &gSHistoryList) { - // Calculate the window of SHEntries that could possibly have a content - // viewer. There could be up to gHistoryMaxViewers content viewers, - // but we don't know whether they are before or after the mIndex position - // in the SHEntry list. Just check both sides, to be safe. - PRInt32 startIndex = PR_MAX(0, shist->mIndex - gHistoryMaxViewers); - PRInt32 endIndex = PR_MIN(shist->mLength - 1, - shist->mIndex + gHistoryMaxViewers); - nsCOMPtr trans; - shist->GetTransactionAtIndex(startIndex, getter_AddRefs(trans)); - - for (PRInt32 i = startIndex; i <= endIndex; ++i) { - nsCOMPtr entry; - trans->GetSHEntry(getter_AddRefs(entry)); - nsCOMPtr viewer; - nsCOMPtr ownerEntry; - entry->GetAnyContentViewer(getter_AddRefs(ownerEntry), - getter_AddRefs(viewer)); - -#ifdef DEBUG_PAGE_CACHE - nsCOMPtr uri; - if (ownerEntry) { - ownerEntry->GetURI(getter_AddRefs(uri)); - } else { - entry->GetURI(getter_AddRefs(uri)); - } - nsCAutoString spec; - if (uri) { - uri->GetSpec(spec); - printf("Considering for eviction: %s\n", spec.get()); - } -#endif - - // This SHEntry has a ContentViewer, so check how far away it is from - // the currently used SHEntry within this SHistory object - if (viewer) { - PRInt32 distance = PR_ABS(shist->mIndex - i); - -#ifdef DEBUG_PAGE_CACHE - printf("Has a cached content viewer: %s\n", spec.get()); - printf("mIndex: %d i: %d\n", shist->mIndex, i); -#endif - totalContentViewers++; - if (distance > distanceFromFocus) { - -#ifdef DEBUG_PAGE_CACHE - printf("Choosing as new eviction candidate: %s\n", spec.get()); -#endif - - distanceFromFocus = distance; - evictFromSHE = ownerEntry; - evictViewer = viewer; - } - } - nsISHTransaction* temp = trans; - temp->GetNext(getter_AddRefs(trans)); - } - shist = NS_STATIC_CAST(nsSHistory*, PR_NEXT_LINK(shist)); - } - -#ifdef DEBUG_PAGE_CACHE - printf("Distance from focus: %d\n", distanceFromFocus); - printf("Total max viewers: %d\n", sHistoryMaxTotalViewers); - printf("Total number of viewers: %d\n", totalContentViewers); -#endif - - if (totalContentViewers > sHistoryMaxTotalViewers && evictViewer) { -#ifdef DEBUG_PAGE_CACHE - nsCOMPtr uri; - evictFromSHE->GetURI(getter_AddRefs(uri)); - nsCAutoString spec; - if (uri) { - uri->GetSpec(spec); - printf("Evicting content viewer: %s\n", spec.get()); - } -#endif - - evictViewer->Destroy(); - evictFromSHE->SetContentViewer(nsnull); - evictFromSHE->SyncPresentationState(); - - // If we only needed to evict one content viewer, then we are done. - // Otherwise, continue evicting until we reach the max total limit. - if (totalContentViewers - sHistoryMaxTotalViewers == 1) { - shouldTryEviction = PR_FALSE; - } - } else { - // couldn't find a content viewer to evict, so we are done - shouldTryEviction = PR_FALSE; - } - } // while shouldTryEviction -} - NS_IMETHODIMP nsSHistory::UpdateIndex() { // Update the actual index with the right value. if (mIndex != mRequestedIndex && mRequestedIndex != -1) { + // We've just finished a history navigation (back or forward), so enforce + // the max number of content viewers. + + EvictContentViewers(mIndex, mRequestedIndex); mIndex = mRequestedIndex; } diff --git a/mozilla/docshell/shistory/src/nsSHistory.h b/mozilla/docshell/shistory/src/nsSHistory.h index cb14ebddc84..2d21404a978 100644 --- a/mozilla/docshell/shistory/src/nsSHistory.h +++ b/mozilla/docshell/shistory/src/nsSHistory.h @@ -52,16 +52,10 @@ #include "nsISimpleEnumerator.h" #include "nsISHistoryListener.h" #include "nsIHistoryEntry.h" -#include "nsIObserver.h" - -// Needed to maintain global list of all SHistory objects -#include "prclist.h" class nsIDocShell; class nsSHEnumerator; -class nsSHistoryPrefObserver; -class nsSHistory: public PRCList, - public nsISHistory, +class nsSHistory: public nsISHistory, public nsISHistoryInternal, public nsIWebNavigation { @@ -73,17 +67,11 @@ public: NS_DECL_NSISHISTORYINTERNAL NS_DECL_NSIWEBNAVIGATION - // One time initialization method called upon docshell module construction - static nsresult Startup(); - - // Calculates a max number of total - // content viewers to cache, based on amount of total memory - static PRUint32 GetMaxTotalViewers(); + NS_IMETHOD Init(); protected: virtual ~nsSHistory(); friend class nsSHEnumerator; - friend class nsSHistoryPrefObserver; // Could become part of nsIWebNavigation NS_IMETHOD GetEntryAtIndex(PRInt32 aIndex, PRBool aModifyIndex, nsISHEntry** aResult); @@ -97,8 +85,7 @@ protected: nsresult PrintHistory(); #endif - void EvictWindowContentViewers(PRInt32 aFromIndex, PRInt32 aToIndex); - static void EvictGlobalContentViewer(); + void EvictContentViewers(PRInt32 aFromIndex, PRInt32 aToIndex); protected: nsCOMPtr mListRoot; @@ -109,9 +96,6 @@ protected: nsWeakPtr mListener; // Weak reference. Do not refcount this. nsIDocShell * mRootDocShell; - - // Max viewers allowed total, across all SHistory objects - static PRInt32 sHistoryMaxTotalViewers; }; //***************************************************************************** //*** nsSHEnumerator: Object Management @@ -133,4 +117,6 @@ private: nsSHistory * mSHistory; }; + + #endif /* nsSHistory */ diff --git a/mozilla/layout/base/nsDocumentViewer.cpp b/mozilla/layout/base/nsDocumentViewer.cpp index 4670466862f..9285fca5bae 100644 --- a/mozilla/layout/base/nsDocumentViewer.cpp +++ b/mozilla/layout/base/nsDocumentViewer.cpp @@ -1370,6 +1370,20 @@ DocumentViewerImpl::Destroy() mSHEntry = nsnull; + // If we put ourselves into session history, make sure there aren't + // too many content viewers around. Note: if max_viewers is set to 0, + // this can reenter Destroy() and dispose of this content viewer! + + nsCOMPtr webNav = do_QueryReferent(mContainer); + if (webNav) { + nsCOMPtr history; + webNav->GetSessionHistory(getter_AddRefs(history)); + nsCOMPtr historyInt = do_QueryInterface(history); + if (historyInt) { + historyInt->EvictContentViewers(); + } + } + // Break the link from the document/presentation to the docshell, so that // link traversals cannot affect the currently-loaded document. // When the presentation is restored, Open() and InitInternal() will reset @@ -1706,30 +1720,6 @@ DocumentViewerImpl::Show(void) nsCOMPtr prevViewer(mPreviousViewer); mPreviousViewer = nsnull; prevViewer->Destroy(); - - // Make sure we don't have too many cached ContentViewers - nsCOMPtr treeItem = do_QueryReferent(mContainer); - if (treeItem) { - // We need to find the root DocShell since only that object has an - // SHistory and we need the SHistory to evict content viewers - nsCOMPtr root; - treeItem->GetSameTypeRootTreeItem(getter_AddRefs(root)); - nsCOMPtr webNav = do_QueryInterface(root); - nsCOMPtr history; - webNav->GetSessionHistory(getter_AddRefs(history)); - nsCOMPtr historyInt = do_QueryInterface(history); - if (historyInt) { - PRInt32 prevIndex,loadedIndex; - nsCOMPtr docShell = do_QueryInterface(treeItem); - docShell->GetPreviousTransIndex(&prevIndex); - docShell->GetLoadedTransIndex(&loadedIndex); -#ifdef DEBUG_PAGE_CACHE - printf("About to evict content viewers: prev=%d, loaded=%d\n", - prevIndex, loadedIndex); -#endif - historyInt->EvictContentViewers(prevIndex, loadedIndex); - } - } } if (mWindow) { diff --git a/mozilla/modules/libpref/src/init/all.js b/mozilla/modules/libpref/src/init/all.js index 78bcae6189e..092de233520 100644 --- a/mozilla/modules/libpref/src/init/all.js +++ b/mozilla/modules/libpref/src/init/all.js @@ -62,9 +62,6 @@ pref("browser.cache.memory.enable", true); pref("browser.cache.disk_cache_ssl", false); // 0 = once-per-session, 1 = each-time, 2 = never, 3 = when-appropriate/automatically pref("browser.cache.check_doc_frequency", 3); -// Fastback caching - if this pref is negative, then we calculate the number -// of content viewers to cache based on the amount of available memory. -pref("browser.sessionhistory.max_total_viewers", -1); pref("browser.display.use_document_fonts", 1); // 0 = never, 1 = quick, 2 = always pref("browser.display.use_document_colors", true); diff --git a/mozilla/xpfe/bootstrap/browser-prefs.js b/mozilla/xpfe/bootstrap/browser-prefs.js index aaa1bbd9d59..cd9c632b5bb 100644 --- a/mozilla/xpfe/bootstrap/browser-prefs.js +++ b/mozilla/xpfe/bootstrap/browser-prefs.js @@ -113,6 +113,7 @@ pref("browser.search.param.Google.1.default", "chrome://navigator/content/search pref("browser.history.grouping", "day"); pref("browser.sessionhistory.max_entries", 50); +pref("browser.sessionhistory.max_viewers", 3); // Tabbed browser pref("browser.tabs.loadDivertedInBackground", false);