Modified: trunk/Source/WTF/ChangeLog (163415 => 163416)
--- trunk/Source/WTF/ChangeLog 2014-02-05 00:09:15 UTC (rev 163415)
+++ trunk/Source/WTF/ChangeLog 2014-02-05 00:23:26 UTC (rev 163416)
@@ -1,5 +1,25 @@
2014-02-04 Anders Carlsson <[email protected]>
+ Store StringImpl substring backpointers as tail data
+ https://bugs.webkit.org/show_bug.cgi?id=128220
+
+ Reviewed by Geoffrey Garen.
+
+ This lets us get rid of m_substringBuffer from the union.
+
+ * wtf/text/StringImpl.cpp:
+ (WTF::StringImpl::~StringImpl):
+ (WTF::StringImpl::getData16SlowCase):
+ * wtf/text/StringImpl.h:
+ (WTF::StringImpl::StringImpl):
+ (WTF::StringImpl::createSubstringSharingImpl8):
+ (WTF::StringImpl::createSubstringSharingImpl):
+ (WTF::StringImpl::cost):
+ (WTF::StringImpl::costDuringGC):
+ (WTF::StringImpl::substringBuffer):
+
+2014-02-04 Anders Carlsson <[email protected]>
+
Rename the substring sharing StringImpl::create variants to better indicate what they do
https://bugs.webkit.org/show_bug.cgi?id=128214
Modified: trunk/Source/WTF/wtf/text/StringImpl.cpp (163415 => 163416)
--- trunk/Source/WTF/wtf/text/StringImpl.cpp 2014-02-05 00:09:15 UTC (rev 163415)
+++ trunk/Source/WTF/wtf/text/StringImpl.cpp 2014-02-05 00:23:26 UTC (rev 163416)
@@ -137,8 +137,8 @@
}
ASSERT(ownership == BufferSubstring);
- ASSERT(m_substringBuffer);
- m_substringBuffer->deref();
+ ASSERT(substringBuffer());
+ substringBuffer()->deref();
}
void StringImpl::destroy(StringImpl* stringImpl)
@@ -307,8 +307,8 @@
if (bufferOwnership() == BufferSubstring) {
// If this is a substring, return a pointer into the parent string.
// TODO: Consider severing this string from the parent string
- unsigned offset = m_data8 - m_substringBuffer->characters8();
- return m_substringBuffer->deprecatedCharacters() + offset;
+ unsigned offset = m_data8 - substringBuffer()->characters8();
+ return substringBuffer()->deprecatedCharacters() + offset;
}
STRING_STATS_ADD_UPCONVERTED_STRING(m_length);
Modified: trunk/Source/WTF/wtf/text/StringImpl.h (163415 => 163416)
--- trunk/Source/WTF/wtf/text/StringImpl.h 2014-02-05 00:09:15 UTC (rev 163415)
+++ trunk/Source/WTF/wtf/text/StringImpl.h 2014-02-05 00:23:26 UTC (rev 163416)
@@ -273,14 +273,15 @@
: m_refCount(s_refCountIncrement)
, m_length(length)
, m_data8(characters)
- , m_substringBuffer(base.leakRef())
, m_hashAndFlags(s_hashFlag8BitBuffer | BufferSubstring)
{
ASSERT(is8Bit());
ASSERT(m_data8);
ASSERT(m_length);
- ASSERT(m_substringBuffer->bufferOwnership() != BufferSubstring);
+ ASSERT(base->bufferOwnership() != BufferSubstring);
+ substringBuffer() = base.leakRef();
+
STRING_STATS_ADD_8BIT_STRING2(m_length, true);
}
@@ -289,14 +290,15 @@
: m_refCount(s_refCountIncrement)
, m_length(length)
, m_data16(characters)
- , m_substringBuffer(base.leakRef())
, m_hashAndFlags(BufferSubstring)
{
ASSERT(!is8Bit());
ASSERT(m_data16);
ASSERT(m_length);
- ASSERT(m_substringBuffer->bufferOwnership() != BufferSubstring);
+ ASSERT(base->bufferOwnership() != BufferSubstring);
+ substringBuffer() = base.leakRef();
+
STRING_STATS_ADD_16BIT_STRING2(m_length, true);
}
@@ -351,8 +353,11 @@
return *empty();
ASSERT(rep->is8Bit());
- StringImpl* ownerRep = (rep->bufferOwnership() == BufferSubstring) ? rep->m_substringBuffer : rep.get();
- return adoptRef(*new StringImpl(rep->m_data8 + offset, length, ownerRep));
+ StringImpl* ownerRep = (rep->bufferOwnership() == BufferSubstring) ? rep->substringBuffer() : rep.get();
+
+ // We allocate a buffer that contains both the StringImpl struct as well as the pointer to the owner string.
+ StringImpl* stringImpl = static_cast<StringImpl*>(fastMalloc(allocationSize<StringImpl*>(1)));
+ return adoptRef(*new (NotNull, stringImpl) StringImpl(rep->m_data8 + offset, length, ownerRep));
}
static ALWAYS_INLINE PassRef<StringImpl> createSubstringSharingImpl(PassRefPtr<StringImpl> rep, unsigned offset, unsigned length)
@@ -363,10 +368,13 @@
if (!length)
return *empty();
- StringImpl* ownerRep = (rep->bufferOwnership() == BufferSubstring) ? rep->m_substringBuffer : rep.get();
+ StringImpl* ownerRep = (rep->bufferOwnership() == BufferSubstring) ? rep->substringBuffer() : rep.get();
+
+ // We allocate a buffer that contains both the StringImpl struct as well as the pointer to the owner string.
+ StringImpl* stringImpl = static_cast<StringImpl*>(fastMalloc(allocationSize<StringImpl*>(1)));
if (rep->is8Bit())
- return adoptRef(*new StringImpl(rep->m_data8 + offset, length, ownerRep));
- return adoptRef(*new StringImpl(rep->m_data16 + offset, length, ownerRep));
+ return adoptRef(*new (NotNull, stringImpl) StringImpl(rep->m_data8 + offset, length, ownerRep));
+ return adoptRef(*new (NotNull, stringImpl) StringImpl(rep->m_data16 + offset, length, ownerRep));
}
template<unsigned charactersCount>
@@ -459,7 +467,7 @@
{
// For substrings, return the cost of the base string.
if (bufferOwnership() == BufferSubstring)
- return m_substringBuffer->cost();
+ return substringBuffer()->cost();
if (m_hashAndFlags & s_hashFlagDidReportCost)
return 0;
@@ -477,7 +485,7 @@
return 0;
if (bufferOwnership() == BufferSubstring)
- return divideRoundedUp(m_substringBuffer->costDuringGC(), refCount());
+ return divideRoundedUp(substringBuffer()->costDuringGC(), refCount());
size_t result = m_length;
if (!is8Bit())
@@ -789,6 +797,20 @@
return reinterpret_cast<T*>(reinterpret_cast<uint8_t*>(this) + tailOffset<T>());
}
+ StringImpl* const& substringBuffer() const
+ {
+ ASSERT(bufferOwnership() == BufferSubstring);
+
+ return *tailPointer<StringImpl*>();
+ }
+
+ StringImpl*& substringBuffer()
+ {
+ ASSERT(bufferOwnership() == BufferSubstring);
+
+ return *tailPointer<StringImpl*>();
+ }
+
// This number must be at least 2 to avoid sharing empty, null as well as 1 character strings from SmallStrings.
static const unsigned s_copyCharsInlineCutOff = 20;
@@ -854,10 +876,7 @@
const LChar* m_data8;
const UChar* m_data16;
};
- union {
- StringImpl* m_substringBuffer;
- mutable UChar* m_copyData16;
- };
+ mutable UChar* m_copyData16;
mutable unsigned m_hashAndFlags;
};