Commit 58ab4932 authored by kouhei@chromium.org's avatar kouhei@chromium.org

Remove SegmentedString::m_pushedChar{1,2} optimization

Before r201294, SegmentedString::push() had an exotic behavior where two
consecutive push() results are swapped.  SegmentedString stored those two
chars into m_pushedChar{1,2} to avoid messing up SegmentedSubString.

After r201294, SegmentedString::push() is guaranteed to be used for
ungetc()-like usecase, where it reverts the SegmentedString::advance()
which was issued just before the call.

This CL removes m_pushedChar{1,2} optimization, and replace it with
SegmentedSubstring::push() which simply decrement m_data.string{8,16}Ptr.
In pessimistic case, this may end up prepending wtf::String inside
SegmentedSubstring, but this should be very rare.

BUG=None
TESTS=SegmentedStringTest

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

git-svn-id: svn://svn.chromium.org/blink/trunk@201517 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 888c76ea
...@@ -25,11 +25,6 @@ namespace blink { ...@@ -25,11 +25,6 @@ namespace blink {
unsigned SegmentedString::length() const unsigned SegmentedString::length() const
{ {
unsigned length = m_currentString.length(); unsigned length = m_currentString.length();
if (m_pushedChar1) {
++length;
if (m_pushedChar2)
++length;
}
if (isComposite()) { if (isComposite()) {
Deque<SegmentedSubstring>::const_iterator it = m_substrings.begin(); Deque<SegmentedSubstring>::const_iterator it = m_substrings.begin();
Deque<SegmentedSubstring>::const_iterator e = m_substrings.end(); Deque<SegmentedSubstring>::const_iterator e = m_substrings.end();
...@@ -52,8 +47,6 @@ void SegmentedString::setExcludeLineNumbers() ...@@ -52,8 +47,6 @@ void SegmentedString::setExcludeLineNumbers()
void SegmentedString::clear() void SegmentedString::clear()
{ {
m_pushedChar1 = 0;
m_pushedChar2 = 0;
m_currentChar = 0; m_currentChar = 0;
m_currentString.clear(); m_currentString.clear();
m_numberOfCharactersConsumedPriorToCurrentString = 0; m_numberOfCharactersConsumedPriorToCurrentString = 0;
...@@ -83,9 +76,19 @@ void SegmentedString::append(const SegmentedSubstring& s) ...@@ -83,9 +76,19 @@ void SegmentedString::append(const SegmentedSubstring& s)
m_empty = false; m_empty = false;
} }
void SegmentedString::push(UChar c)
{
ASSERT(c);
if (m_currentString.pushIfPossible(c)) {
m_currentChar = c;
return;
}
prepend(SegmentedString(String(&c, 1)));
}
void SegmentedString::prepend(const SegmentedSubstring& s) void SegmentedString::prepend(const SegmentedSubstring& s)
{ {
ASSERT(!escaped());
ASSERT(!s.numberOfCharactersConsumed()); ASSERT(!s.numberOfCharactersConsumed());
if (!s.length()) if (!s.length())
return; return;
...@@ -119,13 +122,6 @@ void SegmentedString::close() ...@@ -119,13 +122,6 @@ void SegmentedString::close()
void SegmentedString::append(const SegmentedString& s) void SegmentedString::append(const SegmentedString& s)
{ {
ASSERT(!m_closed); ASSERT(!m_closed);
if (s.m_pushedChar1) {
Vector<UChar, 2> unconsumedData;
unconsumedData.append(s.m_pushedChar1);
if (s.m_pushedChar2)
unconsumedData.append(s.m_pushedChar2);
append(SegmentedSubstring(String(unconsumedData)));
}
append(s.m_currentString); append(s.m_currentString);
if (s.isComposite()) { if (s.isComposite()) {
...@@ -134,13 +130,11 @@ void SegmentedString::append(const SegmentedString& s) ...@@ -134,13 +130,11 @@ void SegmentedString::append(const SegmentedString& s)
for (; it != e; ++it) for (; it != e; ++it)
append(*it); append(*it);
} }
m_currentChar = m_pushedChar1 ? m_pushedChar1 : (m_currentString.length() ? m_currentString.getCurrentChar() : 0); m_currentChar = m_currentString.length() ? m_currentString.getCurrentChar() : 0;
} }
void SegmentedString::prepend(const SegmentedString& s) void SegmentedString::prepend(const SegmentedString& s)
{ {
ASSERT(!escaped());
ASSERT(!s.escaped());
if (s.isComposite()) { if (s.isComposite()) {
Deque<SegmentedSubstring>::const_reverse_iterator it = s.m_substrings.rbegin(); Deque<SegmentedSubstring>::const_reverse_iterator it = s.m_substrings.rbegin();
Deque<SegmentedSubstring>::const_reverse_iterator e = s.m_substrings.rend(); Deque<SegmentedSubstring>::const_reverse_iterator e = s.m_substrings.rend();
...@@ -173,11 +167,6 @@ void SegmentedString::advanceSubstring() ...@@ -173,11 +167,6 @@ void SegmentedString::advanceSubstring()
String SegmentedString::toString() const String SegmentedString::toString() const
{ {
StringBuilder result; StringBuilder result;
if (m_pushedChar1) {
result.append(m_pushedChar1);
if (m_pushedChar2)
result.append(m_pushedChar2);
}
m_currentString.appendTo(result); m_currentString.appendTo(result);
if (isComposite()) { if (isComposite()) {
Deque<SegmentedSubstring>::const_iterator it = m_substrings.begin(); Deque<SegmentedSubstring>::const_iterator it = m_substrings.begin();
...@@ -199,21 +188,18 @@ void SegmentedString::advance(unsigned count, UChar* consumedCharacters) ...@@ -199,21 +188,18 @@ void SegmentedString::advance(unsigned count, UChar* consumedCharacters)
void SegmentedString::advance8() void SegmentedString::advance8()
{ {
ASSERT(!m_pushedChar1);
decrementAndCheckLength(); decrementAndCheckLength();
m_currentChar = m_currentString.incrementAndGetCurrentChar8(); m_currentChar = m_currentString.incrementAndGetCurrentChar8();
} }
void SegmentedString::advance16() void SegmentedString::advance16()
{ {
ASSERT(!m_pushedChar1);
decrementAndCheckLength(); decrementAndCheckLength();
m_currentChar = m_currentString.incrementAndGetCurrentChar16(); m_currentChar = m_currentString.incrementAndGetCurrentChar16();
} }
void SegmentedString::advanceAndUpdateLineNumber8() void SegmentedString::advanceAndUpdateLineNumber8()
{ {
ASSERT(!m_pushedChar1);
ASSERT(m_currentString.getCurrentChar() == m_currentChar); ASSERT(m_currentString.getCurrentChar() == m_currentChar);
if (m_currentChar == '\n') { if (m_currentChar == '\n') {
++m_currentLine; ++m_currentLine;
...@@ -225,7 +211,6 @@ void SegmentedString::advanceAndUpdateLineNumber8() ...@@ -225,7 +211,6 @@ void SegmentedString::advanceAndUpdateLineNumber8()
void SegmentedString::advanceAndUpdateLineNumber16() void SegmentedString::advanceAndUpdateLineNumber16()
{ {
ASSERT(!m_pushedChar1);
ASSERT(m_currentString.getCurrentChar() == m_currentChar); ASSERT(m_currentString.getCurrentChar() == m_currentChar);
if (m_currentChar == '\n') { if (m_currentChar == '\n') {
++m_currentLine; ++m_currentLine;
...@@ -237,17 +222,7 @@ void SegmentedString::advanceAndUpdateLineNumber16() ...@@ -237,17 +222,7 @@ void SegmentedString::advanceAndUpdateLineNumber16()
void SegmentedString::advanceSlowCase() void SegmentedString::advanceSlowCase()
{ {
if (m_pushedChar1) { if (m_currentString.length()) {
m_pushedChar1 = m_pushedChar2;
m_pushedChar2 = 0;
if (m_pushedChar1) {
m_currentChar = m_pushedChar1;
return;
}
updateAdvanceFunctionPointers();
} else if (m_currentString.length()) {
m_currentString.decrementLength(); m_currentString.decrementLength();
if (!m_currentString.length()) if (!m_currentString.length())
advanceSubstring(); advanceSubstring();
...@@ -263,17 +238,7 @@ void SegmentedString::advanceSlowCase() ...@@ -263,17 +238,7 @@ void SegmentedString::advanceSlowCase()
void SegmentedString::advanceAndUpdateLineNumberSlowCase() void SegmentedString::advanceAndUpdateLineNumberSlowCase()
{ {
if (m_pushedChar1) { if (m_currentString.length()) {
m_pushedChar1 = m_pushedChar2;
m_pushedChar2 = 0;
if (m_pushedChar1) {
m_currentChar = m_pushedChar1;
return;
}
updateAdvanceFunctionPointers();
} else if (m_currentString.length()) {
if (m_currentString.getCurrentChar() == '\n' && m_currentString.doNotExcludeLineNumbers()) { if (m_currentString.getCurrentChar() == '\n' && m_currentString.doNotExcludeLineNumbers()) {
++m_currentLine; ++m_currentLine;
// Plus 1 because numberOfCharactersConsumed value hasn't incremented yet; it does with length() decrement below. // Plus 1 because numberOfCharactersConsumed value hasn't incremented yet; it does with length() decrement below.
......
...@@ -55,10 +55,11 @@ public: ...@@ -55,10 +55,11 @@ public:
} }
} else { } else {
m_is8Bit = false; m_is8Bit = false;
m_data.string8Ptr = nullptr;
} }
} }
void clear() { m_length = 0; m_data.string16Ptr = 0; m_is8Bit = false;} void clear() { m_length = 0; m_data.string16Ptr = nullptr; m_is8Bit = false;}
bool is8Bit() { return m_is8Bit; } bool is8Bit() { return m_is8Bit; }
...@@ -81,6 +82,30 @@ public: ...@@ -81,6 +82,30 @@ public:
} }
} }
bool pushIfPossible(UChar c)
{
if (!m_length)
return false;
if (m_is8Bit) {
if (m_data.string8Ptr == m_string.characters8())
return false;
--m_data.string8Ptr;
ASSERT(*m_data.string8Ptr == c);
++m_length;
return true;
}
if (m_data.string16Ptr == m_string.characters16())
return false;
--m_data.string16Ptr;
ASSERT(*m_data.string16Ptr == static_cast<LChar>(c));
++m_length;
return true;
}
UChar getCurrentChar8() UChar getCurrentChar8()
{ {
return *m_data.string8Ptr; return *m_data.string8Ptr;
...@@ -148,9 +173,7 @@ private: ...@@ -148,9 +173,7 @@ private:
class PLATFORM_EXPORT SegmentedString { class PLATFORM_EXPORT SegmentedString {
public: public:
SegmentedString() SegmentedString()
: m_pushedChar1(0) : m_currentChar(0)
, m_pushedChar2(0)
, m_currentChar(0)
, m_numberOfCharactersConsumedPriorToCurrentString(0) , m_numberOfCharactersConsumedPriorToCurrentString(0)
, m_numberOfCharactersConsumedPriorToCurrentLine(0) , m_numberOfCharactersConsumedPriorToCurrentLine(0)
, m_currentLine(0) , m_currentLine(0)
...@@ -163,9 +186,7 @@ public: ...@@ -163,9 +186,7 @@ public:
} }
SegmentedString(const String& str) SegmentedString(const String& str)
: m_pushedChar1(0) : m_currentString(str)
, m_pushedChar2(0)
, m_currentString(str)
, m_currentChar(0) , m_currentChar(0)
, m_numberOfCharactersConsumedPriorToCurrentString(0) , m_numberOfCharactersConsumedPriorToCurrentString(0)
, m_numberOfCharactersConsumedPriorToCurrentLine(0) , m_numberOfCharactersConsumedPriorToCurrentLine(0)
...@@ -188,19 +209,7 @@ public: ...@@ -188,19 +209,7 @@ public:
bool excludeLineNumbers() const { return m_currentString.excludeLineNumbers(); } bool excludeLineNumbers() const { return m_currentString.excludeLineNumbers(); }
void setExcludeLineNumbers(); void setExcludeLineNumbers();
void push(UChar c) void push(UChar);
{
ASSERT(c);
if (!m_pushedChar1) {
m_currentChar = m_pushedChar1 = c;
updateSlowCaseFunctionPointers();
} else {
ASSERT(!m_pushedChar2);
m_pushedChar2 = m_pushedChar1;
m_currentChar = m_pushedChar1 = c;
}
}
bool isEmpty() const { return m_empty; } bool isEmpty() const { return m_empty; }
unsigned length() const; unsigned length() const;
...@@ -219,7 +228,6 @@ public: ...@@ -219,7 +228,6 @@ public:
void advance() void advance()
{ {
if (m_fastPathFlags & Use8BitAdvance) { if (m_fastPathFlags & Use8BitAdvance) {
ASSERT(!m_pushedChar1);
m_currentChar = m_currentString.incrementAndGetCurrentChar8(); m_currentChar = m_currentString.incrementAndGetCurrentChar8();
decrementAndCheckLength(); decrementAndCheckLength();
return; return;
...@@ -231,8 +239,6 @@ public: ...@@ -231,8 +239,6 @@ public:
inline void advanceAndUpdateLineNumber() inline void advanceAndUpdateLineNumber()
{ {
if (m_fastPathFlags & Use8BitAdvance) { if (m_fastPathFlags & Use8BitAdvance) {
ASSERT(!m_pushedChar1);
bool haveNewLine = (m_currentChar == '\n') & !!(m_fastPathFlags & Use8BitAdvanceAndUpdateLineNumbers); bool haveNewLine = (m_currentChar == '\n') & !!(m_fastPathFlags & Use8BitAdvanceAndUpdateLineNumbers);
m_currentChar = m_currentString.incrementAndGetCurrentChar8(); m_currentChar = m_currentString.incrementAndGetCurrentChar8();
decrementAndCheckLength(); decrementAndCheckLength();
...@@ -269,7 +275,7 @@ public: ...@@ -269,7 +275,7 @@ public:
void advancePastNewlineAndUpdateLineNumber() void advancePastNewlineAndUpdateLineNumber()
{ {
ASSERT(currentChar() == '\n'); ASSERT(currentChar() == '\n');
if (!m_pushedChar1 && m_currentString.length() > 1) { if (m_currentString.length() > 1) {
int newLineFlag = m_currentString.doNotExcludeLineNumbers(); int newLineFlag = m_currentString.doNotExcludeLineNumbers();
m_currentLine += newLineFlag; m_currentLine += newLineFlag;
if (newLineFlag) if (newLineFlag)
...@@ -285,16 +291,9 @@ public: ...@@ -285,16 +291,9 @@ public:
// have space for at least |count| characters. // have space for at least |count| characters.
void advance(unsigned count, UChar* consumedCharacters); void advance(unsigned count, UChar* consumedCharacters);
bool escaped() const { return m_pushedChar1; }
int numberOfCharactersConsumed() const int numberOfCharactersConsumed() const
{ {
int numberOfPushedCharacters = 0; int numberOfPushedCharacters = 0;
if (m_pushedChar1) {
++numberOfPushedCharacters;
if (m_pushedChar2)
++numberOfPushedCharacters;
}
return m_numberOfCharactersConsumedPriorToCurrentString + m_currentString.numberOfCharactersConsumed() - numberOfPushedCharacters; return m_numberOfCharactersConsumedPriorToCurrentString + m_currentString.numberOfCharactersConsumed() - numberOfPushedCharacters;
} }
...@@ -340,7 +339,7 @@ private: ...@@ -340,7 +339,7 @@ private:
void updateAdvanceFunctionPointers() void updateAdvanceFunctionPointers()
{ {
if ((m_currentString.length() > 1) && !m_pushedChar1) { if (m_currentString.length() > 1) {
if (m_currentString.is8Bit()) { if (m_currentString.is8Bit()) {
m_advanceFunc = &SegmentedString::advance8; m_advanceFunc = &SegmentedString::advance8;
m_fastPathFlags = Use8BitAdvance; m_fastPathFlags = Use8BitAdvance;
...@@ -373,7 +372,7 @@ private: ...@@ -373,7 +372,7 @@ private:
inline LookAheadResult lookAheadInline(const String& string, TextCaseSensitivity caseSensitivity) inline LookAheadResult lookAheadInline(const String& string, TextCaseSensitivity caseSensitivity)
{ {
if (!m_pushedChar1 && string.length() <= static_cast<unsigned>(m_currentString.length())) { if (string.length() <= static_cast<unsigned>(m_currentString.length())) {
String currentSubstring = m_currentString.currentSubString(string.length()); String currentSubstring = m_currentString.currentSubString(string.length());
if (currentSubstring.startsWith(string, caseSensitivity)) if (currentSubstring.startsWith(string, caseSensitivity))
return DidMatch; return DidMatch;
...@@ -399,8 +398,6 @@ private: ...@@ -399,8 +398,6 @@ private:
bool isComposite() const { return !m_substrings.isEmpty(); } bool isComposite() const { return !m_substrings.isEmpty(); }
UChar m_pushedChar1;
UChar m_pushedChar2;
SegmentedSubstring m_currentString; SegmentedSubstring m_currentString;
UChar m_currentChar; UChar m_currentChar;
int m_numberOfCharactersConsumedPriorToCurrentString; int m_numberOfCharactersConsumedPriorToCurrentString;
......
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