зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1404897: Allow storing Servo selector lists in the document's selector cache. r=heycam
MozReview-Commit-ID: GtIWGN2zEGT --HG-- extra : rebase_source : 42de988406724fd3dbb11134cb454bbfc927e3a6
This commit is contained in:
Родитель
c59ce1be20
Коммит
dd2d07a12c
|
@ -1406,13 +1406,39 @@ nsIDocument::SelectorCache::~SelectorCache()
|
|||
AgeAllGenerations();
|
||||
}
|
||||
|
||||
void
|
||||
nsIDocument::SelectorCache::SelectorList::Reset()
|
||||
{
|
||||
if (mIsServo) {
|
||||
if (mServo) {
|
||||
Servo_SelectorList_Drop(mServo);
|
||||
mServo = nullptr;
|
||||
}
|
||||
} else {
|
||||
if (mGecko) {
|
||||
delete mGecko;
|
||||
mGecko = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// CacheList takes ownership of aSelectorList.
|
||||
void nsIDocument::SelectorCache::CacheList(const nsAString& aSelector,
|
||||
nsCSSSelectorList* aSelectorList)
|
||||
mozilla::UniquePtr<nsCSSSelectorList>&& aSelectorList)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
SelectorCacheKey* key = new SelectorCacheKey(aSelector);
|
||||
mTable.Put(key->mKey, aSelectorList);
|
||||
mTable.Put(key->mKey, SelectorList(Move(aSelectorList)));
|
||||
AddObject(key);
|
||||
}
|
||||
|
||||
void nsIDocument::SelectorCache::CacheList(
|
||||
const nsAString& aSelector,
|
||||
UniquePtr<RawServoSelectorList>&& aSelectorList)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
SelectorCacheKey* key = new SelectorCacheKey(aSelector);
|
||||
mTable.Put(key->mKey, SelectorList(Move(aSelectorList)));
|
||||
AddObject(key);
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "mozilla/LinkedList.h"
|
||||
#include "mozilla/NotNull.h"
|
||||
#include "mozilla/SegmentedVector.h"
|
||||
#include "mozilla/ServoBindingTypes.h"
|
||||
#include "mozilla/StyleBackendType.h"
|
||||
#include "mozilla/StyleSheet.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
|
@ -1148,27 +1149,106 @@ public:
|
|||
: public nsExpirationTracker<SelectorCacheKey, 4>
|
||||
{
|
||||
public:
|
||||
class SelectorList
|
||||
{
|
||||
public:
|
||||
SelectorList()
|
||||
: mIsServo(false)
|
||||
, mGecko(nullptr)
|
||||
{}
|
||||
|
||||
SelectorList(SelectorList&& aOther)
|
||||
{
|
||||
*this = mozilla::Move(aOther);
|
||||
}
|
||||
|
||||
SelectorList& operator=(SelectorList&& aOther)
|
||||
{
|
||||
Reset();
|
||||
mIsServo = aOther.mIsServo;
|
||||
if (mIsServo) {
|
||||
mServo = aOther.mServo;
|
||||
aOther.mServo = nullptr;
|
||||
} else {
|
||||
mGecko = aOther.mGecko;
|
||||
aOther.mGecko = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
SelectorList(const SelectorList& aOther) = delete;
|
||||
|
||||
explicit SelectorList(mozilla::UniquePtr<RawServoSelectorList>&& aList)
|
||||
: mIsServo(true)
|
||||
, mServo(aList.release())
|
||||
{}
|
||||
|
||||
explicit SelectorList(mozilla::UniquePtr<nsCSSSelectorList>&& aList)
|
||||
: mIsServo(false)
|
||||
, mGecko(aList.release())
|
||||
{}
|
||||
|
||||
~SelectorList() {
|
||||
Reset();
|
||||
}
|
||||
|
||||
bool IsServo() const { return mIsServo; }
|
||||
bool IsGecko() const { return !IsServo(); }
|
||||
|
||||
explicit operator bool() const
|
||||
{
|
||||
return IsServo() ? !!AsServo() : !!AsGecko();
|
||||
}
|
||||
|
||||
nsCSSSelectorList* AsGecko() const
|
||||
{
|
||||
MOZ_ASSERT(IsGecko());
|
||||
return mGecko;
|
||||
}
|
||||
|
||||
RawServoSelectorList* AsServo() const
|
||||
{
|
||||
MOZ_ASSERT(IsServo());
|
||||
return mServo;
|
||||
}
|
||||
|
||||
private:
|
||||
void Reset();
|
||||
|
||||
bool mIsServo;
|
||||
|
||||
union {
|
||||
nsCSSSelectorList* mGecko;
|
||||
RawServoSelectorList* mServo;
|
||||
};
|
||||
};
|
||||
|
||||
explicit SelectorCache(nsIEventTarget* aEventTarget);
|
||||
|
||||
// CacheList takes ownership of aSelectorList.
|
||||
void CacheList(const nsAString& aSelector, nsCSSSelectorList* aSelectorList);
|
||||
void CacheList(const nsAString& aSelector,
|
||||
mozilla::UniquePtr<nsCSSSelectorList>&& aSelectorList);
|
||||
void CacheList(const nsAString& aSelector,
|
||||
mozilla::UniquePtr<RawServoSelectorList>&& aSelectorList);
|
||||
|
||||
virtual void NotifyExpired(SelectorCacheKey* aSelector) override;
|
||||
|
||||
// We do not call MarkUsed because it would just slow down lookups and
|
||||
// because we're OK expiring things after a few seconds even if they're
|
||||
// being used. Returns whether we actually had an entry for aSelector.
|
||||
// If we have an entry and *aList is null, that indicates that aSelector
|
||||
//
|
||||
// If we have an entry and the selector list returned has a null
|
||||
// nsCSSSelectorList*/RawServoSelectorList*, that indicates that aSelector
|
||||
// has already been parsed and is not a syntactically valid selector.
|
||||
bool GetList(const nsAString& aSelector, nsCSSSelectorList** aList)
|
||||
SelectorList* GetList(const nsAString& aSelector)
|
||||
{
|
||||
return mTable.Get(aSelector, aList);
|
||||
return mTable.GetValue(aSelector);
|
||||
}
|
||||
|
||||
~SelectorCache();
|
||||
|
||||
private:
|
||||
nsClassHashtable<nsStringHashKey, nsCSSSelectorList> mTable;
|
||||
nsDataHashtable<nsStringHashKey, SelectorList> mTable;
|
||||
};
|
||||
|
||||
SelectorCache& GetSelectorCache() {
|
||||
|
|
|
@ -2682,21 +2682,23 @@ nsINode::ParseSelectorList(const nsAString& aSelectorString,
|
|||
{
|
||||
nsIDocument* doc = OwnerDoc();
|
||||
nsIDocument::SelectorCache& cache = doc->GetSelectorCache();
|
||||
nsCSSSelectorList* selectorList = nullptr;
|
||||
bool haveCachedList = cache.GetList(aSelectorString, &selectorList);
|
||||
if (haveCachedList) {
|
||||
if (!selectorList) {
|
||||
nsIDocument::SelectorCache::SelectorList* list =
|
||||
cache.GetList(aSelectorString);
|
||||
if (list) {
|
||||
if (!*list) {
|
||||
// Invalid selector.
|
||||
aRv.ThrowDOMException(NS_ERROR_DOM_SYNTAX_ERR,
|
||||
NS_LITERAL_CSTRING("'") + NS_ConvertUTF16toUTF8(aSelectorString) +
|
||||
NS_LITERAL_CSTRING("' is not a valid selector")
|
||||
);
|
||||
}
|
||||
return selectorList;
|
||||
MOZ_ASSERT(list->IsGecko(), "We haven't done anything with Servo yet");
|
||||
return list->AsGecko();
|
||||
}
|
||||
|
||||
nsCSSParser parser(doc->CSSLoader());
|
||||
|
||||
nsCSSSelectorList* selectorList = nullptr;
|
||||
aRv = parser.ParseSelectorString(aSelectorString,
|
||||
doc->GetDocumentURI(),
|
||||
0, // XXXbz get the line number!
|
||||
|
@ -2714,7 +2716,7 @@ nsINode::ParseSelectorList(const nsAString& aSelectorString,
|
|||
NS_LITERAL_CSTRING("' is not a valid selector")
|
||||
);
|
||||
|
||||
cache.CacheList(aSelectorString, nullptr);
|
||||
cache.CacheList(aSelectorString, UniquePtr<nsCSSSelectorList>());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -2734,7 +2736,7 @@ nsINode::ParseSelectorList(const nsAString& aSelectorString,
|
|||
if (selectorList) {
|
||||
NS_ASSERTION(selectorList->mSelectors,
|
||||
"How can we not have any selectors?");
|
||||
cache.CacheList(aSelectorString, selectorList);
|
||||
cache.CacheList(aSelectorString, UniquePtr<nsCSSSelectorList>(selectorList));
|
||||
} else {
|
||||
// This is the "only pseudo-element selectors" case, which is
|
||||
// not common, so just don't worry about caching it. That way a
|
||||
|
|
Загрузка…
Ссылка в новой задаче