Title: [100202] trunk/Source/_javascript_Core
Revision
100202
Author
msab...@apple.com
Date
2011-11-14 15:51:06 -0800 (Mon, 14 Nov 2011)

Log Message

Towards 8 bit strings - Add 8 bit handling to JSString Ropes
https://bugs.webkit.org/show_bug.cgi?id=72317

Added bit to track that a rope is made up of all 8 bit fibers.
Created an 8 bit path (fast and slow cases) to handle 8 bit 
only ropes.

Reviewed by Oliver Hunt.

* runtime/JSString.cpp:
(JSC::JSString::resolveRope):
(JSC::JSString::resolveRopeSlowCase8):
(JSC::JSString::resolveRopeSlowCase16):
* runtime/JSString.h:
(JSC::RopeBuilder::finishCreation):
(JSC::RopeBuilder::is8Bit):
(JSC::jsSubstring8):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (100201 => 100202)


--- trunk/Source/_javascript_Core/ChangeLog	2011-11-14 23:33:30 UTC (rev 100201)
+++ trunk/Source/_javascript_Core/ChangeLog	2011-11-14 23:51:06 UTC (rev 100202)
@@ -1,3 +1,23 @@
+2011-11-14  Michael Saboff  <msab...@apple.com>
+
+        Towards 8 bit strings - Add 8 bit handling to JSString Ropes
+        https://bugs.webkit.org/show_bug.cgi?id=72317
+
+        Added bit to track that a rope is made up of all 8 bit fibers.
+        Created an 8 bit path (fast and slow cases) to handle 8 bit 
+        only ropes.
+
+        Reviewed by Oliver Hunt.
+
+        * runtime/JSString.cpp:
+        (JSC::JSString::resolveRope):
+        (JSC::JSString::resolveRopeSlowCase8):
+        (JSC::JSString::resolveRopeSlowCase16):
+        * runtime/JSString.h:
+        (JSC::RopeBuilder::finishCreation):
+        (JSC::RopeBuilder::is8Bit):
+        (JSC::jsSubstring8):
+
 2011-11-14  Geoffrey Garen  <gga...@apple.com>
 
         A little bit of function call cleanup

Modified: trunk/Source/_javascript_Core/runtime/JSString.cpp (100201 => 100202)


--- trunk/Source/_javascript_Core/runtime/JSString.cpp	2011-11-14 23:33:30 UTC (rev 100201)
+++ trunk/Source/_javascript_Core/runtime/JSString.cpp	2011-11-14 23:51:06 UTC (rev 100202)
@@ -62,6 +62,34 @@
 {
     ASSERT(isRope());
 
+    if (is8Bit()) {
+        LChar* buffer;
+        if (PassRefPtr<StringImpl> newImpl = StringImpl::tryCreateUninitialized(m_length, buffer))
+            m_value = newImpl;
+        else {
+            outOfMemory(exec);
+            return;
+        }
+
+        for (size_t i = 0; i < s_maxInternalRopeLength && m_fibers[i]; ++i) {
+            if (m_fibers[i]->isRope())
+                return resolveRopeSlowCase(exec, buffer);
+        }
+
+        LChar* position = buffer;
+        for (size_t i = 0; i < s_maxInternalRopeLength && m_fibers[i]; ++i) {
+            StringImpl* string = m_fibers[i]->m_value.impl();
+            unsigned length = string->length();
+            StringImpl::copyChars(position, string->characters8(), length);
+            position += length;
+            m_fibers[i].clear();
+        }
+        ASSERT((buffer + m_length) == position);
+        ASSERT(!isRope());
+
+        return;
+    }
+
     UChar* buffer;
     if (PassRefPtr<StringImpl> newImpl = StringImpl::tryCreateUninitialized(m_length, buffer))
         m_value = newImpl;
@@ -79,7 +107,7 @@
     for (size_t i = 0; i < s_maxInternalRopeLength && m_fibers[i]; ++i) {
         StringImpl* string = m_fibers[i]->m_value.impl();
         unsigned length = string->length();
-        StringImpl::copyChars(position, string->characters16(), length);
+        StringImpl::copyChars(position, string->characters(), length);
         position += length;
         m_fibers[i].clear();
     }
@@ -87,7 +115,7 @@
     ASSERT(!isRope());
 }
 
-// Overview: this methods converts a JSString from holding a string in rope form
+// Overview: These functions convert a JSString from holding a string in rope form
 // down to a simple UString representation.  It does so by building up the string
 // backwards, since we want to avoid recursion, we expect that the tree structure
 // representing the rope is likely imbalanced with more nodes down the left side
@@ -97,11 +125,11 @@
 // 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::resolveRopeSlowCase(ExecState* exec, UChar* buffer) const
+void JSString::resolveRopeSlowCase(ExecState* exec, LChar* buffer) const
 {
     UNUSED_PARAM(exec);
 
-    UChar* position = buffer + m_length; // We will be working backwards over the rope.
+    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.
     
     for (size_t i = 0; i < s_maxInternalRopeLength && m_fibers[i]; ++i) {
@@ -123,13 +151,43 @@
         StringImpl* string = static_cast<StringImpl*>(currentFiber->m_value.impl());
         unsigned length = string->length();
         position -= length;
-        StringImpl::copyChars(position, string->characters16(), length);
+        StringImpl::copyChars(position, string->characters8(), length);
     }
 
     ASSERT(buffer == position);
     ASSERT(!isRope());
 }
 
+void JSString::resolveRopeSlowCase(ExecState* exec, UChar* buffer) const
+{
+    UNUSED_PARAM(exec);
+
+    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.
+
+    for (size_t i = 0; i < s_maxInternalRopeLength && m_fibers[i]; ++i)
+        workQueue.append(m_fibers[i].get());
+
+    while (!workQueue.isEmpty()) {
+        JSString* currentFiber = workQueue.last();
+        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());
+            continue;
+        }
+
+        StringImpl* string = static_cast<StringImpl*>(currentFiber->m_value.impl());
+        unsigned length = string->length();
+        position -= length;
+        StringImpl::copyChars(position, string->characters(), length);
+    }
+
+    ASSERT(buffer == position);
+    ASSERT(!isRope());
+}
+
 void JSString::outOfMemory(ExecState* exec) const
 {
     for (size_t i = 0; i < s_maxInternalRopeLength && m_fibers[i]; ++i)

Modified: trunk/Source/_javascript_Core/runtime/JSString.h (100201 => 100202)


--- trunk/Source/_javascript_Core/runtime/JSString.h	2011-11-14 23:33:30 UTC (rev 100201)
+++ trunk/Source/_javascript_Core/runtime/JSString.h	2011-11-14 23:51:06 UTC (rev 100202)
@@ -22,7 +22,6 @@
 
 #ifndef JSString_h
 #define JSString_h
-
 #include "CallFrame.h"
 #include "CommonIdentifiers.h"
 #include "Identifier.h"
@@ -85,6 +84,7 @@
                     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()
@@ -127,6 +127,7 @@
             ASSERT(!m_value.isNull());
             Base::finishCreation(globalData);
             m_length = length;
+            m_is8Bit = m_value.impl()->is8Bit();
         }
 
         void finishCreation(JSGlobalData& globalData, size_t length, size_t cost)
@@ -134,6 +135,7 @@
             ASSERT(!m_value.isNull());
             Base::finishCreation(globalData);
             m_length = length;
+            m_is8Bit = m_value.impl()->is8Bit();
             Heap::heap(this)->reportExtraMemoryCost(cost);
         }
 
@@ -141,6 +143,7 @@
         {
             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);
         }
@@ -149,6 +152,7 @@
         {
             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);
@@ -244,6 +248,7 @@
         }
 
         void resolveRope(ExecState*) const;
+        void resolveRopeSlowCase(ExecState*, LChar*) const;
         void resolveRopeSlowCase(ExecState*, UChar*) const;
         void outOfMemory(ExecState*) const;
 
@@ -256,11 +261,13 @@
         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*);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to