RefPtr<AtomicStringImpl> JSRopeString::resolveRopeToExistingAtomicString(ExecState* exec) const { if (length() > maxLengthForOnStackResolve) { resolveRope(exec); if (RefPtr<AtomicStringImpl> existingAtomicString = AtomicStringImpl::lookUp(m_value.impl())) { m_value = *existingAtomicString; setIs8Bit(m_value.impl()->is8Bit()); clearFibers(); return existingAtomicString; } return nullptr; } if (is8Bit()) { LChar buffer[maxLengthForOnStackResolve]; resolveRopeInternal8(buffer); if (RefPtr<AtomicStringImpl> existingAtomicString = AtomicStringImpl::lookUp(buffer, length())) { m_value = *existingAtomicString; setIs8Bit(m_value.impl()->is8Bit()); clearFibers(); return existingAtomicString; } } else { UChar buffer[maxLengthForOnStackResolve]; resolveRopeInternal16(buffer); if (RefPtr<AtomicStringImpl> existingAtomicString = AtomicStringImpl::lookUp(buffer, length())) { m_value = *existingAtomicString; setIs8Bit(m_value.impl()->is8Bit()); clearFibers(); return existingAtomicString; } } return nullptr; }
void JSRopeString::resolveRopeToAtomicString(ExecState* exec) const { if (length() > maxLengthForOnStackResolve) { resolveRope(exec); m_value = AtomicString(m_value); setIs8Bit(m_value.impl()->is8Bit()); return; } if (is8Bit()) { LChar buffer[maxLengthForOnStackResolve]; resolveRopeInternal8(buffer); m_value = AtomicString(buffer, length()); setIs8Bit(m_value.impl()->is8Bit()); } else { UChar buffer[maxLengthForOnStackResolve]; resolveRopeInternal16(buffer); m_value = AtomicString(buffer, length()); setIs8Bit(m_value.impl()->is8Bit()); } 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)->reportExtraMemoryAllocated(m_value.impl()->cost()); }
JSString* JSRopeString::getIndexSlowCase(ExecState* exec, unsigned i) { ASSERT(isRope()); resolveRope(exec); // Return a safe no-value result, this should never be used, since the excetion will be thrown. if (exec->exception()) return jsEmptyString(exec); ASSERT(!isRope()); RELEASE_ASSERT(i < m_value.length()); return jsSingleCharacterSubstring(exec, m_value, i); }
TiString* TiString::getIndexSlowCase(TiExcState* exec, unsigned i) { ASSERT(isRope()); resolveRope(exec); // Return a safe no-value result, this should never be used, since the excetion will be thrown. if (exec->exception()) return jsString(exec, ""); ASSERT(!isRope()); ASSERT(i < m_value.size()); return jsSingleCharacterSubstring(exec, m_value, i); }
// This function construsts a substring out of a rope without flattening by reusing the existing fibers. // This can reduce memory usage substantially. Since traversing ropes is slow the function will revert // back to flattening if the rope turns out to be long. TiString* TiString::substringFromRope(TiExcState* exec, unsigned substringStart, unsigned substringLength) { ASSERT(isRope()); ASSERT(substringLength); TiGlobalData* globalData = &exec->globalData(); UString substringFibers[3]; unsigned fiberCount = 0; unsigned substringFiberCount = 0; unsigned substringEnd = substringStart + substringLength; unsigned fiberEnd = 0; RopeIterator end; for (RopeIterator it(m_fibers.data(), m_fiberCount); it != end; ++it) { ++fiberCount; StringImpl* fiberString = *it; unsigned fiberStart = fiberEnd; fiberEnd = fiberStart + fiberString->length(); if (fiberEnd <= substringStart) continue; unsigned copyStart = std::max(substringStart, fiberStart); unsigned copyEnd = std::min(substringEnd, fiberEnd); if (copyStart == fiberStart && copyEnd == fiberEnd) substringFibers[substringFiberCount++] = UString(fiberString); else substringFibers[substringFiberCount++] = UString(StringImpl::create(fiberString, copyStart - fiberStart, copyEnd - copyStart)); if (fiberEnd >= substringEnd) break; if (fiberCount > substringFromRopeCutoff || substringFiberCount >= 3) { // This turned out to be a really inefficient rope. Just flatten it. resolveRope(exec); return jsSubstring(&exec->globalData(), m_value, substringStart, substringLength); } } ASSERT(substringFiberCount && substringFiberCount <= 3); if (substringLength == 1) { ASSERT(substringFiberCount == 1); UChar c = substringFibers[0].characters()[0]; if (c <= maxSingleCharacterString) return globalData->smallStrings.singleCharacterString(globalData, c); } if (substringFiberCount == 1) return new (globalData) TiString(globalData, substringFibers[0]); if (substringFiberCount == 2) return new (globalData) TiString(globalData, substringFibers[0], substringFibers[1]); return new (globalData) TiString(globalData, substringFibers[0], substringFibers[1], substringFibers[2]); }