Ignore:
Timestamp:
May 11, 2010, 11:42:46 AM (15 years ago)
Author:
[email protected]
Message:

Start using ropes in String.prototype.replace.

Reviewed by Oliver Hunt and Darin Adler.

1%-1.5% speedup on SunSpider.

  • runtime/JSString.cpp:

(JSC::JSString::resolveRope): Updated for RopeImpl refactoring.

(JSC::JSString::replaceCharacter): Added a replaceCharacter function, which creates
a rope for the resulting replacement.

  • runtime/JSString.h: A few changes here:

(JSC::):
(JSC::RopeBuilder::RopeIterator::RopeIterator):
(JSC::RopeBuilder::RopeIterator::operator++):
(JSC::RopeBuilder::RopeIterator::operator*):
(JSC::RopeBuilder::RopeIterator::operator!=):
(JSC::RopeBuilder::RopeIterator::WorkItem::WorkItem):
(JSC::RopeBuilder::RopeIterator::WorkItem::operator!=):
(JSC::RopeBuilder::RopeIterator::skipRopes): Created a RopeIterator abstraction.
We use this to do a substring find without having to resolve the rope.
(We could use this iterator when resolving ropes, too, but resolving
ropes backwards is usually more efficient.)

(JSC::RopeBuilder::JSString): Added constructors for 2 & 3 UStrings.

(JSC::RopeBuilder::appendValueInConstructAndIncrementLength):
(JSC::RopeBuilder::size): Updated for RopeImpl refactoring.

  • runtime/Operations.h: Updated for RopeImpl refactoring.

(JSC::jsString): Added jsString functions for 2 & 3 UStrings.

  • runtime/RopeImpl.cpp:

(JSC::RopeImpl::derefFibersNonRecursive):

  • runtime/RopeImpl.h:

(JSC::RopeImpl::initializeFiber):
(JSC::RopeImpl::size):
(JSC::RopeImpl::fibers):
(JSC::RopeImpl::deref):
(JSC::RopeImpl::RopeImpl): A little refactoring to make this patch easier:
Moved statics to the top of the class; put multi-statement functions on
multiple lines; renamed "fiberCount" to "size" to match other collections;
changed the "fibers" accessor to return the fibers buffer, instead of an
item in the buffer, to make iteration easier.

  • runtime/StringPrototype.cpp:

(JSC::stringProtoFuncReplace): Don't resolve a rope unless we need to. Do
use our new replaceCharacter function if possible. Do use a rope to
represent splicing three strings together.

File:
1 edited

Legend:

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

    r57912 r59161  
    7676            unsigned fiberCountMinusOne = rope->fiberCount() - 1;
    7777            for (unsigned i = 0; i < fiberCountMinusOne; ++i)
    78                 workQueue.append(rope->fibers(i));
    79             currentFiber = rope->fibers(fiberCountMinusOne);
     78                workQueue.append(rope->fibers()[i]);
     79            currentFiber = rope->fibers()[fiberCountMinusOne];
    8080        } else {
    8181            UStringImpl* string = static_cast<UStringImpl*>(currentFiber);
     
    105105}
    106106
     107JSValue JSString::replaceCharacter(ExecState* exec, UChar character, const UString& replacement)
     108{
     109    if (!isRope()) {
     110        size_t matchPosition = m_value.find(character);
     111        if (matchPosition == notFound)
     112            return JSValue(this);
     113        return jsString(exec, m_value.substr(0, matchPosition), replacement, m_value.substr(matchPosition + 1));
     114    }
     115
     116    RopeIterator end;
     117   
     118    // Count total fibers and find matching string.
     119    size_t fiberCount = 0;
     120    UStringImpl* matchString = 0;
     121    size_t matchPosition = notFound;
     122    for (RopeIterator it(m_other.m_fibers, m_fiberCount); it != end; ++it) {
     123        ++fiberCount;
     124        if (matchString)
     125            continue;
     126
     127        UStringImpl* string = *it;
     128        matchPosition = string->find(character);
     129        if (matchPosition == notFound)
     130            continue;
     131        matchString = string;
     132    }
     133
     134    if (!matchString)
     135        return this;
     136
     137    RopeBuilder builder(replacement.size() ? fiberCount + 2 : fiberCount + 1);
     138    if (UNLIKELY(builder.isOutOfMemory()))
     139        return throwOutOfMemoryError(exec);
     140
     141    for (RopeIterator it(m_other.m_fibers, m_fiberCount); it != end; ++it) {
     142        UStringImpl* string = *it;
     143        if (string != matchString) {
     144            builder.append(UString(string));
     145            continue;
     146        }
     147
     148        builder.append(UString(string).substr(0, matchPosition));
     149        if (replacement.size())
     150            builder.append(replacement);
     151        builder.append(UString(string).substr(matchPosition + 1));
     152    }
     153
     154    JSGlobalData* globalData = &exec->globalData();
     155    return JSValue(new (globalData) JSString(globalData, builder.release()));
     156}
     157
    107158JSString* JSString::getIndexSlowCase(ExecState* exec, unsigned i)
    108159{
Note: See TracChangeset for help on using the changeset viewer.