+// Overview: These functions convert a JSString from holding a string in rope form
+// down to a simple String 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
+// (since appending to the string is likely more common) - and as such resolving
+// in this fashion should minimize work queue size. (If we built the queue forwards
+// we would likely have to place all of the constituent StringImpls into the
+// 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 JSRopeString::resolveRopeSlowCase8(LChar* buffer) const
+{
+ LChar* position = buffer + m_length; // We will be working backwards over the rope.
+ Vector<JSString*, 32, UnsafeVectorOverflow> 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 && fiber(i); ++i)
+ workQueue.append(fiber(i).get());
+
+ while (!workQueue.isEmpty()) {
+ JSString* currentFiber = workQueue.last();
+ workQueue.removeLast();
+
+ const LChar* characters;
+
+ if (currentFiber->isRope()) {
+ JSRopeString* currentFiberAsRope = static_cast<JSRopeString*>(currentFiber);
+ if (!currentFiberAsRope->isSubstring()) {
+ for (size_t i = 0; i < s_maxInternalRopeLength && currentFiberAsRope->fiber(i); ++i)
+ workQueue.append(currentFiberAsRope->fiber(i).get());
+ continue;
+ }
+ ASSERT(!currentFiberAsRope->substringBase()->isRope());
+ characters =
+ currentFiberAsRope->substringBase()->m_value.characters8() +
+ currentFiberAsRope->substringOffset();
+ } else
+ characters = currentFiber->m_value.characters8();
+
+ unsigned length = currentFiber->length();
+ position -= length;
+ StringImpl::copyChars(position, characters, length);
+ }
+
+ ASSERT(buffer == position);
+}