Title: [115516] trunk/Source/_javascript_Core
Revision
115516
Author
[email protected]
Date
2012-04-27 16:51:17 -0700 (Fri, 27 Apr 2012)

Log Message

Memory wasted in JSString for non-rope strings
https://bugs.webkit.org/show_bug.cgi?id=84907

Reviewed by Geoffrey Garen.

Split JSString into two classes, JSString as a base class that does not
include the fibers of a Rope, and a subclass JSRopeString that has the
rope functionality.  Both classes "share" the same ClassInfo.  Added
a bool to JSString to indicate that the string was allocated as a JSRopeString
to properly handle visiting the fiber children when the rope is resolved and
the JSRopeString appears as a JSString.  Didn't change the interface of JSString
to require any JIT changes.

As part of this change, removed "cellSize" from ClassInfo since both classes
share the same ClassInfo, but have different sizes.  The only use I could find
for cellSize was an ASSERT in allocateCell().

This appears to be neutral on performance tests.

* _javascript_Core.vcproj/_javascript_Core/_javascript_Core.def: Changed JSString::resolveRope
        to JSRopeString::resolveRope
* runtime/ClassInfo.h:
(JSC):
(ClassInfo):
* runtime/JSCell.h:
(JSC::allocateCell):
* runtime/JSString.cpp:
(JSC::JSRopeString::RopeBuilder::expand):
(JSC::JSString::visitChildren):
(JSC):
(JSC::JSRopeString::visitFibers):
(JSC::JSRopeString::resolveRope):
(JSC::JSRopeString::resolveRopeSlowCase8):
(JSC::JSRopeString::resolveRopeSlowCase):
(JSC::JSRopeString::outOfMemory):
(JSC::JSRopeString::getIndexSlowCase):
* runtime/JSString.h:
(JSC):
(JSString):
(JSC::JSString::finishCreation):
(JSC::JSString::create):
(JSC::JSString::isRope):
(JSC::JSString::is8Bit):
(JSRopeString):
(RopeBuilder):
(JSC::JSRopeString::RopeBuilder::RopeBuilder):
(JSC::JSRopeString::RopeBuilder::append):
(JSC::JSRopeString::RopeBuilder::release):
(JSC::JSRopeString::RopeBuilder::length):
(JSC::JSRopeString::JSRopeString):
(JSC::JSRopeString::finishCreation):
(JSC::JSRopeString::createNull):
(JSC::JSRopeString::create):
(JSC::JSString::value):
(JSC::JSString::tryGetValue):
(JSC::JSString::getIndex):
(JSC::jsStringBuilder):
* runtime/Operations.h:
(JSC::jsString):
(JSC::jsStringFromArguments):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (115515 => 115516)


--- trunk/Source/_javascript_Core/ChangeLog	2012-04-27 23:48:57 UTC (rev 115515)
+++ trunk/Source/_javascript_Core/ChangeLog	2012-04-27 23:51:17 UTC (rev 115516)
@@ -1,3 +1,66 @@
+2012-04-27  Michael Saboff  <[email protected]>
+
+        Memory wasted in JSString for non-rope strings
+        https://bugs.webkit.org/show_bug.cgi?id=84907
+
+        Reviewed by Geoffrey Garen.
+
+        Split JSString into two classes, JSString as a base class that does not
+        include the fibers of a Rope, and a subclass JSRopeString that has the
+        rope functionality.  Both classes "share" the same ClassInfo.  Added
+        a bool to JSString to indicate that the string was allocated as a JSRopeString
+        to properly handle visiting the fiber children when the rope is resolved and
+        the JSRopeString appears as a JSString.  Didn't change the interface of JSString
+        to require any JIT changes.
+
+        As part of this change, removed "cellSize" from ClassInfo since both classes
+        share the same ClassInfo, but have different sizes.  The only use I could find
+        for cellSize was an ASSERT in allocateCell().
+
+        This appears to be neutral on performance tests.
+
+        * _javascript_Core.vcproj/_javascript_Core/_javascript_Core.def: Changed JSString::resolveRope
+                to JSRopeString::resolveRope
+        * runtime/ClassInfo.h:
+        (JSC):
+        (ClassInfo):
+        * runtime/JSCell.h:
+        (JSC::allocateCell):
+        * runtime/JSString.cpp:
+        (JSC::JSRopeString::RopeBuilder::expand):
+        (JSC::JSString::visitChildren):
+        (JSC):
+        (JSC::JSRopeString::visitFibers):
+        (JSC::JSRopeString::resolveRope):
+        (JSC::JSRopeString::resolveRopeSlowCase8):
+        (JSC::JSRopeString::resolveRopeSlowCase):
+        (JSC::JSRopeString::outOfMemory):
+        (JSC::JSRopeString::getIndexSlowCase):
+        * runtime/JSString.h:
+        (JSC):
+        (JSString):
+        (JSC::JSString::finishCreation):
+        (JSC::JSString::create):
+        (JSC::JSString::isRope):
+        (JSC::JSString::is8Bit):
+        (JSRopeString):
+        (RopeBuilder):
+        (JSC::JSRopeString::RopeBuilder::RopeBuilder):
+        (JSC::JSRopeString::RopeBuilder::append):
+        (JSC::JSRopeString::RopeBuilder::release):
+        (JSC::JSRopeString::RopeBuilder::length):
+        (JSC::JSRopeString::JSRopeString):
+        (JSC::JSRopeString::finishCreation):
+        (JSC::JSRopeString::createNull):
+        (JSC::JSRopeString::create):
+        (JSC::JSString::value):
+        (JSC::JSString::tryGetValue):
+        (JSC::JSString::getIndex):
+        (JSC::jsStringBuilder):
+        * runtime/Operations.h:
+        (JSC::jsString):
+        (JSC::jsStringFromArguments):
+
 2012-04-27  Oliver Hunt  <[email protected]>
 
         Correct assertion.

Modified: trunk/Source/_javascript_Core/_javascript_Core.vcproj/_javascript_Core/_javascript_Core.def (115515 => 115516)


--- trunk/Source/_javascript_Core/_javascript_Core.vcproj/_javascript_Core/_javascript_Core.def	2012-04-27 23:48:57 UTC (rev 115515)
+++ trunk/Source/_javascript_Core/_javascript_Core.vcproj/_javascript_Core/_javascript_Core.def	2012-04-27 23:51:17 UTC (rev 115516)
@@ -289,7 +289,7 @@
     ?resetDateCache@JSGlobalData@JSC@@QAEXXZ
     ?resize@StringBuilder@WTF@@QAEXI@Z
     ?resizeOutOfLine@BitVector@WTF@@AAEXI@Z
-    ?resolveRope@JSString@JSC@@ABEXPAVExecState@2@@Z
+    ?resolveRope@JSRopeString@JSC@@ABEXPAVExecState@2@@Z
     ?restoreAll@Profile@JSC@@QAEXXZ
     ?retrieveCallerFromVMCode@Interpreter@JSC@@QBE?AVJSValue@2@PAVExecState@2@PAVJSFunction@2@@Z
     ?retrieveLastCaller@Interpreter@JSC@@QBEXPAVExecState@2@AAH1AAVUString@2@AAVJSValue@2@@Z

Modified: trunk/Source/_javascript_Core/runtime/ClassInfo.h (115515 => 115516)


--- trunk/Source/_javascript_Core/runtime/ClassInfo.h	2012-04-27 23:48:57 UTC (rev 115515)
+++ trunk/Source/_javascript_Core/runtime/ClassInfo.h	2012-04-27 23:51:17 UTC (rev 115516)
@@ -131,7 +131,6 @@
         &ClassName::defineOwnProperty, \
         &ClassName::getOwnPropertyDescriptor, \
     }, \
-    sizeof(ClassName), \
     ClassName::TypedArrayStorageType
 
     struct ClassInfo {
@@ -180,8 +179,6 @@
 
         MethodTable methodTable;
 
-        size_t cellSize;
-        
         TypedArrayType typedArrayStorageType;
     };
 

Modified: trunk/Source/_javascript_Core/runtime/JSCell.h (115515 => 115516)


--- trunk/Source/_javascript_Core/runtime/JSCell.h	2012-04-27 23:48:57 UTC (rev 115515)
+++ trunk/Source/_javascript_Core/runtime/JSCell.h	2012-04-27 23:51:17 UTC (rev 115516)
@@ -328,7 +328,6 @@
     void* allocateCell(Heap& heap)
     {
 #if ENABLE(GC_VALIDATION)
-        ASSERT(sizeof(T) == T::s_info.cellSize);
         ASSERT(!heap.globalData()->isInitializingObject());
         heap.globalData()->setInitializingObjectClass(&T::s_info);
 #endif

Modified: trunk/Source/_javascript_Core/runtime/JSString.cpp (115515 => 115516)


--- trunk/Source/_javascript_Core/runtime/JSString.cpp	2012-04-27 23:48:57 UTC (rev 115515)
+++ trunk/Source/_javascript_Core/runtime/JSString.cpp	2012-04-27 23:51:17 UTC (rev 115516)
@@ -36,9 +36,9 @@
 
 const ClassInfo JSString::s_info = { "string", 0, 0, 0, CREATE_METHOD_TABLE(JSString) };
 
-void JSString::RopeBuilder::expand()
+void JSRopeString::RopeBuilder::expand()
 {
-    ASSERT(m_index == JSString::s_maxInternalRopeLength);
+    ASSERT(m_index == JSRopeString::s_maxInternalRopeLength);
     JSString* jsString = m_jsString;
     m_jsString = jsStringBuilder(&m_globalData);
     m_index = 0;
@@ -55,12 +55,19 @@
 {
     JSString* thisObject = jsCast<JSString*>(cell);
     Base::visitChildren(thisObject, visitor);
-    for (size_t i = 0; i < s_maxInternalRopeLength && thisObject->m_fibers[i]; ++i)
-        visitor.append(&thisObject->m_fibers[i]);
+    
+    if (thisObject->isRope())
+        static_cast<JSRopeString*>(thisObject)->visitFibers(visitor);
 }
 
-void JSString::resolveRope(ExecState* exec) const
+void JSRopeString::visitFibers(SlotVisitor& visitor)
 {
+    for (size_t i = 0; i < s_maxInternalRopeLength && m_fibers[i]; ++i)
+        visitor.append(&m_fibers[i]);
+}
+
+void JSRopeString::resolveRope(ExecState* exec) const
+{
     ASSERT(isRope());
 
     if (is8Bit()) {
@@ -128,7 +135,7 @@
 // Vector before performing any concatenation, but by working backwards we likely
 // only fill the queue with the number of substrings at any given level in a
 // rope-of-ropes.)    
-void JSString::resolveRopeSlowCase8(LChar* buffer) const
+void JSRopeString::resolveRopeSlowCase8(LChar* buffer) const
 {
     LChar* position = buffer + m_length; // We will be working backwards over the rope.
     Vector<JSString*, 32> workQueue; // Putting strings into a Vector is only OK because there are no GC points in this method.
@@ -144,8 +151,9 @@
         workQueue.removeLast();
 
         if (currentFiber->isRope()) {
-            for (size_t i = 0; i < s_maxInternalRopeLength && currentFiber->m_fibers[i]; ++i)
-                workQueue.append(currentFiber->m_fibers[i].get());
+            JSRopeString* currentFiberAsRope = static_cast<JSRopeString*>(currentFiber);
+            for (size_t i = 0; i < s_maxInternalRopeLength && currentFiberAsRope->m_fibers[i]; ++i)
+                workQueue.append(currentFiberAsRope->m_fibers[i].get());
             continue;
         }
 
@@ -159,7 +167,7 @@
     ASSERT(!isRope());
 }
 
-void JSString::resolveRopeSlowCase(UChar* buffer) const
+void JSRopeString::resolveRopeSlowCase(UChar* buffer) const
 {
     UChar* position = buffer + m_length; // We will be working backwards over the rope.
     Vector<JSString*, 32> workQueue; // These strings are kept alive by the parent rope, so using a Vector is OK.
@@ -172,8 +180,9 @@
         workQueue.removeLast();
 
         if (currentFiber->isRope()) {
-            for (size_t i = 0; i < s_maxInternalRopeLength && currentFiber->m_fibers[i]; ++i)
-                workQueue.append(currentFiber->m_fibers[i].get());
+            JSRopeString* currentFiberAsRope = static_cast<JSRopeString*>(currentFiber);
+            for (size_t i = 0; i < s_maxInternalRopeLength && currentFiberAsRope->m_fibers[i]; ++i)
+                workQueue.append(currentFiberAsRope->m_fibers[i].get());
             continue;
         }
 
@@ -187,7 +196,7 @@
     ASSERT(!isRope());
 }
 
-void JSString::outOfMemory(ExecState* exec) const
+void JSRopeString::outOfMemory(ExecState* exec) const
 {
     for (size_t i = 0; i < s_maxInternalRopeLength && m_fibers[i]; ++i)
         m_fibers[i].clear();
@@ -197,7 +206,7 @@
         throwOutOfMemoryError(exec);
 }
 
-JSString* JSString::getIndexSlowCase(ExecState* exec, unsigned i)
+JSString* JSRopeString::getIndexSlowCase(ExecState* exec, unsigned i)
 {
     ASSERT(isRope());
     resolveRope(exec);

Modified: trunk/Source/_javascript_Core/runtime/JSString.h (115515 => 115516)


--- trunk/Source/_javascript_Core/runtime/JSString.h	2012-04-27 23:48:57 UTC (rev 115515)
+++ trunk/Source/_javascript_Core/runtime/JSString.h	2012-04-27 23:51:17 UTC (rev 115516)
@@ -32,6 +32,7 @@
 namespace JSC {
 
     class JSString;
+    class JSRopeString;
     class LLIntOffsetsExtractor;
 
     JSString* jsEmptyString(JSGlobalData*);
@@ -58,55 +59,20 @@
     JSString* jsOwnedString(JSGlobalData*, const UString&); 
     JSString* jsOwnedString(ExecState*, const UString&); 
 
-    JSString* jsStringBuilder(JSGlobalData*);
+    JSRopeString* jsStringBuilder(JSGlobalData*);
 
     class JSString : public JSCell {
     public:
         friend class JIT;
         friend class JSGlobalData;
         friend class SpecializedThunkJIT;
+        friend class JSRopeString;
         friend struct ThunkHelpers;
-        friend JSString* jsStringBuilder(JSGlobalData*);
 
         typedef JSCell Base;
 
         static void destroy(JSCell*);
 
-        class RopeBuilder {
-        public:
-            RopeBuilder(JSGlobalData& globalData)
-                : m_globalData(globalData)
-                , m_jsString(jsStringBuilder(&globalData))
-                , m_index(0)
-            {
-            }
-
-            void append(JSString* jsString)
-            {
-                if (m_index == JSString::s_maxInternalRopeLength)
-                    expand();
-                m_jsString->m_fibers[m_index++].set(m_globalData, m_jsString, jsString);
-                m_jsString->m_length += jsString->m_length;
-                m_jsString->m_is8Bit = m_jsString->m_is8Bit && jsString->m_is8Bit;
-            }
-
-            JSString* release()
-            {
-                JSString* tmp = m_jsString;
-                m_jsString = 0;
-                return tmp;
-            }
-
-            unsigned length() { return m_jsString->m_length; }
-
-        private:
-            void expand();
-
-            JSGlobalData& m_globalData;
-            JSString* m_jsString;
-            size_t m_index;
-        };
-
     private:
         JSString(JSGlobalData& globalData, PassRefPtr<StringImpl> value)
             : JSCell(globalData, globalData.stringStructure.get())
@@ -119,13 +85,6 @@
         {
         }
 
-        void finishCreation(JSGlobalData& globalData)
-        {
-            Base::finishCreation(globalData);
-            m_length = 0;
-            m_is8Bit = true;
-        }
-
         void finishCreation(JSGlobalData& globalData, size_t length)
         {
             ASSERT(!m_value.isNull());
@@ -143,32 +102,14 @@
             Heap::heap(this)->reportExtraMemoryCost(cost);
         }
 
-        void finishCreation(JSGlobalData& globalData, JSString* s1, JSString* s2)
+    protected:
+        void finishCreation(JSGlobalData& globalData)
         {
             Base::finishCreation(globalData);
-            m_length = s1->length() + s2->length();
-            m_is8Bit = (s1->is8Bit() && s2->is8Bit());
-            m_fibers[0].set(globalData, this, s1);
-            m_fibers[1].set(globalData, this, s2);
+            m_length = 0;
+            m_is8Bit = true;
         }
-
-        void finishCreation(JSGlobalData& globalData, JSString* s1, JSString* s2, JSString* s3)
-        {
-            Base::finishCreation(globalData);
-            m_length = s1->length() + s2->length() + s3->length();
-            m_is8Bit = (s1->is8Bit() && s2->is8Bit() &&  s3->is8Bit());
-            m_fibers[0].set(globalData, this, s1);
-            m_fibers[1].set(globalData, this, s2);
-            m_fibers[2].set(globalData, this, s3);
-        }
-
-        static JSString* createNull(JSGlobalData& globalData)
-        {
-            JSString* newString = new (NotNull, allocateCell<JSString>(globalData.heap)) JSString(globalData);
-            newString->finishCreation(globalData);
-            return newString;
-        }
-
+        
     public:
         static JSString* create(JSGlobalData& globalData, PassRefPtr<StringImpl> value)
         {
@@ -179,18 +120,6 @@
             newString->finishCreation(globalData, length, cost);
             return newString;
         }
-        static JSString* create(JSGlobalData& globalData, JSString* s1, JSString* s2)
-        {
-            JSString* newString = new (NotNull, allocateCell<JSString>(globalData.heap)) JSString(globalData);
-            newString->finishCreation(globalData, s1, s2);
-            return newString;
-        }
-        static JSString* create(JSGlobalData& globalData, JSString* s1, JSString* s2, JSString* s3)
-        {
-            JSString* newString = new (NotNull, allocateCell<JSString>(globalData.heap)) JSString(globalData);
-            newString->finishCreation(globalData, s1, s2, s3);
-            return newString;
-        }
         static JSString* createHasOtherOwner(JSGlobalData& globalData, PassRefPtr<StringImpl> value)
         {
             ASSERT(value);
@@ -200,18 +129,8 @@
             return newString;
         }
 
-        const UString& value(ExecState* exec) const
-        {
-            if (isRope())
-                resolveRope(exec);
-            return m_value;
-        }
-        const UString& tryGetValue() const
-        {
-            if (isRope())
-                resolveRope(0);
-            return m_value;
-        }
+        const UString& value(ExecState*) const;
+        const UString& tryGetValue() const;
         unsigned length() { return m_length; }
 
         JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
@@ -226,7 +145,6 @@
 
         bool canGetIndex(unsigned i) { return i < m_length; }
         JSString* getIndex(ExecState*, unsigned);
-        JSString* getIndexSlowCase(ExecState*, unsigned);
 
         static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
         {
@@ -240,38 +158,139 @@
 
         static void visitChildren(JSCell*, SlotVisitor&);
 
+    protected:
+        bool isRope() const { return m_value.isNull(); }
+        bool is8Bit() const { return m_is8Bit; }
+
+        // A string is represented either by a UString or a rope of fibers.
+        bool m_is8Bit : 1;
+        unsigned m_length;
+        mutable UString m_value;
+
     private:
         friend class LLIntOffsetsExtractor;
         
-        JS_EXPORT_PRIVATE void resolveRope(ExecState*) const;
-        void resolveRopeSlowCase8(LChar*) const;
-        void resolveRopeSlowCase(UChar*) const;
-        void outOfMemory(ExecState*) const;
-
         static JSObject* toThisObject(JSCell*, ExecState*);
 
         // Actually getPropertySlot, not getOwnPropertySlot (see JSCell).
         static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier& propertyName, PropertySlot&);
         static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&);
 
-        static const unsigned s_maxInternalRopeLength = 3;
-
-        // A string is represented either by a UString or a rope of fibers.
-        bool m_is8Bit : 1;
-        unsigned m_length;
-        mutable UString m_value;
-        mutable FixedArray<WriteBarrier<JSString>, s_maxInternalRopeLength> m_fibers;
-
-        bool isRope() const { return m_value.isNull(); }
-        bool is8Bit() const { return m_is8Bit; }
         UString& string() { ASSERT(!isRope()); return m_value; }
 
         friend JSValue jsString(ExecState*, JSString*, JSString*);
-        friend JSValue jsString(ExecState*, Register*, unsigned count);
-        friend JSValue jsStringFromArguments(ExecState*, JSValue thisValue);
         friend JSString* jsSubstring(ExecState*, JSString*, unsigned offset, unsigned length);
     };
 
+    class JSRopeString : public JSString {
+        friend class JSString;
+
+        friend JSRopeString* jsStringBuilder(JSGlobalData*);
+
+        class RopeBuilder {
+        public:
+            RopeBuilder(JSGlobalData& globalData)
+            : m_globalData(globalData)
+            , m_jsString(jsStringBuilder(&globalData))
+            , m_index(0)
+            {
+            }
+
+            void append(JSString* jsString)
+            {
+                if (m_index == JSRopeString::s_maxInternalRopeLength)
+                    expand();
+                m_jsString->m_fibers[m_index++].set(m_globalData, m_jsString, jsString);
+                m_jsString->m_length += jsString->m_length;
+                m_jsString->m_is8Bit = m_jsString->m_is8Bit && jsString->m_is8Bit;
+            }
+
+            JSRopeString* release()
+            {
+                JSRopeString* tmp = m_jsString;
+                m_jsString = 0;
+                return tmp;
+            }
+
+            unsigned length() { return m_jsString->m_length; }
+
+        private:
+            void expand();
+            
+            JSGlobalData& m_globalData;
+            JSRopeString* m_jsString;
+            size_t m_index;
+        };
+        
+    private:
+        JSRopeString(JSGlobalData& globalData)
+            : JSString(globalData)
+        {
+        }
+
+        void finishCreation(JSGlobalData& globalData, JSString* s1, JSString* s2)
+        {
+            Base::finishCreation(globalData);
+            m_length = s1->length() + s2->length();
+            m_is8Bit = (s1->is8Bit() && s2->is8Bit());
+            m_fibers[0].set(globalData, this, s1);
+            m_fibers[1].set(globalData, this, s2);
+        }
+        
+        void finishCreation(JSGlobalData& globalData, JSString* s1, JSString* s2, JSString* s3)
+        {
+            Base::finishCreation(globalData);
+            m_length = s1->length() + s2->length() + s3->length();
+            m_is8Bit = (s1->is8Bit() && s2->is8Bit() &&  s3->is8Bit());
+            m_fibers[0].set(globalData, this, s1);
+            m_fibers[1].set(globalData, this, s2);
+            m_fibers[2].set(globalData, this, s3);
+        }
+
+        void finishCreation(JSGlobalData& globalData)
+        {
+            JSString::finishCreation(globalData);
+        }
+
+        static JSRopeString* createNull(JSGlobalData& globalData)
+        {
+            JSRopeString* newString = new (NotNull, allocateCell<JSRopeString>(globalData.heap)) JSRopeString(globalData);
+            newString->finishCreation(globalData);
+            return newString;
+        }
+
+    public:
+        static JSString* create(JSGlobalData& globalData, JSString* s1, JSString* s2)
+        {
+            JSRopeString* newString = new (NotNull, allocateCell<JSRopeString>(globalData.heap)) JSRopeString(globalData);
+            newString->finishCreation(globalData, s1, s2);
+            return newString;
+        }
+        static JSString* create(JSGlobalData& globalData, JSString* s1, JSString* s2, JSString* s3)
+        {
+            JSRopeString* newString = new (NotNull, allocateCell<JSRopeString>(globalData.heap)) JSRopeString(globalData);
+            newString->finishCreation(globalData, s1, s2, s3);
+            return newString;
+        }
+
+        void visitFibers(SlotVisitor&);
+
+    private:
+        friend JSValue jsString(ExecState*, Register*, unsigned);
+        friend JSValue jsStringFromArguments(ExecState*, JSValue);
+
+        JS_EXPORT_PRIVATE void resolveRope(ExecState*) const;
+        void resolveRopeSlowCase8(LChar*) const;
+        void resolveRopeSlowCase(UChar*) const;
+        void outOfMemory(ExecState*) const;
+        
+        JSString* getIndexSlowCase(ExecState*, unsigned);
+
+        static const unsigned s_maxInternalRopeLength = 3;
+        
+        mutable FixedArray<WriteBarrier<JSString>, s_maxInternalRopeLength> m_fibers;
+    };
+
     JSString* asString(JSValue);
 
     inline JSString* asString(JSValue value)
@@ -316,11 +335,25 @@
         return JSString::create(*globalData, s.impl());
     }
 
+    inline const UString& JSString::value(ExecState* exec) const
+    {
+        if (isRope())
+            static_cast<const JSRopeString*>(this)->resolveRope(exec);
+        return m_value;
+    }
+
+    inline const UString& JSString::tryGetValue() const
+    {
+        if (isRope())
+            static_cast<const JSRopeString*>(this)->resolveRope(0);
+        return m_value;
+    }
+
     inline JSString* JSString::getIndex(ExecState* exec, unsigned i)
     {
         ASSERT(canGetIndex(i));
         if (isRope())
-            return getIndexSlowCase(exec, i);
+            return static_cast<JSRopeString*>(this)->getIndexSlowCase(exec, i);
         ASSERT(i < m_value.length());
         return jsSingleCharacterSubstring(exec, m_value, i);
     }
@@ -392,9 +425,9 @@
         return JSString::createHasOtherOwner(*globalData, s.impl());
     }
 
-    inline JSString* jsStringBuilder(JSGlobalData* globalData)
+    inline JSRopeString* jsStringBuilder(JSGlobalData* globalData)
     {
-        return JSString::createNull(*globalData);
+        return JSRopeString::createNull(*globalData);
     }
 
     inline JSString* jsEmptyString(ExecState* exec) { return jsEmptyString(&exec->globalData()); }

Modified: trunk/Source/_javascript_Core/runtime/Operations.h (115515 => 115516)


--- trunk/Source/_javascript_Core/runtime/Operations.h	2012-04-27 23:48:57 UTC (rev 115515)
+++ trunk/Source/_javascript_Core/runtime/Operations.h	2012-04-27 23:51:17 UTC (rev 115516)
@@ -47,7 +47,7 @@
         if ((length1 + length2) < length1)
             return throwOutOfMemoryError(exec);
 
-        return JSString::create(globalData, s1, s2);
+        return JSRopeString::create(globalData, s1, s2);
     }
 
     ALWAYS_INLINE JSValue jsString(ExecState* exec, const UString& u1, const UString& u2, const UString& u3)
@@ -69,13 +69,13 @@
         if ((length1 + length2 + length3) < length3)
             return throwOutOfMemoryError(exec);
 
-        return JSString::create(exec->globalData(), jsString(globalData, u1), jsString(globalData, u2), jsString(globalData, u3));
+        return JSRopeString::create(exec->globalData(), jsString(globalData, u1), jsString(globalData, u2), jsString(globalData, u3));
     }
 
     ALWAYS_INLINE JSValue jsString(ExecState* exec, Register* strings, unsigned count)
     {
         JSGlobalData* globalData = &exec->globalData();
-        JSString::RopeBuilder ropeBuilder(*globalData);
+        JSRopeString::RopeBuilder ropeBuilder(*globalData);
 
         unsigned oldLength = 0;
 
@@ -93,7 +93,7 @@
     ALWAYS_INLINE JSValue jsStringFromArguments(ExecState* exec, JSValue thisValue)
     {
         JSGlobalData* globalData = &exec->globalData();
-        JSString::RopeBuilder ropeBuilder(*globalData);
+        JSRopeString::RopeBuilder ropeBuilder(*globalData);
         ropeBuilder.append(thisValue.toString(exec));
 
         unsigned oldLength = 0;
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to