Ignore:
Timestamp:
Dec 10, 2009, 2:13:15 PM (15 years ago)
Author:
[email protected]
Message:

https://bugs.webkit.org/show_bug.cgi?id=32367
Add support for short Ropes (up to 3 entries) inline within JSString.
(rather than externally allocating an object to hold the rope).
Switch jsAdd of (JSString* + JSString*) to now make use of Ropes.

Reviewed by Oliver Hunt & Mark Rowe.

~1% progression on Sunspidey.

  • interpreter/Interpreter.cpp:

(JSC::Interpreter::privateExecute):

  • jit/JITOpcodes.cpp:

(JSC::JIT::privateCompileCTIMachineTrampolines):

  • jit/JITStubs.cpp:

(JSC::DEFINE_STUB_FUNCTION):

  • runtime/JSString.cpp:

(JSC::JSString::resolveRope):
(JSC::JSString::toBoolean):
(JSC::JSString::getStringPropertyDescriptor):

  • runtime/JSString.h:

(JSC::JSString::Rope::Fiber::deref):
(JSC::JSString::Rope::Fiber::ref):
(JSC::JSString::Rope::Fiber::refAndGetLength):
(JSC::JSString::Rope::append):
(JSC::JSString::JSString):
(JSC::JSString::~JSString):
(JSC::JSString::value):
(JSC::JSString::tryGetValue):
(JSC::JSString::length):
(JSC::JSString::canGetIndex):
(JSC::JSString::appendStringInConstruct):
(JSC::JSString::appendValueInConstructAndIncrementLength):
(JSC::JSString::isRope):
(JSC::JSString::string):
(JSC::JSString::ropeLength):
(JSC::JSString::getStringPropertySlot):

  • runtime/Operations.h:

(JSC::jsString):
(JSC::jsAdd):
(JSC::resolveBase):

File:
1 edited

Legend:

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

    r51933 r51964  
    7676                Fiber(Rope* rope) : m_value(reinterpret_cast<intptr_t>(rope) | 1) {}
    7777
     78                void deref()
     79                {
     80                    if (isRope())
     81                        rope()->deref();
     82                    else
     83                        string()->deref();
     84                }
     85
     86                Fiber& ref()
     87                {
     88                    if (isString())
     89                        string()->ref();
     90                    else
     91                        rope()->ref();
     92                    return *this;
     93                }
     94
     95                unsigned refAndGetLength()
     96                {
     97                    if (isString()) {
     98                        UString::Rep* rep = string();
     99                        return rep->ref()->len;
     100                    } else {
     101                        Rope* r = rope();
     102                        r->ref();
     103                        return r->stringLength();
     104                    }
     105                }
     106
    78107                bool isRope() { return m_value & 1; }
    79108                Rope* rope() { return reinterpret_cast<Rope*>(m_value & ~1); }
     
    98127            void destructNonRecursive();
    99128
    100             void initializeFiber(unsigned index, const UString& string)
     129            void append(unsigned &index, Fiber& fiber)
     130            {
     131                m_fibers[index++] = fiber;
     132                m_stringLength += fiber.refAndGetLength();
     133            }
     134            void append(unsigned &index, const UString& string)
    101135            {
    102136                UString::Rep* rep = string.rep();
    103                 rep->ref();
    104                 m_fibers[index] = Fiber(rep);
    105                 m_stringLength += rep->len;
     137                m_fibers[index++] = Fiber(rep);
     138                m_stringLength += rep->ref()->len;
    106139            }
    107             void initializeFiber(unsigned index, Rope* rope)
     140            void append(unsigned& index, JSString* jsString)
    108141            {
    109                 rope->ref();
    110                 m_fibers[index] = Fiber(rope);
    111                 m_stringLength += rope->stringLength();
    112             }
    113             void initializeFiber(unsigned index, JSString* jsString)
    114             {
    115                 if (jsString->isRope())
    116                     initializeFiber(index, jsString->rope());
    117                 else
    118                     initializeFiber(index, jsString->string());
     142                if (jsString->isRope()) {
     143                    for (unsigned i = 0; i < jsString->m_ropeLength; ++i)
     144                        append(index, jsString->m_fibers[i]);
     145                } else
     146                    append(index, jsString->string());
    119147            }
    120148
     
    134162        JSString(JSGlobalData* globalData, const UString& value)
    135163            : JSCell(globalData->stringStructure.get())
    136             , m_length(value.size())
     164            , m_stringLength(value.size())
    137165            , m_value(value)
     166            , m_ropeLength(0)
    138167        {
    139168            Heap::heap(this)->reportExtraMemoryCost(value.cost());
     
    143172        JSString(JSGlobalData* globalData, const UString& value, HasOtherOwnerType)
    144173            : JSCell(globalData->stringStructure.get())
    145             , m_length(value.size())
     174            , m_stringLength(value.size())
    146175            , m_value(value)
     176            , m_ropeLength(0)
    147177        {
    148178        }
    149179        JSString(JSGlobalData* globalData, PassRefPtr<UString::Rep> value, HasOtherOwnerType)
    150180            : JSCell(globalData->stringStructure.get())
    151             , m_length(value->size())
     181            , m_stringLength(value->size())
    152182            , m_value(value)
     183            , m_ropeLength(0)
    153184        {
    154185        }
    155186        JSString(JSGlobalData* globalData, PassRefPtr<JSString::Rope> rope)
    156187            : JSCell(globalData->stringStructure.get())
    157             , m_length(rope->stringLength())
    158             , m_rope(rope)
    159         {
     188            , m_stringLength(rope->stringLength())
     189            , m_ropeLength(1)
     190        {
     191            m_fibers[0] = rope.releaseRef();
     192        }
     193        // This constructor constructs a new string by concatenating s1 & s2.
     194        // This should only be called with ropeLength <= 3.
     195        JSString(JSGlobalData* globalData, unsigned ropeLength, JSString* s1, JSString* s2)
     196            : JSCell(globalData->stringStructure.get())
     197            , m_stringLength(s1->length() + s2->length())
     198            , m_ropeLength(ropeLength)
     199        {
     200            ASSERT(ropeLength <= s_maxInternalRopeLength);
     201            unsigned index = 0;
     202            appendStringInConstruct(index, s1);
     203            appendStringInConstruct(index, s2);
     204            ASSERT(ropeLength == index);
     205        }
     206        // This constructor constructs a new string by concatenating v1, v2 & v3.
     207        // This should only be called with ropeLength <= 3 ... which since every
     208        // value must require a ropeLength of at least one implies that the length
     209        // for each value must be exactly 1!
     210        JSString(ExecState* exec, JSValue v1, JSValue v2, JSValue v3)
     211            : JSCell(exec->globalData().stringStructure.get())
     212            , m_stringLength(0)
     213            , m_ropeLength(s_maxInternalRopeLength)
     214        {
     215            unsigned index = 0;
     216            appendValueInConstructAndIncrementLength(exec, index, v1);
     217            appendValueInConstructAndIncrementLength(exec, index, v2);
     218            appendValueInConstructAndIncrementLength(exec, index, v3);
     219            ASSERT(index == s_maxInternalRopeLength);
     220        }
     221
     222        ~JSString()
     223        {
     224            for (unsigned i = 0; i < m_ropeLength; ++i)
     225                m_fibers[i].deref();
    160226        }
    161227
    162228        const UString& value(ExecState* exec) const
    163229        {
    164             if (m_rope)
     230            if (isRope())
    165231                resolveRope(exec);
    166232            return m_value;
     
    168234        const UString tryGetValue() const
    169235        {
    170             if (m_rope)
     236            if (isRope())
    171237                UString();
    172238            return m_value;
    173239        }
    174         unsigned length() { return m_length; }
    175 
    176         bool isRope() const { return m_rope; }
    177         Rope* rope() { ASSERT(isRope()); return m_rope.get(); }
    178         UString& string() { ASSERT(!isRope()); return m_value; }
     240        unsigned length() { return m_stringLength; }
    179241
    180242        bool getStringPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
     
    182244        bool getStringPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor&);
    183245
    184         bool canGetIndex(unsigned i) { return i < m_length; }
     246        bool canGetIndex(unsigned i) { return i < m_stringLength; }
    185247        JSString* getIndex(ExecState*, unsigned);
    186248
     
    191253        JSString(VPtrStealingHackType)
    192254            : JSCell(0)
     255            , m_ropeLength(0)
    193256        {
    194257        }
    195258
    196259        void resolveRope(ExecState*) const;
     260
     261        void appendStringInConstruct(unsigned& index, JSString* jsString)
     262        {
     263            if (jsString->isRope()) {
     264                for (unsigned i = 0; i < jsString->m_ropeLength; ++i)
     265                    m_fibers[index++] = jsString->m_fibers[i].ref();
     266            } else
     267                m_fibers[index++] = Rope::Fiber(jsString->string().rep()->ref());
     268        }
     269
     270        void appendValueInConstructAndIncrementLength(ExecState* exec, unsigned& index, JSValue v)
     271        {
     272            if (v.isString()) {
     273                ASSERT(asCell(v)->isString());
     274                JSString* s = static_cast<JSString*>(asCell(v));
     275                ASSERT(s->ropeLength() == 1);
     276                appendStringInConstruct(index, s);
     277                m_stringLength += s->length();
     278            } else {
     279                UString u(v.toString(exec));
     280                m_fibers[index++] = Rope::Fiber(u.rep()->ref());
     281                m_stringLength += u.size();
     282            }
     283        }
    197284
    198285        virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
     
    212299        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
    213300
     301        static const unsigned s_maxInternalRopeLength = 3;
     302
    214303        // A string is represented either by a UString or a Rope.
    215         unsigned m_length;
     304        unsigned m_stringLength;
    216305        mutable UString m_value;
    217         mutable RefPtr<Rope> m_rope;
     306        mutable unsigned m_ropeLength;
     307        mutable Rope::Fiber m_fibers[s_maxInternalRopeLength];
     308
     309        bool isRope() const { return m_ropeLength; }
     310        UString& string() { ASSERT(!isRope()); return m_value; }
     311        unsigned ropeLength() { return m_ropeLength ? m_ropeLength : 1; }
     312
     313        friend JSValue jsString(ExecState* exec, JSString* s1, JSString* s2);
     314        friend JSValue jsString(ExecState* exec, Register* strings, unsigned count);
    218315    };
    219316
     
    279376        return new (globalData) JSString(globalData, s);
    280377    }
    281        
     378
    282379    inline JSString* jsSubstring(JSGlobalData* globalData, const UString& s, unsigned offset, unsigned length)
    283380    {
     
    320417    {
    321418        if (propertyName == exec->propertyNames().length) {
    322             slot.setValue(jsNumber(exec, m_length));
     419            slot.setValue(jsNumber(exec, m_stringLength));
    323420            return true;
    324421        }
     
    326423        bool isStrictUInt32;
    327424        unsigned i = propertyName.toStrictUInt32(&isStrictUInt32);
    328         if (isStrictUInt32 && i < m_length) {
     425        if (isStrictUInt32 && i < m_stringLength) {
    329426            slot.setValue(jsSingleCharacterSubstring(exec, value(exec), i));
    330427            return true;
     
    336433    ALWAYS_INLINE bool JSString::getStringPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
    337434    {
    338         if (propertyName < m_length) {
     435        if (propertyName < m_stringLength) {
    339436            slot.setValue(jsSingleCharacterSubstring(exec, value(exec), propertyName));
    340437            return true;
Note: See TracChangeset for help on using the changeset viewer.