Commit 47a475e1 authored by ager@chromium.org's avatar ager@chromium.org

Avoid allocating temporary ranges in connection with text and character iterators.

30% performance improvement on DOM/textarea-edit on the oilpan build.
2% performance improvement on DOM/textarea-edit on the non-oilpan build.

R=yosin@chromium.org
BUG=388681

Review URL: https://codereview.chromium.org/544083002

git-svn-id: svn://svn.chromium.org/blink/trunk@181551 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent ef2f10e2
...@@ -154,10 +154,9 @@ void DocumentMarkerController::removeMarkers(Range* range, DocumentMarker::Marke ...@@ -154,10 +154,9 @@ void DocumentMarkerController::removeMarkers(Range* range, DocumentMarker::Marke
return; return;
ASSERT(!m_markers.isEmpty()); ASSERT(!m_markers.isEmpty());
RefPtrWillBeRawPtr<Range> textPiece = markedText.range(); int startOffset = markedText.startOffset();
int startOffset = textPiece->startOffset(); int endOffset = markedText.endOffset();
int endOffset = textPiece->endOffset(); removeMarkers(markedText.startContainer(), startOffset, endOffset - startOffset, markerTypes, shouldRemovePartiallyOverlappingMarker);
removeMarkers(textPiece->startContainer(), startOffset, endOffset - startOffset, markerTypes, shouldRemovePartiallyOverlappingMarker);
} }
} }
......
...@@ -85,11 +85,8 @@ PassRefPtrWillBeRawPtr<Range> PlainTextRange::createRangeFor(const ContainerNode ...@@ -85,11 +85,8 @@ PassRefPtrWillBeRawPtr<Range> PlainTextRange::createRangeFor(const ContainerNode
// FIXME: the atEnd() check shouldn't be necessary, workaround for <http://bugs.webkit.org/show_bug.cgi?id=6289>. // FIXME: the atEnd() check shouldn't be necessary, workaround for <http://bugs.webkit.org/show_bug.cgi?id=6289>.
if (!start() && !length() && it.atEnd()) { if (!start() && !length() && it.atEnd()) {
textRunRange = it.range(); resultRange->setStart(it.startContainer(), 0, ASSERT_NO_EXCEPTION);
resultRange->setEnd(it.startContainer(), 0, ASSERT_NO_EXCEPTION);
resultRange->setStart(textRunRange->startContainer(), 0, ASSERT_NO_EXCEPTION);
resultRange->setEnd(textRunRange->startContainer(), 0, ASSERT_NO_EXCEPTION);
return resultRange.release(); return resultRange.release();
} }
......
...@@ -251,7 +251,7 @@ void SpellChecker::advanceToNextMisspelling(bool startBeforeSelection) ...@@ -251,7 +251,7 @@ void SpellChecker::advanceToNextMisspelling(bool startBeforeSelection)
// Stop looking at start of next misspelled word // Stop looking at start of next misspelled word
CharacterIterator chars(grammarSearchRange.get()); CharacterIterator chars(grammarSearchRange.get());
chars.advance(misspellingOffset); chars.advance(misspellingOffset);
grammarSearchRange->setEnd(chars.range()->startContainer(), chars.range()->startOffset(), IGNORE_EXCEPTION); grammarSearchRange->setEnd(chars.startContainer(), chars.startOffset(), IGNORE_EXCEPTION);
} }
if (isGrammarCheckingEnabled()) if (isGrammarCheckingEnabled())
...@@ -282,7 +282,7 @@ void SpellChecker::advanceToNextMisspelling(bool startBeforeSelection) ...@@ -282,7 +282,7 @@ void SpellChecker::advanceToNextMisspelling(bool startBeforeSelection)
// Stop looking at start of next misspelled word // Stop looking at start of next misspelled word
CharacterIterator chars(grammarSearchRange.get()); CharacterIterator chars(grammarSearchRange.get());
chars.advance(misspellingOffset); chars.advance(misspellingOffset);
grammarSearchRange->setEnd(chars.range()->startContainer(), chars.range()->startOffset(), IGNORE_EXCEPTION); grammarSearchRange->setEnd(chars.startContainer(), chars.startOffset(), IGNORE_EXCEPTION);
} }
if (isGrammarCheckingEnabled()) if (isGrammarCheckingEnabled())
......
...@@ -109,14 +109,12 @@ PassRefPtrWillBeRawPtr<Range> SurroundingText::rangeFromContentOffsets(unsigned ...@@ -109,14 +109,12 @@ PassRefPtrWillBeRawPtr<Range> SurroundingText::rangeFromContentOffsets(unsigned
ASSERT(!iterator.atEnd()); ASSERT(!iterator.atEnd());
iterator.advance(startOffsetInContent); iterator.advance(startOffsetInContent);
ASSERT(iterator.range()); Position start = iterator.startPosition();
Position start = iterator.range()->startPosition();
ASSERT(!iterator.atEnd()); ASSERT(!iterator.atEnd());
iterator.advance(endOffsetInContent - startOffsetInContent); iterator.advance(endOffsetInContent - startOffsetInContent);
ASSERT(iterator.range()); Position end = iterator.startPosition();
Position end = iterator.range()->startPosition();
ASSERT(start.document()); ASSERT(start.document());
return Range::create(*start.document(), start, end); return Range::create(*start.document(), start, end);
......
...@@ -570,7 +570,7 @@ UChar TextIterator::characterAt(unsigned index) const ...@@ -570,7 +570,7 @@ UChar TextIterator::characterAt(unsigned index) const
return m_singleCharacterBuffer; return m_singleCharacterBuffer;
} }
return string()[startOffset() + index]; return string()[positionStartOffset() + index];
} }
String TextIterator::substring(unsigned position, unsigned length) const String TextIterator::substring(unsigned position, unsigned length) const
...@@ -584,7 +584,7 @@ String TextIterator::substring(unsigned position, unsigned length) const ...@@ -584,7 +584,7 @@ String TextIterator::substring(unsigned position, unsigned length) const
ASSERT(length == 1); ASSERT(length == 1);
return String(&m_singleCharacterBuffer, 1); return String(&m_singleCharacterBuffer, 1);
} }
return string().substring(startOffset() + position, length); return string().substring(positionStartOffset() + position, length);
} }
void TextIterator::appendTextToStringBuilder(StringBuilder& builder, unsigned position, unsigned maxLength) const void TextIterator::appendTextToStringBuilder(StringBuilder& builder, unsigned position, unsigned maxLength) const
...@@ -596,7 +596,7 @@ void TextIterator::appendTextToStringBuilder(StringBuilder& builder, unsigned po ...@@ -596,7 +596,7 @@ void TextIterator::appendTextToStringBuilder(StringBuilder& builder, unsigned po
ASSERT(!position); ASSERT(!position);
builder.append(m_singleCharacterBuffer); builder.append(m_singleCharacterBuffer);
} else { } else {
builder.append(string(), startOffset() + position, lengthToAppend); builder.append(string(), positionStartOffset() + position, lengthToAppend);
} }
} }
...@@ -1096,6 +1096,16 @@ bool TextIterator::handleNonTextNode() ...@@ -1096,6 +1096,16 @@ bool TextIterator::handleNonTextNode()
return true; return true;
} }
void TextIterator::flushPositionOffsets() const
{
if (!m_positionOffsetBaseNode)
return;
int index = m_positionOffsetBaseNode->nodeIndex();
m_positionStartOffset += index;
m_positionEndOffset += index;
m_positionOffsetBaseNode = nullptr;
}
void TextIterator::exitNode() void TextIterator::exitNode()
{ {
// prevent emitting a newline when exiting a collapsed block at beginning of the range // prevent emitting a newline when exiting a collapsed block at beginning of the range
...@@ -1181,12 +1191,7 @@ PassRefPtrWillBeRawPtr<Range> TextIterator::range() const ...@@ -1181,12 +1191,7 @@ PassRefPtrWillBeRawPtr<Range> TextIterator::range() const
{ {
// use the current run information, if we have it // use the current run information, if we have it
if (m_positionNode) { if (m_positionNode) {
if (m_positionOffsetBaseNode) { flushPositionOffsets();
int index = m_positionOffsetBaseNode->nodeIndex();
m_positionStartOffset += index;
m_positionEndOffset += index;
m_positionOffsetBaseNode = nullptr;
}
return Range::create(m_positionNode->document(), m_positionNode, m_positionStartOffset, m_positionNode, m_positionEndOffset); return Range::create(m_positionNode->document(), m_positionNode, m_positionStartOffset, m_positionNode, m_positionEndOffset);
} }
...@@ -1199,17 +1204,52 @@ PassRefPtrWillBeRawPtr<Range> TextIterator::range() const ...@@ -1199,17 +1204,52 @@ PassRefPtrWillBeRawPtr<Range> TextIterator::range() const
Node* TextIterator::node() const Node* TextIterator::node() const
{ {
RefPtrWillBeRawPtr<Range> textRange = range(); if (m_positionNode || m_endContainer) {
if (!textRange) Node* node = startContainer();
return 0; if (node->offsetInCharacters())
return node;
return NodeTraversal::childAt(*node, startOffset());
}
return 0;
}
Node* node = textRange->startContainer(); int TextIterator::startOffset() const
if (!node) {
return 0; if (m_positionNode) {
if (node->offsetInCharacters()) flushPositionOffsets();
return node; return m_positionStartOffset;
}
ASSERT(m_endContainer);
return m_endOffset;
}
return NodeTraversal::childAt(*node, textRange->startOffset()); int TextIterator::endOffset() const
{
if (m_positionNode) {
flushPositionOffsets();
return m_positionEndOffset;
}
ASSERT(m_endContainer);
return m_endOffset;
}
Node* TextIterator::startContainer() const
{
if (m_positionNode) {
return m_positionNode;
}
ASSERT(m_endContainer);
return m_endContainer;
}
Position TextIterator::startPosition() const
{
return createLegacyEditingPosition(startContainer(), startOffset());
}
Position TextIterator::endPosition() const
{
return createLegacyEditingPosition(startContainer(), endOffset());
} }
// -------- // --------
...@@ -1503,6 +1543,27 @@ PassRefPtrWillBeRawPtr<Range> SimplifiedBackwardsTextIterator::range() const ...@@ -1503,6 +1543,27 @@ PassRefPtrWillBeRawPtr<Range> SimplifiedBackwardsTextIterator::range() const
return Range::create(m_startNode->document(), m_startNode, m_startOffset, m_startNode, m_startOffset); return Range::create(m_startNode->document(), m_startNode, m_startOffset, m_startNode, m_startOffset);
} }
Node* SimplifiedBackwardsTextIterator::startContainer() const
{
if (m_positionNode)
return m_positionNode;
return m_startNode;
}
int SimplifiedBackwardsTextIterator::endOffset() const
{
if (m_positionNode)
return m_positionEndOffset;
return m_startOffset;
}
Position SimplifiedBackwardsTextIterator::startPosition() const
{
if (m_positionNode)
return createLegacyEditingPosition(m_positionNode, m_positionStartOffset);
return createLegacyEditingPosition(m_startNode, m_startOffset);
}
// -------- // --------
CharacterIterator::CharacterIterator(const Range* range, TextIteratorBehaviorFlags behavior) CharacterIterator::CharacterIterator(const Range* range, TextIteratorBehaviorFlags behavior)
...@@ -1546,6 +1607,47 @@ PassRefPtrWillBeRawPtr<Range> CharacterIterator::range() const ...@@ -1546,6 +1607,47 @@ PassRefPtrWillBeRawPtr<Range> CharacterIterator::range() const
return r.release(); return r.release();
} }
Node* CharacterIterator::startContainer() const
{
return m_textIterator.startContainer();
}
int CharacterIterator::startOffset() const
{
if (!m_textIterator.atEnd()) {
if (m_textIterator.length() > 1)
return m_textIterator.startOffset() + m_runOffset;
ASSERT(!m_runOffset);
}
return m_textIterator.startOffset();
}
Position CharacterIterator::startPosition() const
{
if (!m_textIterator.atEnd()) {
if (m_textIterator.length() > 1) {
Node* n = m_textIterator.startContainer();
int offset = m_textIterator.startOffset() + m_runOffset;
return createLegacyEditingPosition(n, offset);
}
ASSERT(!m_runOffset);
}
return m_textIterator.startPosition();
}
Position CharacterIterator::endPosition() const
{
if (!m_textIterator.atEnd()) {
if (m_textIterator.length() > 1) {
Node* n = m_textIterator.startContainer();
int offset = m_textIterator.startOffset() + m_runOffset;
return createLegacyEditingPosition(n, offset + 1);
}
ASSERT(!m_runOffset);
}
return m_textIterator.endPosition();
}
void CharacterIterator::advance(int count) void CharacterIterator::advance(int count)
{ {
if (count <= 0) { if (count <= 0) {
...@@ -1594,13 +1696,11 @@ void CharacterIterator::advance(int count) ...@@ -1594,13 +1696,11 @@ void CharacterIterator::advance(int count)
static void calculateCharacterSubrange(CharacterIterator& it, int offset, int length, Position& startPosition, Position& endPosition) static void calculateCharacterSubrange(CharacterIterator& it, int offset, int length, Position& startPosition, Position& endPosition)
{ {
it.advance(offset); it.advance(offset);
RefPtrWillBeRawPtr<Range> start = it.range(); startPosition = it.startPosition();
startPosition = start->startPosition();
if (length > 1) if (length > 1)
it.advance(length - 1); it.advance(length - 1);
RefPtrWillBeRawPtr<Range> end = it.range(); endPosition = it.endPosition();
endPosition = end->endPosition();
} }
BackwardsCharacterIterator::BackwardsCharacterIterator(const Range* range, TextIteratorBehaviorFlags behavior) BackwardsCharacterIterator::BackwardsCharacterIterator(const Range* range, TextIteratorBehaviorFlags behavior)
...@@ -1630,6 +1730,17 @@ PassRefPtrWillBeRawPtr<Range> BackwardsCharacterIterator::range() const ...@@ -1630,6 +1730,17 @@ PassRefPtrWillBeRawPtr<Range> BackwardsCharacterIterator::range() const
return r.release(); return r.release();
} }
Position BackwardsCharacterIterator::endPosition() const
{
Node* n = m_textIterator.startContainer();
if (m_textIterator.atEnd()) {
if (m_textIterator.length() > 1)
return createLegacyEditingPosition(n, m_textIterator.endOffset() - m_runOffset);
ASSERT(!m_runOffset);
}
return createLegacyEditingPosition(n, m_textIterator.endOffset());
}
void BackwardsCharacterIterator::advance(int count) void BackwardsCharacterIterator::advance(int count)
{ {
if (count <= 0) { if (count <= 0) {
...@@ -1699,8 +1810,6 @@ void WordAwareIterator::advance() ...@@ -1699,8 +1810,6 @@ void WordAwareIterator::advance()
while (!m_textIterator.atEnd() && !m_textIterator.length()) while (!m_textIterator.atEnd() && !m_textIterator.length())
m_textIterator.advance(); m_textIterator.advance();
m_range = m_textIterator.range();
if (m_textIterator.atEnd()) if (m_textIterator.atEnd())
return; return;
...@@ -1722,7 +1831,6 @@ void WordAwareIterator::advance() ...@@ -1722,7 +1831,6 @@ void WordAwareIterator::advance()
// Start gobbling chunks until we get to a suitable stopping point // Start gobbling chunks until we get to a suitable stopping point
m_textIterator.appendTextTo(m_buffer); m_textIterator.appendTextTo(m_buffer);
m_range->setEnd(m_textIterator.range()->endContainer(), m_textIterator.range()->endOffset(), IGNORE_EXCEPTION);
} }
} }
......
...@@ -110,6 +110,12 @@ public: ...@@ -110,6 +110,12 @@ public:
PassRefPtrWillBeRawPtr<Range> range() const; PassRefPtrWillBeRawPtr<Range> range() const;
Node* node() const; Node* node() const;
int startOffset() const;
int endOffset() const;
Node* startContainer() const;
Position startPosition() const;
Position endPosition() const;
// Computes the length of the given range using a text iterator. The default // Computes the length of the given range using a text iterator. The default
// iteration behavior is to always emit object replacement characters for // iteration behavior is to always emit object replacement characters for
// replaced elements. When |forSelectionPreservation| is set to true, it // replaced elements. When |forSelectionPreservation| is set to true, it
...@@ -129,7 +135,8 @@ private: ...@@ -129,7 +135,8 @@ private:
void initialize(const Position& start, const Position& end); void initialize(const Position& start, const Position& end);
int startOffset() const { return m_positionStartOffset; } void flushPositionOffsets() const;
int positionStartOffset() const { return m_positionStartOffset; }
const String& string() const { return m_text; } const String& string() const { return m_text; }
void exitNode(); void exitNode();
bool shouldRepresentNodeOffsetZero(); bool shouldRepresentNodeOffsetZero();
...@@ -246,6 +253,10 @@ public: ...@@ -246,6 +253,10 @@ public:
PassRefPtrWillBeRawPtr<Range> range() const; PassRefPtrWillBeRawPtr<Range> range() const;
Node* startContainer() const;
int endOffset() const;
Position startPosition() const;
private: private:
void exitNode(); void exitNode();
bool handleTextNode(); bool handleTextNode();
...@@ -324,6 +335,11 @@ public: ...@@ -324,6 +335,11 @@ public:
int characterOffset() const { return m_offset; } int characterOffset() const { return m_offset; }
PassRefPtrWillBeRawPtr<Range> range() const; PassRefPtrWillBeRawPtr<Range> range() const;
Node* startContainer() const;
int startOffset() const;
Position startPosition() const;
Position endPosition() const;
private: private:
void initialize(); void initialize();
...@@ -345,6 +361,8 @@ public: ...@@ -345,6 +361,8 @@ public:
PassRefPtrWillBeRawPtr<Range> range() const; PassRefPtrWillBeRawPtr<Range> range() const;
Position endPosition() const;
private: private:
int m_offset; int m_offset;
int m_runOffset; int m_runOffset;
...@@ -372,7 +390,6 @@ private: ...@@ -372,7 +390,6 @@ private:
Vector<UChar> m_buffer; Vector<UChar> m_buffer;
// Did we have to look ahead in the textIterator to confirm the current chunk? // Did we have to look ahead in the textIterator to confirm the current chunk?
bool m_didLookAhead; bool m_didLookAhead;
RefPtrWillBeMember<Range> m_range;
TextIterator m_textIterator; TextIterator m_textIterator;
}; };
......
...@@ -313,7 +313,7 @@ void VisibleSelection::appendTrailingWhitespace() ...@@ -313,7 +313,7 @@ void VisibleSelection::appendTrailingWhitespace()
UChar c = charIt.characterAt(0); UChar c = charIt.characterAt(0);
if ((!isSpaceOrNewline(c) && c != noBreakSpace) || c == '\n') if ((!isSpaceOrNewline(c) && c != noBreakSpace) || c == '\n')
break; break;
m_end = charIt.range()->endPosition(); m_end = charIt.endPosition();
changed = true; changed = true;
} }
if (changed) if (changed)
......
...@@ -514,9 +514,9 @@ static VisiblePosition previousBoundary(const VisiblePosition& c, BoundarySearch ...@@ -514,9 +514,9 @@ static VisiblePosition previousBoundary(const VisiblePosition& c, BoundarySearch
} }
if (!next) if (!next)
return VisiblePosition(it.atEnd() ? it.range()->startPosition() : pos, DOWNSTREAM); return VisiblePosition(it.atEnd() ? it.startPosition() : pos, DOWNSTREAM);
Node* node = it.range()->startContainer(); Node* node = it.startContainer();
if ((node->isTextNode() && static_cast<int>(next) <= node->maxCharacterOffset()) || (node->renderer() && node->renderer()->isBR() && !next)) if ((node->isTextNode() && static_cast<int>(next) <= node->maxCharacterOffset()) || (node->renderer() && node->renderer()->isBR() && !next))
// The next variable contains a usable index into a text node // The next variable contains a usable index into a text node
return VisiblePosition(createLegacyEditingPosition(node, next), DOWNSTREAM); return VisiblePosition(createLegacyEditingPosition(node, next), DOWNSTREAM);
...@@ -525,7 +525,7 @@ static VisiblePosition previousBoundary(const VisiblePosition& c, BoundarySearch ...@@ -525,7 +525,7 @@ static VisiblePosition previousBoundary(const VisiblePosition& c, BoundarySearch
BackwardsCharacterIterator charIt(searchRange.get()); BackwardsCharacterIterator charIt(searchRange.get());
charIt.advance(string.size() - suffixLength - next); charIt.advance(string.size() - suffixLength - next);
// FIXME: charIt can get out of shadow host. // FIXME: charIt can get out of shadow host.
return VisiblePosition(charIt.range()->endPosition(), DOWNSTREAM); return VisiblePosition(charIt.endPosition(), DOWNSTREAM);
} }
static VisiblePosition nextBoundary(const VisiblePosition& c, BoundarySearchFunction searchFunction) static VisiblePosition nextBoundary(const VisiblePosition& c, BoundarySearchFunction searchFunction)
...@@ -590,20 +590,19 @@ static VisiblePosition nextBoundary(const VisiblePosition& c, BoundarySearchFunc ...@@ -590,20 +590,19 @@ static VisiblePosition nextBoundary(const VisiblePosition& c, BoundarySearchFunc
} }
if (it.atEnd() && next == string.size()) { if (it.atEnd() && next == string.size()) {
pos = it.range()->startPosition(); pos = it.startPosition();
} else if (next != invalidOffset && next != prefixLength) { } else if (next != invalidOffset && next != prefixLength) {
// Use the character iterator to translate the next value into a DOM position. // Use the character iterator to translate the next value into a DOM position.
CharacterIterator charIt(searchRange.get(), TextIteratorEmitsCharactersBetweenAllVisiblePositions); CharacterIterator charIt(searchRange.get(), TextIteratorEmitsCharactersBetweenAllVisiblePositions);
charIt.advance(next - prefixLength - 1); charIt.advance(next - prefixLength - 1);
RefPtrWillBeRawPtr<Range> characterRange = charIt.range(); pos = charIt.endPosition();
pos = characterRange->endPosition();
if (charIt.characterAt(0) == '\n') { if (charIt.characterAt(0) == '\n') {
// FIXME: workaround for collapsed range (where only start position is correct) emitted for some emitted newlines (see rdar://5192593) // FIXME: workaround for collapsed range (where only start position is correct) emitted for some emitted newlines (see rdar://5192593)
VisiblePosition visPos = VisiblePosition(pos); VisiblePosition visPos = VisiblePosition(pos);
if (visPos == VisiblePosition(characterRange->startPosition())) { if (visPos == VisiblePosition(charIt.startPosition())) {
charIt.advance(1); charIt.advance(1);
pos = charIt.range()->startPosition(); pos = charIt.startPosition();
} }
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment