Bug 1942080, part 4 - Text Fragments: Use NodeIndexCache to further speed up nsContentUtils::ComparePoints(). r=farre,dom-core
`nsContentUtils::ComparePoints()` already has a cache which keeps the last 100 indices in a stack-allocated array. This patch makes use of this cache in the hot path. Differential Revision: https://phabricator.services.mozilla.com/D235557
This commit is contained in:
@@ -873,6 +873,7 @@ Result<nsTArray<RefPtr<nsRange>>, ErrorResult>
|
|||||||
TextDirectiveCreator::FindAllMatchingRanges(const nsString& aSearchQuery) {
|
TextDirectiveCreator::FindAllMatchingRanges(const nsString& aSearchQuery) {
|
||||||
MOZ_ASSERT(!aSearchQuery.IsEmpty());
|
MOZ_ASSERT(!aSearchQuery.IsEmpty());
|
||||||
ErrorResult rv;
|
ErrorResult rv;
|
||||||
|
nsContentUtils::NodeIndexCache nodeIndexCache;
|
||||||
RangeBoundary documentStart{&mDocument, 0u};
|
RangeBoundary documentStart{&mDocument, 0u};
|
||||||
RefPtr<nsRange> searchRange =
|
RefPtr<nsRange> searchRange =
|
||||||
nsRange::Create(documentStart, mInputRange->EndRef(), rv);
|
nsRange::Create(documentStart, mInputRange->EndRef(), rv);
|
||||||
@@ -888,14 +889,14 @@ TextDirectiveCreator::FindAllMatchingRanges(const nsString& aSearchQuery) {
|
|||||||
return matchingRanges;
|
return matchingRanges;
|
||||||
}
|
}
|
||||||
RefPtr<nsRange> searchResult = TextDirectiveUtil::FindStringInRange(
|
RefPtr<nsRange> searchResult = TextDirectiveUtil::FindStringInRange(
|
||||||
searchStart, searchEnd, aSearchQuery, true, true);
|
searchStart, searchEnd, aSearchQuery, true, true, &nodeIndexCache);
|
||||||
if (!searchResult) {
|
if (!searchResult) {
|
||||||
// This would mean we reached a weird edge case in which the search query
|
// This would mean we reached a weird edge case in which the search query
|
||||||
// is not in the search range.
|
// is not in the search range.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (TextDirectiveUtil::NormalizedRangeBoundariesAreEqual(
|
if (TextDirectiveUtil::NormalizedRangeBoundariesAreEqual(
|
||||||
searchResult->EndRef(), searchEnd)) {
|
searchResult->EndRef(), searchEnd, &nodeIndexCache)) {
|
||||||
// It is safe to assume that this algorithm reached the end of all
|
// It is safe to assume that this algorithm reached the end of all
|
||||||
// potential ranges if the search result is equal to the search query.
|
// potential ranges if the search result is equal to the search query.
|
||||||
// Therefore, this range is not added to the results.
|
// Therefore, this range is not added to the results.
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ RefPtr<nsRange> TextDirectiveFinder::FindRangeForTextDirective(
|
|||||||
if (rv.Failed()) {
|
if (rv.Failed()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
nsContentUtils::NodeIndexCache nodeIndexCache;
|
||||||
// 2. While searchRange is not collapsed:
|
// 2. While searchRange is not collapsed:
|
||||||
while (!searchRange->Collapsed()) {
|
while (!searchRange->Collapsed()) {
|
||||||
// 2.1. Let potentialMatch be null.
|
// 2.1. Let potentialMatch be null.
|
||||||
@@ -108,7 +109,7 @@ RefPtr<nsRange> TextDirectiveFinder::FindRangeForTextDirective(
|
|||||||
// searchRange, wordStartBounded true and wordEndBounded false.
|
// searchRange, wordStartBounded true and wordEndBounded false.
|
||||||
RefPtr<nsRange> prefixMatch = TextDirectiveUtil::FindStringInRange(
|
RefPtr<nsRange> prefixMatch = TextDirectiveUtil::FindStringInRange(
|
||||||
searchRange->StartRef(), searchRange->EndRef(), aTextDirective.prefix,
|
searchRange->StartRef(), searchRange->EndRef(), aTextDirective.prefix,
|
||||||
true, false);
|
true, false, &nodeIndexCache);
|
||||||
// 2.2.2. If prefixMatch is null, return null.
|
// 2.2.2. If prefixMatch is null, return null.
|
||||||
if (!prefixMatch) {
|
if (!prefixMatch) {
|
||||||
TEXT_FRAGMENT_LOG(
|
TEXT_FRAGMENT_LOG(
|
||||||
@@ -213,7 +214,7 @@ RefPtr<nsRange> TextDirectiveFinder::FindRangeForTextDirective(
|
|||||||
// wordStartBounded true, and wordEndBounded mustEndAtWordBoundary.
|
// wordStartBounded true, and wordEndBounded mustEndAtWordBoundary.
|
||||||
potentialMatch = TextDirectiveUtil::FindStringInRange(
|
potentialMatch = TextDirectiveUtil::FindStringInRange(
|
||||||
searchRange->StartRef(), searchRange->EndRef(), aTextDirective.start,
|
searchRange->StartRef(), searchRange->EndRef(), aTextDirective.start,
|
||||||
true, mustEndAtWordBoundary);
|
true, mustEndAtWordBoundary, &nodeIndexCache);
|
||||||
// 2.3.3. If potentialMatch is null, return null.
|
// 2.3.3. If potentialMatch is null, return null.
|
||||||
if (!potentialMatch) {
|
if (!potentialMatch) {
|
||||||
TEXT_FRAGMENT_LOG(
|
TEXT_FRAGMENT_LOG(
|
||||||
@@ -258,7 +259,7 @@ RefPtr<nsRange> TextDirectiveFinder::FindRangeForTextDirective(
|
|||||||
// mustEndAtWordBoundary.
|
// mustEndAtWordBoundary.
|
||||||
RefPtr<nsRange> endMatch = TextDirectiveUtil::FindStringInRange(
|
RefPtr<nsRange> endMatch = TextDirectiveUtil::FindStringInRange(
|
||||||
rangeEndSearchRange->StartRef(), rangeEndSearchRange->EndRef(),
|
rangeEndSearchRange->StartRef(), rangeEndSearchRange->EndRef(),
|
||||||
aTextDirective.end, true, mustEndAtWordBoundary);
|
aTextDirective.end, true, mustEndAtWordBoundary, &nodeIndexCache);
|
||||||
// 2.5.1.3. If endMatch is null then return null.
|
// 2.5.1.3. If endMatch is null then return null.
|
||||||
if (!endMatch) {
|
if (!endMatch) {
|
||||||
TEXT_FRAGMENT_LOG(
|
TEXT_FRAGMENT_LOG(
|
||||||
|
|||||||
@@ -425,8 +425,8 @@ TextDirectiveUtil::FindBlockBoundaryInRange(const nsRange& aRange,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* static */ bool TextDirectiveUtil::NormalizedRangeBoundariesAreEqual(
|
/* static */ bool TextDirectiveUtil::NormalizedRangeBoundariesAreEqual(
|
||||||
const RangeBoundary& aRangeBoundary1,
|
const RangeBoundary& aRangeBoundary1, const RangeBoundary& aRangeBoundary2,
|
||||||
const RangeBoundary& aRangeBoundary2) {
|
nsContentUtils::NodeIndexCache* aCache /* = nullptr */) {
|
||||||
MOZ_ASSERT(aRangeBoundary1.IsSetAndValid() &&
|
MOZ_ASSERT(aRangeBoundary1.IsSetAndValid() &&
|
||||||
aRangeBoundary2.IsSetAndValid());
|
aRangeBoundary2.IsSetAndValid());
|
||||||
if (aRangeBoundary1 == aRangeBoundary2) {
|
if (aRangeBoundary1 == aRangeBoundary2) {
|
||||||
@@ -468,7 +468,8 @@ TextDirectiveUtil::FindBlockBoundaryInRange(const nsRange& aRange,
|
|||||||
|
|
||||||
mozilla::UnsafePreContentIterator iter;
|
mozilla::UnsafePreContentIterator iter;
|
||||||
// ContentIterator classes require boundaries to be in correct order.
|
// ContentIterator classes require boundaries to be in correct order.
|
||||||
auto comp = nsContentUtils::ComparePoints(aRangeBoundary1, aRangeBoundary2);
|
auto comp =
|
||||||
|
nsContentUtils::ComparePoints(aRangeBoundary1, aRangeBoundary2, aCache);
|
||||||
if (!comp) {
|
if (!comp) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -193,7 +193,8 @@ class TextDirectiveUtil final {
|
|||||||
*/
|
*/
|
||||||
static bool NormalizedRangeBoundariesAreEqual(
|
static bool NormalizedRangeBoundariesAreEqual(
|
||||||
const RangeBoundary& aRangeBoundary1,
|
const RangeBoundary& aRangeBoundary1,
|
||||||
const RangeBoundary& aRangeBoundary2);
|
const RangeBoundary& aRangeBoundary2,
|
||||||
|
nsContentUtils::NodeIndexCache* aCache = nullptr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Extends the range boundaries to word boundaries across nodes.
|
* @brief Extends the range boundaries to word boundaries across nodes.
|
||||||
|
|||||||
Reference in New Issue
Block a user