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:
Jan-Niklas Jaeschke
2025-02-22 19:46:44 +00:00
parent e8f2074681
commit 5a3143f2ec
4 changed files with 13 additions and 9 deletions

View File

@@ -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.

View File

@@ -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(

View File

@@ -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;
} }

View File

@@ -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.