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):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@100202 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/runtime/JSString.cpp b/Source/JavaScriptCore/runtime/JSString.cpp
index 8ed9251..10f843d 100644
--- a/Source/JavaScriptCore/runtime/JSString.cpp
+++ b/Source/JavaScriptCore/runtime/JSString.cpp
@@ -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,7 +151,37 @@
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);