+static const unsigned maxLengthForOnStackResolve = 2048;
+
+void JSRopeString::resolveRopeInternal8(LChar* buffer) const
+{
+ for (size_t i = 0; i < s_maxInternalRopeLength && m_fibers[i]; ++i) {
+ if (m_fibers[i]->isRope()) {
+ resolveRopeSlowCase8(buffer);
+ return;
+ }
+ }
+
+ LChar* position = buffer;
+ for (size_t i = 0; i < s_maxInternalRopeLength && m_fibers[i]; ++i) {
+ const StringImpl& fiberString = *m_fibers[i]->m_value.impl();
+ unsigned length = fiberString.length();
+ StringImpl::copyChars(position, fiberString.characters8(), length);
+ position += length;
+ }
+ ASSERT((buffer + m_length) == position);
+}
+
+void JSRopeString::resolveRopeInternal16(UChar* buffer) const
+{
+ for (size_t i = 0; i < s_maxInternalRopeLength && m_fibers[i]; ++i) {
+ if (m_fibers[i]->isRope()) {
+ resolveRopeSlowCase(buffer);
+ return;
+ }
+ }
+
+ UChar* position = buffer;
+ for (size_t i = 0; i < s_maxInternalRopeLength && m_fibers[i]; ++i) {
+ const StringImpl& fiberString = *m_fibers[i]->m_value.impl();
+ unsigned length = fiberString.length();
+ if (fiberString.is8Bit())
+ StringImpl::copyChars(position, fiberString.characters8(), length);
+ else
+ StringImpl::copyChars(position, fiberString.characters16(), length);
+ position += length;
+ }
+ ASSERT((buffer + m_length) == position);
+}
+
+void JSRopeString::resolveRopeToAtomicString(ExecState* exec) const
+{
+ if (m_length > maxLengthForOnStackResolve) {
+ resolveRope(exec);
+ m_value = AtomicString(m_value);
+ return;
+ }
+
+ if (is8Bit()) {
+ LChar buffer[maxLengthForOnStackResolve];
+ resolveRopeInternal8(buffer);
+ m_value = AtomicString(buffer, m_length);
+ } else {
+ UChar buffer[maxLengthForOnStackResolve];
+ resolveRopeInternal16(buffer);
+ m_value = AtomicString(buffer, m_length);
+ }
+
+ clearFibers();
+
+ // If we resolved a string that didn't previously exist, notify the heap that we've grown.
+ if (m_value.impl()->hasOneRef())
+ Heap::heap(this)->reportExtraMemoryCost(m_value.impl()->cost());
+}
+
+void JSRopeString::clearFibers() const
+{
+ for (size_t i = 0; i < s_maxInternalRopeLength && m_fibers[i]; ++i)
+ m_fibers[i].clear();
+}
+
+AtomicStringImpl* JSRopeString::resolveRopeToExistingAtomicString(ExecState* exec) const
+{
+ if (m_length > maxLengthForOnStackResolve) {
+ resolveRope(exec);
+ if (AtomicStringImpl* existingAtomicString = AtomicString::find(m_value.impl())) {
+ m_value = *existingAtomicString;
+ clearFibers();
+ return existingAtomicString;
+ }
+ return nullptr;
+ }
+
+ if (is8Bit()) {
+ LChar buffer[maxLengthForOnStackResolve];
+ resolveRopeInternal8(buffer);
+ if (AtomicStringImpl* existingAtomicString = AtomicString::find(buffer, m_length)) {
+ m_value = *existingAtomicString;
+ clearFibers();
+ return existingAtomicString;
+ }
+ } else {
+ UChar buffer[maxLengthForOnStackResolve];
+ resolveRopeInternal16(buffer);
+ if (AtomicStringImpl* existingAtomicString = AtomicString::find(buffer, m_length)) {
+ m_value = *existingAtomicString;
+ clearFibers();
+ return existingAtomicString;
+ }
+ }
+
+ return nullptr;
+}
+