Title: [119217] trunk/Source/WTF
- Revision
- 119217
- Author
- [email protected]
- Date
- 2012-06-01 05:25:31 -0700 (Fri, 01 Jun 2012)
Log Message
[Qt] Make conversion from QString to WTF::String (and back again) ~free
https://bugs.webkit.org/show_bug.cgi?id=87847
Instead of copying the QString data when converting to a WTF::String we
make the WTF::String adopt the QString data by introducing a new buffer
ownership type, and pointing the internal WTF::StringImpl 16-bit data
member to the string data managed by QStringData.
We make sure to reference the QStringData when adopting, so that the
data will stay alive, and then dereference it when the WTF::StringImpl
is deleted, which will free the QStringData (either straight away, if
we're the only one holding a reference still, or later, when the ref
count goes to 0).
In the case of going back from a WTF::String to a QString we can cheat
a bit (avoid a copy), if we know that the WTF::String was adopted from
a QString, since it's then just a matter of having the QString adopt
the existing QStringData (just like a regular QString copy).
If the WTF::String buffer is not owned by QStringData, eg a regular
8-bit or 16-bit string/substring, we have to fall back to copying,
as before (though there are potential optimization tricks we can
apply here later on).
Reviewed by Gavin Barraclough.
* wtf/qt/StringQt.cpp:
* wtf/text/StringImpl.cpp:
* wtf/text/StringImpl.h:
Modified Paths
Diff
Modified: trunk/Source/WTF/ChangeLog (119216 => 119217)
--- trunk/Source/WTF/ChangeLog 2012-06-01 12:21:31 UTC (rev 119216)
+++ trunk/Source/WTF/ChangeLog 2012-06-01 12:25:31 UTC (rev 119217)
@@ -1,3 +1,36 @@
+2012-05-30 Tor Arne Vestbø <[email protected]>
+
+ [Qt] Make conversion from QString to WTF::String (and back again) ~free
+
+ https://bugs.webkit.org/show_bug.cgi?id=87847
+
+ Instead of copying the QString data when converting to a WTF::String we
+ make the WTF::String adopt the QString data by introducing a new buffer
+ ownership type, and pointing the internal WTF::StringImpl 16-bit data
+ member to the string data managed by QStringData.
+
+ We make sure to reference the QStringData when adopting, so that the
+ data will stay alive, and then dereference it when the WTF::StringImpl
+ is deleted, which will free the QStringData (either straight away, if
+ we're the only one holding a reference still, or later, when the ref
+ count goes to 0).
+
+ In the case of going back from a WTF::String to a QString we can cheat
+ a bit (avoid a copy), if we know that the WTF::String was adopted from
+ a QString, since it's then just a matter of having the QString adopt
+ the existing QStringData (just like a regular QString copy).
+
+ If the WTF::String buffer is not owned by QStringData, eg a regular
+ 8-bit or 16-bit string/substring, we have to fall back to copying,
+ as before (though there are potential optimization tricks we can
+ apply here later on).
+
+ Reviewed by Gavin Barraclough.
+
+ * wtf/qt/StringQt.cpp:
+ * wtf/text/StringImpl.cpp:
+ * wtf/text/StringImpl.h:
+
2012-06-01 Sudarsana Nagineni <[email protected]>
[EFL] Implement PlatformStrategies
Modified: trunk/Source/WTF/wtf/qt/StringQt.cpp (119216 => 119217)
--- trunk/Source/WTF/wtf/qt/StringQt.cpp 2012-06-01 12:21:31 UTC (rev 119216)
+++ trunk/Source/WTF/wtf/qt/StringQt.cpp 2012-06-01 12:25:31 UTC (rev 119217)
@@ -37,7 +37,11 @@
{
if (qstr.isNull())
return;
+#if HAVE(QT5)
+ m_impl = StringImpl::adopt(const_cast<QString&>(qstr).data_ptr());
+#else
m_impl = StringImpl::create(reinterpret_cast_ptr<const UChar*>(qstr.constData()), qstr.length());
+#endif
}
String::String(const QStringRef& ref)
@@ -49,6 +53,19 @@
String::operator QString() const
{
+ if (!m_impl)
+ return QString();
+
+#if HAVE(QT5)
+ if (QStringData* qStringData = m_impl->qStringData()) {
+ // The WTF string was adopted from a QString at some point, so we
+ // can just adopt the QStringData like a regular QString copy.
+ qStringData->ref.ref();
+ QStringDataPtr qStringDataPointer = { qStringData };
+ return QString(qStringDataPointer);
+ }
+#endif
+
return QString(reinterpret_cast<const QChar*>(characters()), length());
}
Modified: trunk/Source/WTF/wtf/text/StringImpl.cpp (119216 => 119217)
--- trunk/Source/WTF/wtf/text/StringImpl.cpp 2012-06-01 12:21:31 UTC (rev 119216)
+++ trunk/Source/WTF/wtf/text/StringImpl.cpp 2012-06-01 12:25:31 UTC (rev 119217)
@@ -69,6 +69,13 @@
fastFree(const_cast<LChar*>(m_data8));
return;
}
+#if PLATFORM(QT) && HAVE(QT5)
+ if (ownership == BufferAdoptedQString) {
+ if (!m_qStringData->ref.deref())
+ QStringData::deallocate(m_qStringData);
+ return;
+ }
+#endif
ASSERT(ownership == BufferSubstring);
ASSERT(m_substringBuffer);
@@ -1644,6 +1651,18 @@
return adoptRef(new StringImpl(buffer.release(), length));
}
+#if PLATFORM(QT) && HAVE(QT5)
+PassRefPtr<StringImpl> StringImpl::adopt(QStringData* qStringData)
+{
+ ASSERT(qStringData);
+
+ if (!qStringData->size)
+ return empty();
+
+ return adoptRef(new StringImpl(qStringData, ConstructAdoptedQString));
+}
+#endif
+
PassRefPtr<StringImpl> StringImpl::createWithTerminatingNullCharacter(const StringImpl& string)
{
// Use createUninitialized instead of 'new StringImpl' so that the string and its buffer
Modified: trunk/Source/WTF/wtf/text/StringImpl.h (119216 => 119217)
--- trunk/Source/WTF/wtf/text/StringImpl.h 2012-06-01 12:21:31 UTC (rev 119216)
+++ trunk/Source/WTF/wtf/text/StringImpl.h 2012-06-01 12:25:31 UTC (rev 119217)
@@ -31,6 +31,10 @@
#include <wtf/Vector.h>
#include <wtf/unicode/Unicode.h>
+#if PLATFORM(QT) && HAVE(QT5)
+#include <QString>
+#endif
+
#if USE(CF)
typedef const struct __CFString * CFStringRef;
#endif
@@ -82,6 +86,10 @@
BufferInternal,
BufferOwned,
BufferSubstring,
+#if PLATFORM(QT) && HAVE(QT5)
+ BufferAdoptedQString
+#endif
+ // NOTE: Adding more ownership types needs to extend m_hashAndFlags as we're at capacity
};
// Used to construct static strings, which have an special refCount that can never hit zero.
@@ -215,6 +223,29 @@
m_hashAndFlags = hash | BufferInternal;
}
+#if PLATFORM(QT) && HAVE(QT5)
+ // Used to create new strings that adopt an existing QString's data
+ enum ConstructAdoptedQStringTag { ConstructAdoptedQString };
+ StringImpl(QStringData* qStringData, ConstructAdoptedQStringTag)
+ : m_refCount(s_refCountIncrement)
+ , m_length(qStringData->size)
+ , m_data16(0)
+ , m_qStringData(qStringData)
+ , m_hashAndFlags(BufferAdoptedQString)
+ {
+ ASSERT(m_length);
+
+ // We ref the string-data to ensure it will be valid for the lifetime of
+ // this string. We then deref it in the destructor, so that the string
+ // data can eventually be freed.
+ m_qStringData->ref.ref();
+
+ // Now that we have a ref we can safely reference the string data
+ m_data16 = reinterpret_cast_ptr<const UChar*>(qStringData->data());
+ ASSERT(m_data16);
+ }
+#endif
+
public:
WTF_EXPORT_PRIVATE ~StringImpl();
@@ -308,6 +339,10 @@
static PassRefPtr<StringImpl> adopt(StringBuffer<LChar>& buffer);
WTF_EXPORT_PRIVATE static PassRefPtr<StringImpl> adopt(StringBuffer<UChar>& buffer);
+#if PLATFORM(QT) && HAVE(QT5)
+ static PassRefPtr<StringImpl> adopt(QStringData*);
+#endif
+
unsigned length() const { return m_length; }
bool is8Bit() const { return m_hashAndFlags & s_hashFlag8BitBuffer; }
@@ -367,6 +402,10 @@
m_hashAndFlags &= ~s_hashFlagIsAtomic;
}
+#if PLATFORM(QT) && HAVE(QT5)
+ QStringData* qStringData() { return bufferOwnership() == BufferAdoptedQString ? m_qStringData : 0; }
+#endif
+
private:
// The high bits of 'hash' are always empty, but we prefer to store our flags
// in the low bits because it makes them slightly more efficient to access.
@@ -591,6 +630,9 @@
void* m_buffer;
StringImpl* m_substringBuffer;
mutable UChar* m_copyData16;
+#if PLATFORM(QT) && HAVE(QT5)
+ QStringData* m_qStringData;
+#endif
};
mutable unsigned m_hashAndFlags;
};
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes