Ignore:
Timestamp:
Jan 11, 2009, 7:19:23 PM (16 years ago)
Author:
Darin Adler
Message:

2009-01-11 David Levin <[email protected]>

Reviewed by Darin Adler.

https://bugs.webkit.org/show_bug.cgi?id=23175

Separate out BaseString information from UString::Rep and make all baseString access go through
a member function, so that it may be used for something else (in the future) in the BaseString
case.

  • runtime/SmallStrings.cpp: (JSC::SmallStringsStorage::rep): (JSC::SmallStringsStorage::SmallStringsStorage): (JSC::SmallStrings::SmallStrings): (JSC::SmallStrings::mark): Adjust to account for the changes in UString and put the UString in place in SmallStringsStorage to aid in locality of reference among the UChar[] and UString::Rep's.
  • runtime/SmallStrings.h:
  • runtime/UString.cpp: (JSC::initializeStaticBaseString): (JSC::initializeUString): (JSC::UString::Rep::create): (JSC::UString::Rep::destroy): (JSC::UString::Rep::checkConsistency): (JSC::expandCapacity): (JSC::UString::expandPreCapacity): (JSC::concatenate): (JSC::UString::append): (JSC::UString::operator=):
  • runtime/UString.h: (JSC::UString::Rep::baseIsSelf): (JSC::UString::Rep::setBaseString): (JSC::UString::Rep::baseString): (JSC::UString::Rep::): (JSC::UString::Rep::null): (JSC::UString::Rep::empty): (JSC::UString::Rep::data): (JSC::UString::cost): Separate out the items out used by base strings from those used in Rep's that only point to base strings. (This potentially saves 24 bytes per Rep.)
File:
1 edited

Legend:

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

    r39747 r39815  
    188188// reduce the possibility of it becoming zero due to ref/deref not being thread-safe.
    189189static UChar sharedEmptyChar;
    190 UString::Rep* UString::Rep::nullBaseString;
    191 UString::Rep* UString::Rep::emptyBaseString;
     190UString::BaseString* UString::Rep::nullBaseString;
     191UString::BaseString* UString::Rep::emptyBaseString;
    192192UString* UString::nullUString;
    193193
    194 void initializeStaticBaseString(int len, UChar* buf, UString::Rep& base)
     194void initializeStaticBaseString(int len, UChar* buf, UString::BaseString& base)
    195195{
    196196    base.offset = 0;
     
    199199    base._hash = 0;
    200200    base.m_identifierTableAndFlags.setFlag(UString::Rep::StaticFlag);
    201     base.baseString = &base;
     201    base.m_baseString = 0;
    202202    base.buf = buf;
    203203    base.preCapacity = 0;
     
    206206    base.usedCapacity = 0;
    207207    base.reportedCost = 0;
     208    base.checkConsistency();
    208209}
    209210
    210211void initializeUString()
    211212{
    212     UString::Rep::nullBaseString = new UString::Rep;
     213    UString::Rep::nullBaseString = new UString::BaseString;
    213214    initializeStaticBaseString(0, 0, *UString::Rep::nullBaseString);
    214215
    215     UString::Rep::emptyBaseString = new UString::Rep;
     216    UString::Rep::emptyBaseString = new UString::BaseString;
    216217    initializeStaticBaseString(0, &sharedEmptyChar, *UString::Rep::emptyBaseString);
    217218
     
    230231PassRefPtr<UString::Rep> UString::Rep::create(UChar* d, int l)
    231232{
    232     Rep* r = new Rep;
     233    BaseString* r = new BaseString;
    233234    r->offset = 0;
    234235    r->len = l;
    235236    r->rc = 1;
    236237    r->_hash = 0;
    237     r->baseString = r;
     238    r->m_baseString = 0;
    238239    r->reportedCost = 0;
    239240    r->buf = d;
     
    249250}
    250251
    251 PassRefPtr<UString::Rep> UString::Rep::create(PassRefPtr<Rep> base, int offset, int length)
    252 {
    253     ASSERT(base);
    254     base->checkConsistency();
    255 
    256     int baseOffset = base->offset;
    257 
    258     base = base->baseString;
    259 
    260     ASSERT(-(offset + baseOffset) <= base->usedPreCapacity);
    261     ASSERT(offset + baseOffset + length <= base->usedCapacity);
     252PassRefPtr<UString::Rep> UString::Rep::create(PassRefPtr<Rep> rep, int offset, int length)
     253{
     254    ASSERT(rep);
     255    rep->checkConsistency();
     256
     257    int repOffset = rep->offset;
     258
     259    PassRefPtr<BaseString> base = rep->baseString();
     260
     261    ASSERT(-(offset + repOffset) <= base->usedPreCapacity);
     262    ASSERT(offset + repOffset + length <= base->usedCapacity);
    262263
    263264    Rep* r = new Rep;
    264     r->offset = baseOffset + offset;
     265    r->offset = repOffset + offset;
    265266    r->len = length;
    266267    r->rc = 1;
    267268    r->_hash = 0;
    268     r->baseString = base.releaseRef();
    269     r->reportedCost = 0;
    270     r->buf = 0;
    271     r->usedCapacity = 0;
    272     r->capacity = 0;
    273     r->usedPreCapacity = 0;
    274     r->preCapacity = 0;
     269    r->setBaseString(base);
    275270
    276271    r->checkConsistency();
     
    303298        if (identifierTable())
    304299            Identifier::remove(this);
    305         if (baseString == this)
    306             fastFree(buf);
     300        UString::BaseString* base = baseString();
     301        if (base == this)
     302            fastFree(base->buf);
    307303        else
    308             baseString->deref();
     304            base->deref();
    309305
    310306        delete this;
     
    408404void UString::Rep::checkConsistency() const
    409405{
    410     // Only base strings have non-zero shared data.
    411     if (this != baseString) {
    412         ASSERT(!buf);
    413         ASSERT(!usedCapacity);
    414         ASSERT(!capacity);
    415         ASSERT(!usedPreCapacity);
    416         ASSERT(!preCapacity);
    417     }
     406    const UString::BaseString* base = baseString();
    418407
    419408    // There is no recursion for base strings.
    420     ASSERT(baseString == baseString->baseString);
     409    ASSERT(base == base->baseString());
    421410
    422411    if (isStatic()) {
     
    429418
    430419    // The string fits in buffer.
    431     ASSERT(baseString->usedPreCapacity <= baseString->preCapacity);
    432     ASSERT(baseString->usedCapacity <= baseString->capacity);
    433     ASSERT(-offset <= baseString->usedPreCapacity);
    434     ASSERT(offset + len <= baseString->usedCapacity);
     420    ASSERT(base->usedPreCapacity <= base->preCapacity);
     421    ASSERT(base->usedCapacity <= base->capacity);
     422    ASSERT(-offset <= base->usedPreCapacity);
     423    ASSERT(offset + len <= base->usedCapacity);
    435424}
    436425#endif
     
    452441}
    453442
    454 inline int UString::usedCapacity() const
    455 {
    456     return m_rep->baseString->usedCapacity;
    457 }
    458 
    459 inline int UString::usedPreCapacity() const
    460 {
    461     return m_rep->baseString->usedPreCapacity;
    462 }
    463 
    464 
    465443static inline bool expandCapacity(UString::Rep* rep, int requiredLength)
    466444{
    467445    rep->checkConsistency();
    468446
    469     UString::Rep* r = rep->baseString;
    470 
    471     if (requiredLength > r->capacity) {
    472         size_t newCapacity = expandedSize(requiredLength, r->preCapacity);
    473         UChar* oldBuf = r->buf;
    474         r->buf = reallocChars(r->buf, newCapacity);
    475         if (!r->buf) {
    476             r->buf = oldBuf;
     447    UString::BaseString* base = rep->baseString();
     448
     449    if (requiredLength > base->capacity) {
     450        size_t newCapacity = expandedSize(requiredLength, base->preCapacity);
     451        UChar* oldBuf = base->buf;
     452        base->buf = reallocChars(base->buf, newCapacity);
     453        if (!base->buf) {
     454            base->buf = oldBuf;
    477455            return false;
    478456        }
    479         r->capacity = newCapacity - r->preCapacity;
    480     }
    481     if (requiredLength > r->usedCapacity)
    482         r->usedCapacity = requiredLength;
     457        base->capacity = newCapacity - base->preCapacity;
     458    }
     459    if (requiredLength > base->usedCapacity)
     460        base->usedCapacity = requiredLength;
    483461
    484462    rep->checkConsistency();
     
    496474    m_rep->checkConsistency();
    497475
    498     Rep* r = m_rep->baseString;
    499 
    500     if (requiredPreCap > r->preCapacity) {
    501         size_t newCapacity = expandedSize(requiredPreCap, r->capacity);
    502         int delta = newCapacity - r->capacity - r->preCapacity;
     476    BaseString* base = m_rep->baseString();
     477
     478    if (requiredPreCap > base->preCapacity) {
     479        size_t newCapacity = expandedSize(requiredPreCap, base->capacity);
     480        int delta = newCapacity - base->capacity - base->preCapacity;
    503481
    504482        UChar* newBuf = allocChars(newCapacity);
     
    507485            return;
    508486        }
    509         copyChars(newBuf + delta, r->buf, r->capacity + r->preCapacity);
    510         fastFree(r->buf);
    511         r->buf = newBuf;
    512 
    513         r->preCapacity = newCapacity - r->capacity;
    514     }
    515     if (requiredPreCap > r->usedPreCapacity)
    516         r->usedPreCapacity = requiredPreCap;
     487        copyChars(newBuf + delta, base->buf, base->capacity + base->preCapacity);
     488        fastFree(base->buf);
     489        base->buf = newBuf;
     490
     491        base->preCapacity = newCapacity - base->capacity;
     492    }
     493    if (requiredPreCap > base->usedPreCapacity)
     494        base->usedPreCapacity = requiredPreCap;
    517495
    518496    m_rep->checkConsistency();
     
    579557    int thisOffset = rep->offset;
    580558    int length = thisSize + tSize;
     559    UString::BaseString* base = rep->baseString();
    581560
    582561    // possible cases:
     
    586565        // this is empty
    587566        rep = UString::Rep::createCopying(tData, tSize);
    588     } else if (rep->baseIsSelf() && rep->rc == 1) {
     567    } else if (rep == base && rep->rc == 1) {
    589568        // this is direct and has refcount of 1 (so we can just alter it directly)
    590569        if (!expandCapacity(rep.get(), thisOffset + length))
     
    595574            rep->_hash = 0;
    596575        }
    597     } else if (thisOffset + thisSize == rep->baseString->usedCapacity && thisSize >= minShareSize) {
     576    } else if (thisOffset + thisSize == base->usedCapacity && thisSize >= minShareSize) {
    598577        // this reaches the end of the buffer - extend it if it's long enough to append to
    599578        if (!expandCapacity(rep.get(), thisOffset + length))
     
    613592            copyChars(d + thisSize, tData, tSize);
    614593            rep = UString::Rep::create(d, length);
    615             rep->capacity = newCapacity;
     594            rep->baseString()->capacity = newCapacity;
    616595        }
    617596    }
     
    632611    int tSize = static_cast<int>(strlen(t));
    633612    int length = thisSize + tSize;
     613    UString::BaseString* base = rep->baseString();
    634614
    635615    // possible cases:
     
    639619    } else if (tSize == 0) {
    640620        // t is empty, we'll just return *this below.
    641     } else if (rep->baseIsSelf() && rep->rc == 1) {
     621    } else if (rep == base && rep->rc == 1) {
    642622        // this is direct and has refcount of 1 (so we can just alter it directly)
    643623        expandCapacity(rep.get(), thisOffset + length);
     
    649629            rep->_hash = 0;
    650630        }
    651     } else if (thisOffset + thisSize == rep->baseString->usedCapacity && thisSize >= minShareSize) {
     631    } else if (thisOffset + thisSize == base->usedCapacity && thisSize >= minShareSize) {
    652632        // this string reaches the end of the buffer - extend it
    653633        expandCapacity(rep.get(), thisOffset + length);
     
    669649                d[thisSize + i] = static_cast<unsigned char>(t[i]); // use unsigned char to zero-extend instead of sign-extend
    670650            rep = UString::Rep::create(d, length);
    671             rep->capacity = newCapacity;
     651            rep->baseString()->capacity = newCapacity;
    672652        }
    673653    }
     
    698678        return a;
    699679
    700     if (bSize == 1 && aOffset + aSize == a->baseString->usedCapacity && aOffset + length <= a->baseString->capacity) {
     680    UString::BaseString* aBase = a->baseString();
     681    if (bSize == 1 && aOffset + aSize == aBase->usedCapacity && aOffset + length <= aBase->capacity) {
    701682        // b is a single character (common fast case)
    702         a->baseString->usedCapacity = aOffset + length;
     683        aBase->usedCapacity = aOffset + length;
    703684        a->data()[aSize] = b->data()[0];
    704685        return UString::Rep::create(a, 0, length);
    705686    }
    706687
    707     if (aOffset + aSize == a->baseString->usedCapacity && aSize >= minShareSize && 4 * aSize >= bSize &&
    708                (-bOffset != b->baseString->usedPreCapacity || aSize >= bSize)) {
     688    UString::BaseString* bBase = b->baseString();
     689    if (aOffset + aSize == aBase->usedCapacity && aSize >= minShareSize && 4 * aSize >= bSize
     690        && (-bOffset != bBase->usedPreCapacity || aSize >= bSize)) {
    709691        // - a reaches the end of its buffer so it qualifies for shared append
    710692        // - also, it's at least a quarter the length of b - appending to a much shorter
     
    725707    }
    726708
    727     if (-bOffset == b->baseString->usedPreCapacity && bSize >= minShareSize && 4 * bSize >= aSize) {
     709    if (-bOffset == bBase->usedPreCapacity && bSize >= minShareSize && 4 * bSize >= aSize) {
    728710        // - b reaches the beginning of its buffer so it qualifies for shared prepend
    729711        // - also, it's at least a quarter the length of a - prepending to a much shorter
     
    751733    copyChars(d + aSize, b->data(), bSize);
    752734    PassRefPtr<UString::Rep> result = UString::Rep::create(d, length);
    753     result->capacity = newCapacity;
     735    result->baseString()->capacity = newCapacity;
    754736
    755737    a->checkConsistency();
     
    10521034    int tSize = t.size();
    10531035    int length = thisSize + tSize;
     1036    BaseString* base = m_rep->baseString();
    10541037
    10551038    // possible cases:
     
    10591042    } else if (tSize == 0) {
    10601043        // t is empty
    1061     } else if (m_rep->baseIsSelf() && m_rep->rc == 1) {
     1044    } else if (m_rep == base && m_rep->rc == 1) {
    10621045        // this is direct and has refcount of 1 (so we can just alter it directly)
    10631046        expandCapacity(thisOffset + length);
     
    10671050            m_rep->_hash = 0;
    10681051        }
    1069     } else if (thisOffset + thisSize == usedCapacity() && thisSize >= minShareSize) {
     1052    } else if (thisOffset + thisSize == base->usedCapacity && thisSize >= minShareSize) {
    10701053        // this reaches the end of the buffer - extend it if it's long enough to append to
    10711054        expandCapacity(thisOffset + length);
     
    10841067            copyChars(d + thisSize, t.data(), tSize);
    10851068            m_rep = Rep::create(d, length);
    1086             m_rep->capacity = newCapacity;
     1069            m_rep->baseString()->capacity = newCapacity;
    10871070        }
    10881071    }
     
    11121095    int thisOffset = m_rep->offset;
    11131096    int length = size();
     1097    BaseString* base = m_rep->baseString();
    11141098
    11151099    // possible cases:
     
    11231107            d[0] = c;
    11241108            m_rep = Rep::create(d, 1);
    1125             m_rep->capacity = newCapacity;
    1126         }
    1127     } else if (m_rep->baseIsSelf() && m_rep->rc == 1) {
     1109            m_rep->baseString()->capacity = newCapacity;
     1110        }
     1111    } else if (m_rep == base && m_rep->rc == 1) {
    11281112        // this is direct and has refcount of 1 (so we can just alter it directly)
    11291113        expandCapacity(thisOffset + length + 1);
     
    11341118            m_rep->_hash = 0;
    11351119        }
    1136     } else if (thisOffset + length == usedCapacity() && length >= minShareSize) {
     1120    } else if (thisOffset + length == base->usedCapacity && length >= minShareSize) {
    11371121        // this reaches the end of the string - extend it and share
    11381122        expandCapacity(thisOffset + length + 1);
     
    11521136            d[length] = c;
    11531137            m_rep = Rep::create(d, length + 1);
    1154             m_rep->capacity = newCapacity;
     1138            m_rep->baseString()->capacity = newCapacity;
    11551139        }
    11561140    }
     
    12181202    int l = static_cast<int>(strlen(c));
    12191203    UChar* d;
    1220     if (m_rep->rc == 1 && l <= m_rep->capacity && m_rep->baseIsSelf() && m_rep->offset == 0 && m_rep->preCapacity == 0) {
    1221         d = m_rep->buf;
     1204    BaseString* base = m_rep->baseString();
     1205    if (m_rep->rc == 1 && l <= base->capacity && m_rep == base && m_rep->offset == 0 && base->preCapacity == 0) {
     1206        d = base->buf;
    12221207        m_rep->_hash = 0;
    12231208        m_rep->len = l;
Note: See TracChangeset for help on using the changeset viewer.