diff options
| author | Ben Murdoch <benm@google.com> | 2011-05-05 14:36:32 +0100 |
|---|---|---|
| committer | Ben Murdoch <benm@google.com> | 2011-05-10 15:38:30 +0100 |
| commit | f05b935882198ccf7d81675736e3aeb089c5113a (patch) | |
| tree | 4ea0ca838d9ef1b15cf17ddb3928efb427c7e5a1 /JavaScriptCore/runtime/JSString.cpp | |
| parent | 60fbdcc62bced8db2cb1fd233cc4d1e4ea17db1b (diff) | |
| download | external_webkit-f05b935882198ccf7d81675736e3aeb089c5113a.zip external_webkit-f05b935882198ccf7d81675736e3aeb089c5113a.tar.gz external_webkit-f05b935882198ccf7d81675736e3aeb089c5113a.tar.bz2 | |
Merge WebKit at r74534: Initial merge by git.
Change-Id: I6ccd1154fa1b19c2ec2a66878eb675738735f1eb
Diffstat (limited to 'JavaScriptCore/runtime/JSString.cpp')
| -rw-r--r-- | JavaScriptCore/runtime/JSString.cpp | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/JavaScriptCore/runtime/JSString.cpp b/JavaScriptCore/runtime/JSString.cpp index 340a898..ba28139 100644 --- a/JavaScriptCore/runtime/JSString.cpp +++ b/JavaScriptCore/runtime/JSString.cpp @@ -31,6 +31,8 @@ #include "StringPrototype.h" namespace JSC { + +static const unsigned substringFromRopeCutoff = 4; // Overview: this methods converts a JSString from holding a string in rope form // down to a simple UString representation. It does so by building up the string @@ -105,6 +107,60 @@ void JSString::resolveRope(ExecState* exec) const } } } + +// This function construsts a substring out of a rope without flattening by reusing the existing fibers. +// This can reduce memory usage substantially. Since traversing ropes is slow the function will revert +// back to flattening if the rope turns out to be long. +JSString* JSString::substringFromRope(ExecState* exec, unsigned substringStart, unsigned substringLength) +{ + ASSERT(isRope()); + ASSERT(substringLength); + + JSGlobalData* globalData = &exec->globalData(); + + UString substringFibers[3]; + + unsigned fiberCount = 0; + unsigned substringFiberCount = 0; + unsigned substringEnd = substringStart + substringLength; + unsigned fiberEnd = 0; + + RopeIterator end; + for (RopeIterator it(m_other.m_fibers.data(), m_fiberCount); it != end; ++it) { + ++fiberCount; + StringImpl* fiberString = *it; + unsigned fiberStart = fiberEnd; + fiberEnd = fiberStart + fiberString->length(); + if (fiberEnd <= substringStart) + continue; + unsigned copyStart = std::max(substringStart, fiberStart); + unsigned copyEnd = std::min(substringEnd, fiberEnd); + if (copyStart == fiberStart && copyEnd == fiberEnd) + substringFibers[substringFiberCount++] = UString(fiberString); + else + substringFibers[substringFiberCount++] = UString(StringImpl::create(fiberString, copyStart - fiberStart, copyEnd - copyStart)); + if (fiberEnd >= substringEnd) + break; + if (fiberCount > substringFromRopeCutoff || substringFiberCount >= 3) { + // This turned out to be a really inefficient rope. Just flatten it. + resolveRope(exec); + return jsSubstring(&exec->globalData(), m_value, substringStart, substringLength); + } + } + ASSERT(substringFiberCount && substringFiberCount <= 3); + + if (substringLength == 1) { + ASSERT(substringFiberCount == 1); + UChar c = substringFibers[0].characters()[0]; + if (c <= 0xFF) + return globalData->smallStrings.singleCharacterString(globalData, c); + } + if (substringFiberCount == 1) + return new (globalData) JSString(globalData, substringFibers[0]); + if (substringFiberCount == 2) + return new (globalData) JSString(globalData, substringFibers[0], substringFibers[1]); + return new (globalData) JSString(globalData, substringFibers[0], substringFibers[1], substringFibers[2]); +} JSValue JSString::replaceCharacter(ExecState* exec, UChar character, const UString& replacement) { |
