Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(463)

Unified Diff: third_party/WebKit/Source/wtf/text/StringView.h

Issue 2033293002: Implement StringImpl sharing for StringView::toString(). (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix preload scanner bug. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/wtf/text/StringView.h
diff --git a/third_party/WebKit/Source/wtf/text/StringView.h b/third_party/WebKit/Source/wtf/text/StringView.h
index 692053b2afc85632bb0b260864d29e6f33d0ac0e..7b4793192c31a5d43ba83e969dd8017b2f39077f 100644
--- a/third_party/WebKit/Source/wtf/text/StringView.h
+++ b/third_party/WebKit/Source/wtf/text/StringView.h
@@ -6,6 +6,7 @@
#define WTF_StringView_h
#include "wtf/Allocator.h"
+#include "wtf/GetPtr.h"
#if DCHECK_IS_ON()
#include "wtf/RefPtr.h"
#endif
@@ -21,7 +22,7 @@ namespace WTF {
// and keeps track of the length and the type, it does NOT own the bytes.
//
// Since StringView does not own the bytes creating a StringView from a String,
-// then calling clear() on the string will result in a use-after-free. Asserts
+// then calling clear() on the String will result in a use-after-free. Asserts
// in ~StringView attempt to enforce this for most common cases.
//
// See base/strings/string_piece.h for more details.
@@ -47,7 +48,7 @@ public:
StringView(const String& string, unsigned offset)
: StringView(string.impl(), offset) {}
StringView(const String& string)
- : StringView(string, 0, string.length()) {}
+ : StringView(string.impl()) {}
// From an AtomicString:
StringView(const AtomicString& string, unsigned offset, unsigned length)
@@ -55,10 +56,11 @@ public:
StringView(const AtomicString& string, unsigned offset)
: StringView(string.impl(), offset) {}
StringView(const AtomicString& string)
- : StringView(string, 0, string.length()) {}
+ : StringView(string.impl()) {}
// From a literal string or LChar buffer:
- StringView(const LChar* chars, unsigned length);
+ StringView(const LChar* chars, unsigned length)
+ : StringView(reinterpret_cast<const void*>(chars), length, true) {}
StringView(const char* chars, unsigned length)
: StringView(reinterpret_cast<const LChar*>(chars), length) {}
StringView(const LChar* chars)
@@ -67,27 +69,26 @@ public:
: StringView(reinterpret_cast<const LChar*>(chars)) {}
// From a wide literal string or UChar buffer.
+ StringView(const UChar* chars, unsigned length)
+ : StringView(reinterpret_cast<const void*>(chars), length, false) {}
StringView(const UChar* chars);
- StringView(const UChar* chars, unsigned length);
// From a byte pointer.
StringView(const void* bytes, unsigned length, bool is8Bit)
- : m_length(length)
- , m_is8Bit(is8Bit)
- {
- m_data.bytes = bytes;
- }
+ : m_impl(is8Bit ? StringImpl::empty() : StringImpl::empty16Bit())
+ , m_bytes(bytes)
+ , m_length(length) {}
#if DCHECK_IS_ON()
~StringView();
#endif
- bool isNull() const { return !m_data.bytes; }
+ bool isNull() const { return !m_bytes; }
bool isEmpty() const { return !m_length; }
unsigned length() const { return m_length; }
- bool is8Bit() const { return m_is8Bit; }
+ bool is8Bit() const { DCHECK(m_impl); return m_impl->is8Bit(); }
void clear();
@@ -101,17 +102,31 @@ public:
const LChar* characters8() const
{
- ASSERT(is8Bit());
- return m_data.characters8;
+ DCHECK(is8Bit());
+ return m_characters8;
}
const UChar* characters16() const
{
- ASSERT(!is8Bit());
- return m_data.characters16;
+ DCHECK(!is8Bit());
+ return m_characters16;
}
- const void* bytes() const { return m_data.bytes; }
+ const void* bytes() const { return m_bytes; }
+
+ // This is not named impl() like String because it has different semantics.
+ // String::impl() is never null if String::isNull() is false. For StringView
+ // sharedImpl() can be null if the StringView was created with a non-zero
+ // offset, or a length that made it shorter than the underlying impl.
+ StringImpl* sharedImpl() const
+ {
+ // If this StringView is backed by a StringImpl, and was constructed
+ // with a zero offset and the same length we can just access the impl
+ // directly since this == StringView(m_impl).
+ if (m_impl->bytes() == bytes() && m_length == m_impl->length())
haraken 2016/06/06 02:28:52 Would you help me understand why do you need to ch
esprehn 2016/06/06 04:42:21 A StringView can be a shorter length than the unde
+ return getPtr(m_impl);
+ return nullptr;
+ }
String toString() const;
AtomicString toAtomicString() const;
@@ -119,32 +134,42 @@ public:
private:
void set(StringImpl&, unsigned offset, unsigned length);
+ // We use the StringImpl to mark for 8bit or 16bit, even for strings where
+ // we were constructed from a char pointer. So m_impl->bytes() might have
+ // nothing to do with this view's bytes().
#if DCHECK_IS_ON()
RefPtr<StringImpl> m_impl;
+#else
+ StringImpl* m_impl;
haraken 2016/06/06 02:28:52 Who guarantees that someone else keeps a reference
esprehn 2016/06/06 04:42:21 The caller does, this is the same as base::StringP
haraken 2016/06/06 05:02:35 Thanks for the details. Makes sense. The assertio
#endif
- union DataUnion {
- const LChar* characters8;
- const UChar* characters16;
- const void* bytes;
- } m_data;
+ union {
+ const LChar* m_characters8;
+ const UChar* m_characters16;
+ const void* m_bytes;
haraken 2016/06/06 02:28:52 Worth adding a comment that how each of the fields
esprehn 2016/06/06 04:42:21 This is the same as String's semantics. In the nex
haraken 2016/06/06 05:02:35 That sounds great.
+ };
unsigned m_length;
- unsigned m_is8Bit : 1;
};
inline StringView::StringView(const StringView& view, unsigned offset, unsigned length)
- : m_length(length)
- , m_is8Bit(view.is8Bit())
+ : m_impl(view.m_impl)
+ , m_length(length)
{
SECURITY_DCHECK(offset + length <= view.length());
if (is8Bit())
- m_data.characters8 = view.characters8() + offset;
+ m_characters8 = view.characters8() + offset;
else
- m_data.characters16 = view.characters16() + offset;
+ m_characters16 = view.characters16() + offset;
}
inline StringView::StringView(StringImpl* impl)
{
- impl ? set(*impl, 0, impl->length()) : clear();
+ if (!impl) {
+ clear();
+ return;
+ }
+ m_impl = impl;
+ m_length = impl->length();
+ m_bytes = impl->bytes();
}
inline StringView::StringView(StringImpl* impl, unsigned offset)
@@ -157,35 +182,22 @@ inline StringView::StringView(StringImpl* impl, unsigned offset, unsigned length
impl ? set(*impl, offset, length) : clear();
}
-inline StringView::StringView(const LChar* chars, unsigned length)
- : m_length(length)
- , m_is8Bit(true)
-{
- m_data.characters8 = chars;
-}
-
inline void StringView::clear()
{
m_length = 0;
- m_is8Bit = true;
- m_data.bytes = nullptr;
-#if DCHECK_IS_ON()
- m_impl = nullptr;
-#endif
+ m_bytes = nullptr;
+ m_impl = StringImpl::empty(); // mark as 8 bit.
}
inline void StringView::set(StringImpl& impl, unsigned offset, unsigned length)
{
SECURITY_DCHECK(offset + length <= impl.length());
m_length = length;
- m_is8Bit = impl.is8Bit();
-#if DCHECK_IS_ON()
m_impl = &impl;
-#endif
- if (m_is8Bit)
- m_data.characters8 = impl.characters8() + offset;
+ if (impl.is8Bit())
+ m_characters8 = impl.characters8() + offset;
else
- m_data.characters16 = impl.characters16() + offset;
+ m_characters16 = impl.characters16() + offset;
}
WTF_EXPORT bool equalIgnoringASCIICase(const StringView& a, const StringView& b);

Powered by Google App Engine
This is Rietveld 408576698