Ignore:
Timestamp:
Dec 7, 2010, 3:11:08 AM (14 years ago)
Author:
Antti Koivisto
Message:

https://bugs.webkit.org/show_bug.cgi?id=50412
http://www.wunderground.com/US/CA/Hayward.html causes big memory spike during page loading

Reviewed by Gavin Barraclough.

Creating a substring caused the original string be flattened if it was in the rope form. This could use
significant amount of memory by reducing buffer sharing between strings.

Add a rope specific substring function that constructs the substring by reusing the rope fibers
instead of flattening the rope.

No change observed in SunSpider.

  • runtime/JSString.cpp:

(JSC::JSString::substringFromRope):

  • runtime/JSString.h:

(JSC::jsSubstring):

  • runtime/StringPrototype.cpp:

(JSC::stringProtoFuncSubstr):
(JSC::stringProtoFuncSubstring):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/runtime/JSString.cpp

    r70496 r73433  
    3232
    3333namespace JSC {
     34   
     35static const unsigned substringFromRopeCutoff = 4;
    3436
    3537// Overview: this methods converts a JSString from holding a string in rope form
     
    106108    }
    107109}
     110   
     111// This function construsts a substring out of a rope without flattening by reusing the existing fibers.
     112// This can reduce memory usage substantially. Since traversing ropes is slow the function will revert
     113// back to flattening if the rope turns out to be long.
     114JSString* JSString::substringFromRope(ExecState* exec, unsigned substringStart, unsigned substringLength)
     115{
     116    ASSERT(isRope());
     117    ASSERT(substringLength);
     118   
     119    JSGlobalData* globalData = &exec->globalData();
     120
     121    UString substringFibers[3];
     122   
     123    unsigned fiberCount = 0;
     124    unsigned substringFiberCount = 0;
     125    unsigned substringEnd = substringStart + substringLength;
     126    unsigned fiberEnd = 0;
     127
     128    RopeIterator end;
     129    for (RopeIterator it(m_other.m_fibers.data(), m_fiberCount); it != end; ++it) {
     130        ++fiberCount;
     131        StringImpl* fiberString = *it;
     132        unsigned fiberStart = fiberEnd;
     133        fiberEnd = fiberStart + fiberString->length();
     134        if (fiberEnd <= substringStart)
     135            continue;
     136        unsigned copyStart = std::max(substringStart, fiberStart);
     137        unsigned copyEnd = std::min(substringEnd, fiberEnd);
     138        if (copyStart == fiberStart && copyEnd == fiberEnd)
     139            substringFibers[substringFiberCount++] = UString(fiberString);
     140        else
     141            substringFibers[substringFiberCount++] = UString(StringImpl::create(fiberString, copyStart - fiberStart, copyEnd - copyStart));
     142        if (fiberEnd >= substringEnd)
     143            break;
     144        if (fiberCount > substringFromRopeCutoff || substringFiberCount >= 3) {
     145            // This turned out to be a really inefficient rope. Just flatten it.
     146            resolveRope(exec);
     147            return jsSubstring(&exec->globalData(), m_value, substringStart, substringLength);
     148        }
     149    }
     150    ASSERT(substringFiberCount && substringFiberCount <= 3);
     151
     152    if (substringLength == 1) {
     153        ASSERT(substringFiberCount == 1);
     154        UChar c = substringFibers[0].characters()[0];
     155        if (c <= 0xFF)
     156            return globalData->smallStrings.singleCharacterString(globalData, c);
     157    }
     158    if (substringFiberCount == 1)
     159        return new (globalData) JSString(globalData, substringFibers[0]);
     160    if (substringFiberCount == 2)
     161        return new (globalData) JSString(globalData, substringFibers[0], substringFibers[1]);
     162    return new (globalData) JSString(globalData, substringFibers[0], substringFibers[1], substringFibers[2]);
     163}
    108164
    109165JSValue JSString::replaceCharacter(ExecState* exec, UChar character, const UString& replacement)
Note: See TracChangeset for help on using the changeset viewer.