Bug 1843239, optimize Location.hash, r=peterv,dom-core

Differential Revision: https://phabricator.services.mozilla.com/D183788
This commit is contained in:
Olli Pettay 2023-08-07 12:31:25 +00:00
Родитель 23a0c9beff
Коммит ae55d8bc22
8 изменённых файлов: 74 добавлений и 35 удалений

Просмотреть файл

@ -617,6 +617,7 @@ void BrowsingContext::SetDocShell(nsIDocShell* aDocShell) {
}
RecomputeCanExecuteScripts();
ClearCachedValuesOfLocations();
}
// This class implements a callback that will return the remote window proxy for
@ -1048,6 +1049,8 @@ void BrowsingContext::PrepareForProcessChange() {
mIsInProcess = false;
mUserGestureStart = TimeStamp();
ClearCachedValuesOfLocations();
// NOTE: For now, clear our nsDocShell reference, as we're primarily in a
// different process now. This may need to change in the future with
// Cross-Process BFCache.
@ -1414,6 +1417,9 @@ BrowsingContext::~BrowsingContext() {
sBrowsingContexts->Remove(Id());
}
UnregisterBrowserId(this);
ClearCachedValuesOfLocations();
mLocations.clear();
}
/* static */
@ -3758,6 +3764,17 @@ void BrowsingContext::ResetLocationChangeRateLimit() {
mLocationChangeRateLimitSpanStart = TimeStamp();
}
void BrowsingContext::LocationCreated(dom::Location* aLocation) {
MOZ_ASSERT(!aLocation->isInList());
mLocations.insertBack(aLocation);
}
void BrowsingContext::ClearCachedValuesOfLocations() {
for (dom::Location* loc = mLocations.getFirst(); loc; loc = loc->getNext()) {
loc->ClearCachedValues();
}
}
} // namespace dom
namespace ipc {

Просмотреть файл

@ -68,6 +68,7 @@ class ChildSHistory;
class ContentParent;
class Element;
struct LoadingSessionHistoryInfo;
class Location;
template <typename>
struct Nullable;
template <typename T>
@ -948,6 +949,9 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
return GetIsUnderHiddenEmbedderElement();
}
void LocationCreated(dom::Location* aLocation);
void ClearCachedValuesOfLocations();
protected:
virtual ~BrowsingContext();
BrowsingContext(WindowContext* aParentWindow, BrowsingContextGroup* aGroup,
@ -1023,7 +1027,7 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
uintptr_t(this) - offsetof(BrowsingContext, mLocation));
}
already_AddRefed<nsIDocShell> GetDocShell() override { return nullptr; }
nsIDocShell* GetDocShell() override { return nullptr; }
};
// Send a given `BaseTransaction` object to the correct remote.
@ -1406,6 +1410,8 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
// Used by CheckLocationChangeRateLimit. Do not apply cross-process.
uint32_t mLocationChangeRateLimitCount;
mozilla::TimeStamp mLocationChangeRateLimitSpanStart;
mozilla::LinkedList<dom::Location> mLocations;
};
/**

Просмотреть файл

@ -1550,7 +1550,7 @@ bool nsDocShell::SetCurrentURI(nsIURI* aURI, nsIRequest* aRequest,
mTitleValidForCurrentURI = false;
}
mCurrentURI = aURI;
SetCurrentURIInternal(aURI);
#ifdef DEBUG
mLastOpenedURI = aURI;
@ -1576,6 +1576,13 @@ bool nsDocShell::SetCurrentURI(nsIURI* aURI, nsIRequest* aRequest,
return !aFireOnLocationChange;
}
void nsDocShell::SetCurrentURIInternal(nsIURI* aURI) {
mCurrentURI = aURI;
if (mBrowsingContext) {
mBrowsingContext->ClearCachedValuesOfLocations();
}
}
NS_IMETHODIMP
nsDocShell::GetCharset(nsACString& aCharset) {
aCharset.Truncate();
@ -4574,7 +4581,7 @@ nsDocShell::Destroy() {
nsDocLoader::Destroy();
mParentWidget = nullptr;
mCurrentURI = nullptr;
SetCurrentURIInternal(nullptr);
if (mScriptGlobal) {
mScriptGlobal->DetachFromDocShell(!mWillChangeProcess);
@ -8189,7 +8196,7 @@ nsresult nsDocShell::SetupNewViewer(nsIContentViewer* aNewViewer,
viewer->Close(nullptr);
viewer->Destroy();
mContentViewer = nullptr;
mCurrentURI = nullptr;
SetCurrentURIInternal(nullptr);
NS_WARNING("ContentViewer Initialization failed");
return NS_ERROR_FAILURE;
}

Просмотреть файл

@ -1160,7 +1160,10 @@ class nsDocShell final : public nsDocLoader,
const nsAString& aTitle, bool aReplace,
nsIURI* aCurrentURI, bool aEqualURIs);
private: // data members
private:
void SetCurrentURIInternal(nsIURI* aURI);
// data members
nsString mTitle;
nsCString mOriginalUriString;
nsTObserverArray<nsWeakPtr> mPrivacyObservers;
@ -1205,6 +1208,7 @@ class nsDocShell final : public nsDocLoader,
mozilla::UniquePtr<mozilla::ObservedDocShell> mObserved;
// mCurrentURI should be marked immutable on set if possible.
// Change mCurrentURI only through SetCurrentURIInternal method.
nsCOMPtr<nsIURI> mCurrentURI;
nsCOMPtr<nsIReferrerInfo> mReferrerInfo;

Просмотреть файл

@ -23,6 +23,7 @@
#include "nsContentUtils.h"
#include "nsDocShell.h"
#include "nsGlobalWindowOuter.h"
#include "nsPIDOMWindowInlines.h"
#include "mozilla/Likely.h"
#include "nsCycleCollectionParticipant.h"
#include "mozilla/BasePrincipal.h"
@ -39,16 +40,19 @@
namespace mozilla::dom {
Location::Location(nsPIDOMWindowInner* aWindow,
BrowsingContext* aBrowsingContext)
: mInnerWindow(aWindow) {
// aBrowsingContext can be null if it gets called after nsDocShell::Destory().
if (aBrowsingContext) {
mBrowsingContextId = aBrowsingContext->Id();
Location::Location(nsPIDOMWindowInner* aWindow)
: mCachedHash(VoidString()), mInnerWindow(aWindow) {
BrowsingContext* bc = GetBrowsingContext();
if (bc) {
bc->LocationCreated(this);
}
}
Location::~Location() = default;
Location::~Location() {
if (isInList()) {
remove();
}
}
// QueryInterface implementation for Location
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Location)
@ -62,13 +66,12 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(Location)
NS_IMPL_CYCLE_COLLECTING_RELEASE(Location)
BrowsingContext* Location::GetBrowsingContext() {
RefPtr<BrowsingContext> bc = BrowsingContext::Get(mBrowsingContextId);
return bc.get();
return mInnerWindow ? mInnerWindow->GetBrowsingContext() : nullptr;
}
already_AddRefed<nsIDocShell> Location::GetDocShell() {
if (RefPtr<BrowsingContext> bc = GetBrowsingContext()) {
return do_AddRef(bc->GetDocShell());
nsIDocShell* Location::GetDocShell() {
if (BrowsingContext* bc = GetBrowsingContext()) {
return bc->GetDocShell();
}
return nullptr;
}
@ -76,7 +79,7 @@ already_AddRefed<nsIDocShell> Location::GetDocShell() {
nsresult Location::GetURI(nsIURI** aURI, bool aGetInnermostURI) {
*aURI = nullptr;
nsCOMPtr<nsIDocShell> docShell(GetDocShell());
nsIDocShell* docShell = GetDocShell();
if (!docShell) {
return NS_OK;
}
@ -114,6 +117,11 @@ void Location::GetHash(nsAString& aHash, nsIPrincipal& aSubjectPrincipal,
return;
}
if (!mCachedHash.IsVoid()) {
aHash = mCachedHash;
return;
}
aHash.SetLength(0);
nsCOMPtr<nsIURI> uri;
@ -123,7 +131,6 @@ void Location::GetHash(nsAString& aHash, nsIPrincipal& aSubjectPrincipal,
}
nsAutoCString ref;
nsAutoString unicodeRef;
aRv = uri->GetRef(ref);
if (NS_WARN_IF(aRv.Failed())) {
@ -135,14 +142,7 @@ void Location::GetHash(nsAString& aHash, nsIPrincipal& aSubjectPrincipal,
AppendUTF8toUTF16(ref, aHash);
}
if (aHash == mCachedHash) {
// Work around ShareThis stupidly polling location.hash every
// 5ms all the time by handing out the same exact string buffer
// we handed out last time.
aHash = mCachedHash;
} else {
mCachedHash = aHash;
}
mCachedHash = aHash;
}
void Location::SetHash(const nsAString& aHash, nsIPrincipal& aSubjectPrincipal,
@ -544,7 +544,7 @@ void Location::Reload(bool aForceget, nsIPrincipal& aSubjectPrincipal,
return;
}
RefPtr<nsDocShell> docShell(GetDocShell().downcast<nsDocShell>());
RefPtr<nsDocShell> docShell(nsDocShell::Cast(GetDocShell()));
if (!docShell) {
return aRv.Throw(NS_ERROR_FAILURE);
}
@ -613,7 +613,7 @@ void Location::Assign(const nsAString& aUrl, nsIPrincipal& aSubjectPrincipal,
bool Location::CallerSubsumes(nsIPrincipal* aSubjectPrincipal) {
MOZ_ASSERT(aSubjectPrincipal);
RefPtr<BrowsingContext> bc(GetBrowsingContext());
BrowsingContext* bc = GetBrowsingContext();
if (MOZ_UNLIKELY(!bc) || MOZ_UNLIKELY(bc->IsDiscarded())) {
// Per spec, operations on a Location object with a discarded BC are no-ops,
// not security errors, so we need to return true from the access check and
@ -646,4 +646,6 @@ JSObject* Location::WrapObject(JSContext* aCx,
return Location_Binding::Wrap(aCx, this, aGivenProto);
}
void Location::ClearCachedValues() { mCachedHash = VoidString(); }
} // namespace mozilla::dom

Просмотреть файл

@ -9,6 +9,7 @@
#include "js/TypeDecls.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/LinkedList.h"
#include "mozilla/dom/BrowsingContext.h"
#include "mozilla/dom/LocationBase.h"
#include "nsCycleCollectionParticipant.h"
@ -28,11 +29,12 @@ namespace mozilla::dom {
class Location final : public nsISupports,
public LocationBase,
public nsWrapperCache {
public nsWrapperCache,
public LinkedListElement<Location> {
public:
typedef BrowsingContext::LocationProxy RemoteProxy;
Location(nsPIDOMWindowInner* aWindow, BrowsingContext* aBrowsingContext);
explicit Location(nsPIDOMWindowInner* aWindow);
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(Location)
@ -110,11 +112,13 @@ class Location final : public nsISupports,
nsresult ToString(nsAString& aString) { return GetHref(aString); }
void ClearCachedValues();
protected:
virtual ~Location();
BrowsingContext* GetBrowsingContext() override;
already_AddRefed<nsIDocShell> GetDocShell() override;
nsIDocShell* GetDocShell() override;
// In the case of jar: uris, we sometimes want the place the jar was
// fetched from as the URI instead of the jar: uri itself. Pass in
@ -127,7 +131,6 @@ class Location final : public nsISupports,
nsString mCachedHash;
nsCOMPtr<nsPIDOMWindowInner> mInnerWindow;
uint64_t mBrowsingContextId = 0;
};
} // namespace mozilla::dom

Просмотреть файл

@ -36,7 +36,7 @@ class LocationBase {
protected:
virtual BrowsingContext* GetBrowsingContext() = 0;
virtual already_AddRefed<nsIDocShell> GetDocShell() = 0;
virtual nsIDocShell* GetDocShell() = 0;
void SetURI(nsIURI* aURL, nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv,
bool aReplace = false);

Просмотреть файл

@ -4259,7 +4259,7 @@ nsGlobalWindowInner::GetExistingDebuggerNotificationManager() {
Location* nsGlobalWindowInner::Location() {
if (!mLocation) {
mLocation = new dom::Location(this, GetBrowsingContext());
mLocation = new dom::Location(this);
}
return mLocation;