Changeset 54804 in webkit for trunk/JavaScriptCore/runtime


Ignore:
Timestamp:
Feb 15, 2010, 5:32:06 PM (15 years ago)
Author:
[email protected]
Message:

Some general Rope related refactoring.

Reviewed by Oliver Hunt.

Rename Rope::m_ropeLength to m_fiberCount, to be more descriptive.
Rename Rope::m_stringLength to simply m_length (since this is the
more conventional name for the length of a string). Move append
behaviour out into a new RopeBuilder class, so that Rope no longer
needs any knowledge of the JSString or UString implementation.

Make Rope no longer be nested within JSString.
(Rope now no-longer need reside within JSString.h, but leaving
the change of moving this out to a different header as a separate
change from these renames).

(JSC::JIT::privateCompileCTIMachineTrampolines):

  • runtime/JSString.cpp:

(JSC::Rope::destructNonRecursive):
(JSC::Rope::~Rope):
(JSC::JSString::resolveRope):
(JSC::JSString::toBoolean):
(JSC::JSString::getStringPropertyDescriptor):

  • runtime/JSString.h:

(JSC::Rope::Fiber::Fiber):
(JSC::Rope::Fiber::deref):
(JSC::Rope::Fiber::ref):
(JSC::Rope::Fiber::refAndGetLength):
(JSC::Rope::Fiber::isRope):
(JSC::Rope::Fiber::rope):
(JSC::Rope::Fiber::isString):
(JSC::Rope::Fiber::string):
(JSC::Rope::Fiber::nonFiber):
(JSC::Rope::tryCreateUninitialized):
(JSC::Rope::append):
(JSC::Rope::fiberCount):
(JSC::Rope::length):
(JSC::Rope::fibers):
(JSC::Rope::Rope):
(JSC::Rope::operator new):
(JSC::):
(JSC::RopeBuilder::JSString):
(JSC::RopeBuilder::~JSString):
(JSC::RopeBuilder::length):
(JSC::RopeBuilder::canGetIndex):
(JSC::RopeBuilder::appendStringInConstruct):
(JSC::RopeBuilder::appendValueInConstructAndIncrementLength):
(JSC::RopeBuilder::isRope):
(JSC::RopeBuilder::fiberCount):
(JSC::JSString::getStringPropertySlot):

  • runtime/Operations.h:

(JSC::jsString):

Location:
trunk/JavaScriptCore/runtime
Files:
3 edited

Legend:

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

    r53371 r54804  
    3232namespace JSC {
    3333
    34 void JSString::Rope::destructNonRecursive()
     34void Rope::destructNonRecursive()
    3535{
    3636    Vector<Rope*, 32> workQueue;
     
    3838
    3939    while (true) {
    40         unsigned length = rope->ropeLength();
     40        unsigned length = rope->fiberCount();
    4141        for (unsigned i = 0; i < length; ++i) {
    4242            Fiber& fiber = rope->fibers(i);
     
    6262}
    6363
    64 JSString::Rope::~Rope()
     64Rope::~Rope()
    6565{
    6666    destructNonRecursive();
     
    8383    // Allocate the buffer to hold the final string, position initially points to the end.
    8484    UChar* buffer;
    85     if (PassRefPtr<UStringImpl> newImpl = UStringImpl::tryCreateUninitialized(m_stringLength, buffer))
     85    if (PassRefPtr<UStringImpl> newImpl = UStringImpl::tryCreateUninitialized(m_length, buffer))
    8686        m_value = newImpl;
    8787    else {
    88         for (unsigned i = 0; i < m_ropeLength; ++i) {
     88        for (unsigned i = 0; i < m_fiberCount; ++i) {
    8989            m_fibers[i].deref();
    9090            m_fibers[i] = static_cast<void*>(0);
    9191        }
    92         m_ropeLength = 0;
     92        m_fiberCount = 0;
    9393        ASSERT(!isRope());
    9494        ASSERT(m_value == UString());
     
    9696        return;
    9797    }
    98     UChar* position = buffer + m_stringLength;
     98    UChar* position = buffer + m_length;
    9999
    100100    // Start with the current Rope.
    101101    Vector<Rope::Fiber, 32> workQueue;
    102102    Rope::Fiber currentFiber;
    103     for (unsigned i = 0; i < (m_ropeLength - 1); ++i)
     103    for (unsigned i = 0; i < (m_fiberCount - 1); ++i)
    104104        workQueue.append(m_fibers[i]);
    105     currentFiber = m_fibers[m_ropeLength - 1];
     105    currentFiber = m_fibers[m_fiberCount - 1];
    106106    while (true) {
    107107        if (currentFiber.isRope()) {
     
    109109            // Copy the contents of the current rope into the workQueue, with the last item in 'currentFiber'
    110110            // (we will be working backwards over the rope).
    111             unsigned ropeLengthMinusOne = rope->ropeLength() - 1;
    112             for (unsigned i = 0; i < ropeLengthMinusOne; ++i)
     111            unsigned fiberCountMinusOne = rope->fiberCount() - 1;
     112            for (unsigned i = 0; i < fiberCountMinusOne; ++i)
    113113                workQueue.append(rope->fibers(i));
    114             currentFiber = rope->fibers(ropeLengthMinusOne);
     114            currentFiber = rope->fibers(fiberCountMinusOne);
    115115        } else {
    116116            UString::Rep* string = currentFiber.string();
     
    123123                // Create a string from the UChar buffer, clear the rope RefPtr.
    124124                ASSERT(buffer == position);
    125                 for (unsigned i = 0; i < m_ropeLength; ++i) {
     125                for (unsigned i = 0; i < m_fiberCount; ++i) {
    126126                    m_fibers[i].deref();
    127127                    m_fibers[i] = static_cast<void*>(0);
    128128                }
    129                 m_ropeLength = 0;
     129                m_fiberCount = 0;
    130130
    131131                ASSERT(!isRope());
     
    154154bool JSString::toBoolean(ExecState*) const
    155155{
    156     return m_stringLength;
     156    return m_length;
    157157}
    158158
     
    216216{
    217217    if (propertyName == exec->propertyNames().length) {
    218         descriptor.setDescriptor(jsNumber(exec, m_stringLength), DontEnum | DontDelete | ReadOnly);
     218        descriptor.setDescriptor(jsNumber(exec, m_length), DontEnum | DontDelete | ReadOnly);
    219219        return true;
    220220    }
     
    222222    bool isStrictUInt32;
    223223    unsigned i = propertyName.toStrictUInt32(&isStrictUInt32);
    224     if (isStrictUInt32 && i < m_stringLength) {
     224    if (isStrictUInt32 && i < m_length) {
    225225        descriptor.setDescriptor(jsSingleCharacterSubstring(exec, value(exec), i), DontDelete | ReadOnly);
    226226        return true;
  • trunk/JavaScriptCore/runtime/JSString.h

    r54545 r54804  
    3333namespace JSC {
    3434
     35    // FIXME: this class is on its way out into a different header.
     36    class Rope : public RefCounted<Rope> {
     37    public:
     38        // A Rope is composed from a set of smaller strings called Fibers.
     39        // Each Fiber in a rope is either UString::Rep or another Rope.
     40        class Fiber {
     41        public:
     42            Fiber() : m_value(0) {}
     43            Fiber(UString::Rep* string) : m_value(reinterpret_cast<intptr_t>(string)) {}
     44            Fiber(Rope* rope) : m_value(reinterpret_cast<intptr_t>(rope) | 1) {}
     45
     46            Fiber(void* nonFiber) : m_value(reinterpret_cast<intptr_t>(nonFiber)) {}
     47
     48            void deref()
     49            {
     50                if (isRope())
     51                    rope()->deref();
     52                else
     53                    string()->deref();
     54            }
     55
     56            Fiber& ref()
     57            {
     58                if (isString())
     59                    string()->ref();
     60                else
     61                    rope()->ref();
     62                return *this;
     63            }
     64
     65            unsigned refAndGetLength()
     66            {
     67                if (isString()) {
     68                    UString::Rep* rep = string();
     69                    return rep->ref()->size();
     70                } else {
     71                    Rope* r = rope();
     72                    r->ref();
     73                    return r->length();
     74                }
     75            }
     76
     77            bool isRope() { return m_value & 1; }
     78            Rope* rope() { return reinterpret_cast<Rope*>(m_value & ~1); }
     79            bool isString() { return !isRope(); }
     80            UString::Rep* string() { return reinterpret_cast<UString::Rep*>(m_value); }
     81
     82            void* nonFiber() { return reinterpret_cast<void*>(m_value); }
     83        private:
     84            intptr_t m_value;
     85        };
     86
     87        // Creates a Rope comprising of 'fiberCount' Fibers.
     88        // The Rope is constructed in an uninitialized state - initialize must be called for each Fiber in the Rope.
     89        static PassRefPtr<Rope> tryCreateUninitialized(unsigned fiberCount)
     90        {
     91            void* allocation;
     92            if (tryFastMalloc(sizeof(Rope) + (fiberCount - 1) * sizeof(Fiber)).getValue(allocation))
     93                return adoptRef(new (allocation) Rope(fiberCount));
     94            return 0;
     95        }
     96
     97        ~Rope();
     98        void destructNonRecursive();
     99
     100        void initializeFiber(unsigned &index, Fiber& fiber)
     101        {
     102            m_fibers[index++] = fiber;
     103            m_length += fiber.refAndGetLength();
     104        }
     105        void initializeFiber(unsigned &index, UStringImpl* impl)
     106        {
     107            m_fibers[index++] = Fiber(impl);
     108            m_length += impl->ref()->size();
     109        }
     110
     111        unsigned fiberCount() { return m_fiberCount; }
     112        unsigned length() { return m_length; }
     113        Fiber& fibers(unsigned index) { return m_fibers[index]; }
     114
     115    private:
     116        Rope(unsigned fiberCount) : m_fiberCount(fiberCount), m_length(0) {}
     117        void* operator new(size_t, void* inPlace) { return inPlace; }
     118       
     119        unsigned m_fiberCount;
     120        unsigned m_length;
     121        Fiber m_fibers[1];
     122    };
     123
    35124    class JSString;
    36125
     
    68157        friend class JSGlobalData;
    69158
    70         // A Rope is a string composed of a set of substrings.
    71         class Rope : public RefCounted<Rope> {
     159        class RopeBuilder {
    72160        public:
    73             // A Rope is composed from a set of smaller strings called Fibers.
    74             // Each Fiber in a rope is either UString::Rep or another Rope.
    75             class Fiber {
    76             public:
    77                 Fiber() : m_value(0) {}
    78                 Fiber(UString::Rep* string) : m_value(reinterpret_cast<intptr_t>(string)) {}
    79                 Fiber(Rope* rope) : m_value(reinterpret_cast<intptr_t>(rope) | 1) {}
    80 
    81                 Fiber(void* nonFiber) : m_value(reinterpret_cast<intptr_t>(nonFiber)) {}
    82 
    83                 void deref()
    84                 {
    85                     if (isRope())
    86                         rope()->deref();
    87                     else
    88                         string()->deref();
    89                 }
    90 
    91                 Fiber& ref()
    92                 {
    93                     if (isString())
    94                         string()->ref();
    95                     else
    96                         rope()->ref();
    97                     return *this;
    98                 }
    99 
    100                 unsigned refAndGetLength()
    101                 {
    102                     if (isString()) {
    103                         UString::Rep* rep = string();
    104                         return rep->ref()->size();
    105                     } else {
    106                         Rope* r = rope();
    107                         r->ref();
    108                         return r->stringLength();
    109                     }
    110                 }
    111 
    112                 bool isRope() { return m_value & 1; }
    113                 Rope* rope() { return reinterpret_cast<Rope*>(m_value & ~1); }
    114                 bool isString() { return !isRope(); }
    115                 UString::Rep* string() { return reinterpret_cast<UString::Rep*>(m_value); }
    116 
    117                 void* nonFiber() { return reinterpret_cast<void*>(m_value); }
    118             private:
    119                 intptr_t m_value;
    120             };
    121 
    122             // Creates a Rope comprising of 'ropeLength' Fibers.
    123             // The Rope is constructed in an uninitialized state - initialize must be called for each Fiber in the Rope.
    124             static PassRefPtr<Rope> createOrNull(unsigned ropeLength)
    125             {
    126                 void* allocation;
    127                 if (tryFastMalloc(sizeof(Rope) + (ropeLength - 1) * sizeof(Fiber)).getValue(allocation))
    128                     return adoptRef(new (allocation) Rope(ropeLength));
    129                 return 0;
    130             }
    131 
    132             ~Rope();
    133             void destructNonRecursive();
    134 
    135             void append(unsigned &index, Fiber& fiber)
    136             {
    137                 m_fibers[index++] = fiber;
    138                 m_stringLength += fiber.refAndGetLength();
    139             }
    140             void append(unsigned &index, const UString& string)
    141             {
    142                 UString::Rep* rep = string.rep();
    143                 m_fibers[index++] = Fiber(rep);
    144                 m_stringLength += rep->ref()->size();
    145             }
    146             void append(unsigned& index, JSString* jsString)
     161            RopeBuilder(unsigned fiberCount)
     162                : m_index(0)
     163                , m_rope(Rope::tryCreateUninitialized(fiberCount))
     164            {
     165            }
     166
     167            bool isOutOfMemory() { return !m_rope; }
     168
     169            void append(Rope::Fiber& fiber)
     170            {
     171                ASSERT(m_rope);
     172                m_rope->initializeFiber(m_index, fiber);
     173            }
     174            void append(const UString& string)
     175            {
     176                ASSERT(m_rope);
     177                m_rope->initializeFiber(m_index, string.rep());
     178            }
     179            void append(JSString* jsString)
    147180            {
    148181                if (jsString->isRope()) {
    149                     for (unsigned i = 0; i < jsString->m_ropeLength; ++i)
    150                         append(index, jsString->m_fibers[i]);
     182                    for (unsigned i = 0; i < jsString->m_fiberCount; ++i)
     183                        append(jsString->m_fibers[i]);
    151184                } else
    152                     append(index, jsString->string());
    153             }
    154 
    155             unsigned ropeLength() { return m_ropeLength; }
    156             unsigned stringLength() { return m_stringLength; }
    157             Fiber& fibers(unsigned index) { return m_fibers[index]; }
     185                    append(jsString->string());
     186            }
     187
     188            PassRefPtr<Rope> release()
     189            {
     190                ASSERT(m_index == m_rope->fiberCount());
     191                return m_rope.release();
     192            }
    158193
    159194        private:
    160             Rope(unsigned ropeLength) : m_ropeLength(ropeLength), m_stringLength(0) {}
    161             void* operator new(size_t, void* inPlace) { return inPlace; }
    162            
    163             unsigned m_ropeLength;
    164             unsigned m_stringLength;
    165             Fiber m_fibers[1];
     195            unsigned m_index;
     196            RefPtr<Rope> m_rope;
    166197        };
    167198
    168199        ALWAYS_INLINE JSString(JSGlobalData* globalData, const UString& value)
    169200            : JSCell(globalData->stringStructure.get())
    170             , m_stringLength(value.size())
     201            , m_length(value.size())
    171202            , m_value(value)
    172             , m_ropeLength(0)
     203            , m_fiberCount(0)
    173204        {
    174205            Heap::heap(this)->reportExtraMemoryCost(value.cost());
     
    178209        JSString(JSGlobalData* globalData, const UString& value, HasOtherOwnerType)
    179210            : JSCell(globalData->stringStructure.get())
    180             , m_stringLength(value.size())
     211            , m_length(value.size())
    181212            , m_value(value)
    182             , m_ropeLength(0)
     213            , m_fiberCount(0)
    183214        {
    184215        }
    185216        JSString(JSGlobalData* globalData, PassRefPtr<UString::Rep> value, HasOtherOwnerType)
    186217            : JSCell(globalData->stringStructure.get())
    187             , m_stringLength(value->size())
     218            , m_length(value->size())
    188219            , m_value(value)
    189             , m_ropeLength(0)
    190         {
    191         }
    192         JSString(JSGlobalData* globalData, PassRefPtr<JSString::Rope> rope)
    193             : JSCell(globalData->stringStructure.get())
    194             , m_stringLength(rope->stringLength())
    195             , m_ropeLength(1)
     220            , m_fiberCount(0)
     221        {
     222        }
     223        JSString(JSGlobalData* globalData, PassRefPtr<Rope> rope)
     224            : JSCell(globalData->stringStructure.get())
     225            , m_length(rope->length())
     226            , m_fiberCount(1)
    196227        {
    197228            m_fibers[0] = rope.releaseRef();
    198229        }
    199230        // This constructor constructs a new string by concatenating s1 & s2.
    200         // This should only be called with ropeLength <= 3.
    201         JSString(JSGlobalData* globalData, unsigned ropeLength, JSString* s1, JSString* s2)
    202             : JSCell(globalData->stringStructure.get())
    203             , m_stringLength(s1->length() + s2->length())
    204             , m_ropeLength(ropeLength)
    205         {
    206             ASSERT(ropeLength <= s_maxInternalRopeLength);
     231        // This should only be called with fiberCount <= 3.
     232        JSString(JSGlobalData* globalData, unsigned fiberCount, JSString* s1, JSString* s2)
     233            : JSCell(globalData->stringStructure.get())
     234            , m_length(s1->length() + s2->length())
     235            , m_fiberCount(fiberCount)
     236        {
     237            ASSERT(fiberCount <= s_maxInternalRopeLength);
    207238            unsigned index = 0;
    208239            appendStringInConstruct(index, s1);
    209240            appendStringInConstruct(index, s2);
    210             ASSERT(ropeLength == index);
     241            ASSERT(fiberCount == index);
    211242        }
    212243        // This constructor constructs a new string by concatenating s1 & s2.
    213         // This should only be called with ropeLength <= 3.
    214         JSString(JSGlobalData* globalData, unsigned ropeLength, JSString* s1, const UString& u2)
    215             : JSCell(globalData->stringStructure.get())
    216             , m_stringLength(s1->length() + u2.size())
    217             , m_ropeLength(ropeLength)
    218         {
    219             ASSERT(ropeLength <= s_maxInternalRopeLength);
     244        // This should only be called with fiberCount <= 3.
     245        JSString(JSGlobalData* globalData, unsigned fiberCount, JSString* s1, const UString& u2)
     246            : JSCell(globalData->stringStructure.get())
     247            , m_length(s1->length() + u2.size())
     248            , m_fiberCount(fiberCount)
     249        {
     250            ASSERT(fiberCount <= s_maxInternalRopeLength);
    220251            unsigned index = 0;
    221252            appendStringInConstruct(index, s1);
    222253            appendStringInConstruct(index, u2);
    223             ASSERT(ropeLength == index);
     254            ASSERT(fiberCount == index);
    224255        }
    225256        // This constructor constructs a new string by concatenating s1 & s2.
    226         // This should only be called with ropeLength <= 3.
    227         JSString(JSGlobalData* globalData, unsigned ropeLength, const UString& u1, JSString* s2)
    228             : JSCell(globalData->stringStructure.get())
    229             , m_stringLength(u1.size() + s2->length())
    230             , m_ropeLength(ropeLength)
    231         {
    232             ASSERT(ropeLength <= s_maxInternalRopeLength);
     257        // This should only be called with fiberCount <= 3.
     258        JSString(JSGlobalData* globalData, unsigned fiberCount, const UString& u1, JSString* s2)
     259            : JSCell(globalData->stringStructure.get())
     260            , m_length(u1.size() + s2->length())
     261            , m_fiberCount(fiberCount)
     262        {
     263            ASSERT(fiberCount <= s_maxInternalRopeLength);
    233264            unsigned index = 0;
    234265            appendStringInConstruct(index, u1);
    235266            appendStringInConstruct(index, s2);
    236             ASSERT(ropeLength == index);
     267            ASSERT(fiberCount == index);
    237268        }
    238269        // This constructor constructs a new string by concatenating v1, v2 & v3.
    239         // This should only be called with ropeLength <= 3 ... which since every
    240         // value must require a ropeLength of at least one implies that the length
     270        // This should only be called with fiberCount <= 3 ... which since every
     271        // value must require a fiberCount of at least one implies that the length
    241272        // for each value must be exactly 1!
    242273        JSString(ExecState* exec, JSValue v1, JSValue v2, JSValue v3)
    243274            : JSCell(exec->globalData().stringStructure.get())
    244             , m_stringLength(0)
    245             , m_ropeLength(s_maxInternalRopeLength)
     275            , m_length(0)
     276            , m_fiberCount(s_maxInternalRopeLength)
    246277        {
    247278            unsigned index = 0;
     
    254285        JSString(JSGlobalData* globalData, const UString& value, JSStringFinalizerCallback finalizer, void* context)
    255286            : JSCell(globalData->stringStructure.get())
    256             , m_stringLength(value.size())
     287            , m_length(value.size())
    257288            , m_value(value)
    258             , m_ropeLength(0)
     289            , m_fiberCount(0)
    259290        {
    260291            // nasty hack because we can't union non-POD types
     
    267298        {
    268299            ASSERT(vptr() == JSGlobalData::jsStringVPtr);
    269             for (unsigned i = 0; i < m_ropeLength; ++i)
     300            for (unsigned i = 0; i < m_fiberCount; ++i)
    270301                m_fibers[i].deref();
    271302
    272             if (!m_ropeLength && m_fibers[0].nonFiber()) {
     303            if (!m_fiberCount && m_fibers[0].nonFiber()) {
    273304                JSStringFinalizerCallback finalizer = reinterpret_cast<JSStringFinalizerCallback>(m_fibers[0].nonFiber());
    274305                finalizer(this, m_fibers[1].nonFiber());
     
    289320            return m_value;
    290321        }
    291         unsigned length() { return m_stringLength; }
     322        unsigned length() { return m_length; }
    292323
    293324        bool getStringPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
     
    295326        bool getStringPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor&);
    296327
    297         bool canGetIndex(unsigned i) { return i < m_stringLength; }
     328        bool canGetIndex(unsigned i) { return i < m_length; }
    298329        JSString* getIndex(ExecState*, unsigned);
    299330
     
    304335        JSString(VPtrStealingHackType)
    305336            : JSCell(0)
    306             , m_ropeLength(0)
     337            , m_fiberCount(0)
    307338        {
    308339        }
     
    318349        {
    319350            if (jsString->isRope()) {
    320                 for (unsigned i = 0; i < jsString->m_ropeLength; ++i)
     351                for (unsigned i = 0; i < jsString->m_fiberCount; ++i)
    321352                    m_fibers[index++] = jsString->m_fibers[i].ref();
    322353            } else
     
    329360                ASSERT(asCell(v)->isString());
    330361                JSString* s = static_cast<JSString*>(asCell(v));
    331                 ASSERT(s->ropeLength() == 1);
     362                ASSERT(s->fiberCount() == 1);
    332363                appendStringInConstruct(index, s);
    333                 m_stringLength += s->length();
     364                m_length += s->length();
    334365            } else {
    335366                UString u(v.toString(exec));
    336367                m_fibers[index++] = Rope::Fiber(u.rep()->ref());
    337                 m_stringLength += u.size();
     368                m_length += u.size();
    338369            }
    339370        }
     
    358389
    359390        // A string is represented either by a UString or a Rope.
    360         unsigned m_stringLength;
     391        unsigned m_length;
    361392        mutable UString m_value;
    362         mutable unsigned m_ropeLength;
     393        mutable unsigned m_fiberCount;
    363394        mutable Rope::Fiber m_fibers[s_maxInternalRopeLength];
    364395
    365         bool isRope() const { return m_ropeLength; }
     396        bool isRope() const { return m_fiberCount; }
    366397        UString& string() { ASSERT(!isRope()); return m_value; }
    367         unsigned ropeLength() { return m_ropeLength ? m_ropeLength : 1; }
     398        unsigned fiberCount() { return m_fiberCount ? m_fiberCount : 1; }
    368399
    369400        friend JSValue jsString(ExecState* exec, JSString* s1, JSString* s2);
     
    494525    {
    495526        if (propertyName == exec->propertyNames().length) {
    496             slot.setValue(jsNumber(exec, m_stringLength));
     527            slot.setValue(jsNumber(exec, m_length));
    497528            return true;
    498529        }
     
    500531        bool isStrictUInt32;
    501532        unsigned i = propertyName.toStrictUInt32(&isStrictUInt32);
    502         if (isStrictUInt32 && i < m_stringLength) {
     533        if (isStrictUInt32 && i < m_length) {
    503534            slot.setValue(jsSingleCharacterSubstring(exec, value(exec), i));
    504535            return true;
     
    510541    ALWAYS_INLINE bool JSString::getStringPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
    511542    {
    512         if (propertyName < m_stringLength) {
     543        if (propertyName < m_length) {
    513544            slot.setValue(jsSingleCharacterSubstring(exec, value(exec), propertyName));
    514545            return true;
  • trunk/JavaScriptCore/runtime/Operations.h

    r54394 r54804  
    4343            return s1;
    4444
    45         unsigned ropeLength = s1->ropeLength() + s2->ropeLength();
     45        unsigned fiberCount = s1->fiberCount() + s2->fiberCount();
    4646        JSGlobalData* globalData = &exec->globalData();
    4747
    48         if (ropeLength <= JSString::s_maxInternalRopeLength)
    49             return new (globalData) JSString(globalData, ropeLength, s1, s2);
    50 
    51         unsigned index = 0;
    52         RefPtr<JSString::Rope> rope = JSString::Rope::createOrNull(ropeLength);
    53         if (UNLIKELY(!rope))
     48        if (fiberCount <= JSString::s_maxInternalRopeLength)
     49            return new (globalData) JSString(globalData, fiberCount, s1, s2);
     50
     51        JSString::RopeBuilder ropeBuilder(fiberCount);
     52        if (UNLIKELY(ropeBuilder.isOutOfMemory()))
    5453            return throwOutOfMemoryError(exec);
    55         rope->append(index, s1);
    56         rope->append(index, s2);
    57         ASSERT(index == ropeLength);
    58         return new (globalData) JSString(globalData, rope.release());
     54        ropeBuilder.append(s1);
     55        ropeBuilder.append(s2);
     56        return new (globalData) JSString(globalData, ropeBuilder.release());
    5957    }
    6058
    6159    ALWAYS_INLINE JSValue jsString(ExecState* exec, const UString& u1, JSString* s2)
    6260    {
    63         unsigned ropeLength = 1 + s2->ropeLength();
     61        unsigned fiberCount = 1 + s2->fiberCount();
    6462        JSGlobalData* globalData = &exec->globalData();
    6563
    66         if (ropeLength <= JSString::s_maxInternalRopeLength)
    67             return new (globalData) JSString(globalData, ropeLength, u1, s2);
    68 
    69         unsigned index = 0;
    70         RefPtr<JSString::Rope> rope = JSString::Rope::createOrNull(ropeLength);
    71         if (UNLIKELY(!rope))
     64        if (fiberCount <= JSString::s_maxInternalRopeLength)
     65            return new (globalData) JSString(globalData, fiberCount, u1, s2);
     66
     67        JSString::RopeBuilder ropeBuilder(fiberCount);
     68        if (UNLIKELY(ropeBuilder.isOutOfMemory()))
    7269            return throwOutOfMemoryError(exec);
    73         rope->append(index, u1);
    74         rope->append(index, s2);
    75         ASSERT(index == ropeLength);
    76         return new (globalData) JSString(globalData, rope.release());
     70        ropeBuilder.append(u1);
     71        ropeBuilder.append(s2);
     72        return new (globalData) JSString(globalData, ropeBuilder.release());
    7773    }
    7874
    7975    ALWAYS_INLINE JSValue jsString(ExecState* exec, JSString* s1, const UString& u2)
    8076    {
    81         unsigned ropeLength = s1->ropeLength() + 1;
     77        unsigned fiberCount = s1->fiberCount() + 1;
    8278        JSGlobalData* globalData = &exec->globalData();
    8379
    84         if (ropeLength <= JSString::s_maxInternalRopeLength)
    85             return new (globalData) JSString(globalData, ropeLength, s1, u2);
    86 
    87         unsigned index = 0;
    88         RefPtr<JSString::Rope> rope = JSString::Rope::createOrNull(ropeLength);
    89         if (UNLIKELY(!rope))
     80        if (fiberCount <= JSString::s_maxInternalRopeLength)
     81            return new (globalData) JSString(globalData, fiberCount, s1, u2);
     82
     83        JSString::RopeBuilder ropeBuilder(fiberCount);
     84        if (UNLIKELY(ropeBuilder.isOutOfMemory()))
    9085            return throwOutOfMemoryError(exec);
    91         rope->append(index, s1);
    92         rope->append(index, u2);
    93         ASSERT(index == ropeLength);
    94         return new (globalData) JSString(globalData, rope.release());
     86        ropeBuilder.append(s1);
     87        ropeBuilder.append(u2);
     88        return new (globalData) JSString(globalData, ropeBuilder.release());
    9589    }
    9690
     
    9993        ASSERT(count >= 3);
    10094
    101         unsigned ropeLength = 0;
     95        unsigned fiberCount = 0;
    10296        for (unsigned i = 0; i < count; ++i) {
    10397            JSValue v = strings[i].jsValue();
    10498            if (LIKELY(v.isString()))
    105                 ropeLength += asString(v)->ropeLength();
     99                fiberCount += asString(v)->fiberCount();
    106100            else
    107                 ++ropeLength;
     101                ++fiberCount;
    108102        }
    109103
    110104        JSGlobalData* globalData = &exec->globalData();
    111         if (ropeLength == 3)
     105        if (fiberCount == 3)
    112106            return new (globalData) JSString(exec, strings[0].jsValue(), strings[1].jsValue(), strings[2].jsValue());
    113107
    114         RefPtr<JSString::Rope> rope = JSString::Rope::createOrNull(ropeLength);
    115         if (UNLIKELY(!rope))
     108        JSString::RopeBuilder ropeBuilder(fiberCount);
     109        if (UNLIKELY(ropeBuilder.isOutOfMemory()))
    116110            return throwOutOfMemoryError(exec);
    117111
    118         unsigned index = 0;
    119112        for (unsigned i = 0; i < count; ++i) {
    120113            JSValue v = strings[i].jsValue();
    121114            if (LIKELY(v.isString()))
    122                 rope->append(index, asString(v));
     115                ropeBuilder.append(asString(v));
    123116            else
    124                 rope->append(index, v.toString(exec));
    125         }
    126 
    127         ASSERT(index == ropeLength);
    128         return new (globalData) JSString(globalData, rope.release());
     117                ropeBuilder.append(v.toString(exec));
     118        }
     119
     120        return new (globalData) JSString(globalData, ropeBuilder.release());
    129121    }
    130122
    131123    ALWAYS_INLINE JSValue jsString(ExecState* exec, JSValue thisValue, const ArgList& args)
    132124    {
    133         unsigned ropeLength = 0;
     125        unsigned fiberCount = 0;
    134126        if (LIKELY(thisValue.isString()))
    135             ropeLength += asString(thisValue)->ropeLength();
     127            fiberCount += asString(thisValue)->fiberCount();
    136128        else
    137             ++ropeLength;
     129            ++fiberCount;
    138130        for (unsigned i = 0; i < args.size(); ++i) {
    139131            JSValue v = args.at(i);
    140132            if (LIKELY(v.isString()))
    141                 ropeLength += asString(v)->ropeLength();
     133                fiberCount += asString(v)->fiberCount();
    142134            else
    143                 ++ropeLength;
    144         }
    145 
    146         RefPtr<JSString::Rope> rope = JSString::Rope::createOrNull(ropeLength);
    147         if (UNLIKELY(!rope))
     135                ++fiberCount;
     136        }
     137
     138        JSString::RopeBuilder ropeBuilder(fiberCount);
     139        if (UNLIKELY(ropeBuilder.isOutOfMemory()))
    148140            return throwOutOfMemoryError(exec);
    149141
    150         unsigned index = 0;
    151142        if (LIKELY(thisValue.isString()))
    152             rope->append(index, asString(thisValue));
     143            ropeBuilder.append(asString(thisValue));
    153144        else
    154             rope->append(index, thisValue.toString(exec));
     145            ropeBuilder.append(thisValue.toString(exec));
    155146        for (unsigned i = 0; i < args.size(); ++i) {
    156147            JSValue v = args.at(i);
    157148            if (LIKELY(v.isString()))
    158                 rope->append(index, asString(v));
     149                ropeBuilder.append(asString(v));
    159150            else
    160                 rope->append(index, v.toString(exec));
    161         }
    162         ASSERT(index == ropeLength);
     151                ropeBuilder.append(v.toString(exec));
     152        }
    163153
    164154        JSGlobalData* globalData = &exec->globalData();
    165         return new (globalData) JSString(globalData, rope.release());
     155        return new (globalData) JSString(globalData, ropeBuilder.release());
    166156    }
    167157
Note: See TracChangeset for help on using the changeset viewer.