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

Side by Side Diff: Source/wtf/text/StringImpl.h

Issue 21437003: Remove the pointer from StringImpl (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Now with placement new Created 7 years, 4 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/scripts/make_names.pl ('k') | Source/wtf/text/StringImpl.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. All rights reserved. 3 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. All rights reserved.
4 * Copyright (C) 2009 Google Inc. All rights reserved. 4 * Copyright (C) 2009 Google Inc. All rights reserved.
5 * 5 *
6 * This library is free software; you can redistribute it and/or 6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public 7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either 8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version. 9 * version 2 of the License, or (at your option) any later version.
10 * 10 *
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 friend struct WTF::HashAndUTF8CharactersTranslator; 108 friend struct WTF::HashAndUTF8CharactersTranslator;
109 friend struct WTF::CharBufferFromLiteralDataTranslator; 109 friend struct WTF::CharBufferFromLiteralDataTranslator;
110 friend struct WTF::LCharBufferTranslator; 110 friend struct WTF::LCharBufferTranslator;
111 friend struct WTF::SubstringTranslator; 111 friend struct WTF::SubstringTranslator;
112 friend struct WTF::UCharBufferTranslator; 112 friend struct WTF::UCharBufferTranslator;
113 113
114 private: 114 private:
115 // Used to construct static strings, which have an special refCount that can never hit zero. 115 // Used to construct static strings, which have an special refCount that can never hit zero.
116 // This means that the static string will never be destroyed, which is impor tant because 116 // This means that the static string will never be destroyed, which is impor tant because
117 // static strings will be shared across threads & ref-counted in a non-threa dsafe manner. 117 // static strings will be shared across threads & ref-counted in a non-threa dsafe manner.
118 enum ConstructStaticStringTag { ConstructStaticString }; 118 enum ConstructEmptyStringTag { ConstructEmptyString };
119 StringImpl(const LChar* characters, unsigned length, ConstructStaticStringTa g) 119 explicit StringImpl(ConstructEmptyStringTag)
120 : m_data8(characters) 120 : m_refCount(s_refCountFlagIsStaticString)
121 , m_refCount(s_refCountFlagIsStaticString) 121 , m_length(0)
122 , m_length(length)
123 , m_hashAndFlags(s_hashFlag8BitBuffer) 122 , m_hashAndFlags(s_hashFlag8BitBuffer)
124 { 123 {
125 // Ensure that the hash is computed so that AtomicStringHash can call ex istingHash() 124 // Ensure that the hash is computed so that AtomicStringHash can call ex istingHash()
126 // with impunity. The empty string is special because it is never entere d into 125 // with impunity. The empty string is special because it is never entere d into
127 // AtomicString's HashKey, but still needs to compare correctly. 126 // AtomicString's HashKey, but still needs to compare correctly.
128 STRING_STATS_ADD_8BIT_STRING(m_length); 127 STRING_STATS_ADD_8BIT_STRING(m_length);
129
130 hash(); 128 hash();
131 } 129 }
132 130
133 // FIXME: there has to be a less hacky way to do this. 131 // FIXME: there has to be a less hacky way to do this.
134 enum Force8Bit { Force8BitConstructor }; 132 enum Force8Bit { Force8BitConstructor };
135 StringImpl(unsigned length, Force8Bit) 133 StringImpl(unsigned length, Force8Bit)
136 : m_data8(reinterpret_cast<const LChar*>(this + 1)) 134 : m_refCount(s_refCountIncrement)
137 , m_refCount(s_refCountIncrement)
138 , m_length(length) 135 , m_length(length)
139 , m_hashAndFlags(s_hashFlag8BitBuffer) 136 , m_hashAndFlags(s_hashFlag8BitBuffer)
140 { 137 {
141 ASSERT(m_data8);
142 ASSERT(m_length); 138 ASSERT(m_length);
143
144 STRING_STATS_ADD_8BIT_STRING(m_length); 139 STRING_STATS_ADD_8BIT_STRING(m_length);
145 } 140 }
146 141
147 StringImpl(unsigned length) 142 StringImpl(unsigned length)
148 : m_data16(reinterpret_cast<const UChar*>(this + 1)) 143 : m_refCount(s_refCountIncrement)
149 , m_refCount(s_refCountIncrement)
150 , m_length(length) 144 , m_length(length)
151 , m_hashAndFlags(0) 145 , m_hashAndFlags(0)
152 { 146 {
153 ASSERT(m_data16);
154 ASSERT(m_length); 147 ASSERT(m_length);
155
156 STRING_STATS_ADD_16BIT_STRING(m_length); 148 STRING_STATS_ADD_16BIT_STRING(m_length);
157 } 149 }
158 150
159 public: 151 public:
160 ~StringImpl(); 152 ~StringImpl();
161 153
154 enum StaticStringTag { StaticString };
155 StringImpl(unsigned length, unsigned hash, StaticStringTag)
156 : m_refCount(s_refCountFlagIsStaticString)
157 , m_length(length)
158 , m_hashAndFlags(hash << s_flagCount | s_hashFlag8BitBuffer)
159 {
160 #ifndef NDEBUG
161 assertHashIsCorrect();
162 #endif
163 }
164
162 static PassRefPtr<StringImpl> create(const UChar*, unsigned length); 165 static PassRefPtr<StringImpl> create(const UChar*, unsigned length);
163 static PassRefPtr<StringImpl> create(const LChar*, unsigned length); 166 static PassRefPtr<StringImpl> create(const LChar*, unsigned length);
164 static PassRefPtr<StringImpl> create8BitIfPossible(const UChar*, unsigned le ngth); 167 static PassRefPtr<StringImpl> create8BitIfPossible(const UChar*, unsigned le ngth);
165 template<size_t inlineCapacity> 168 template<size_t inlineCapacity>
166 static PassRefPtr<StringImpl> create8BitIfPossible(const Vector<UChar, inlin eCapacity>& vector) 169 static PassRefPtr<StringImpl> create8BitIfPossible(const Vector<UChar, inlin eCapacity>& vector)
167 { 170 {
168 return create8BitIfPossible(vector.data(), vector.size()); 171 return create8BitIfPossible(vector.data(), vector.size());
169 } 172 }
170 173
171 ALWAYS_INLINE static PassRefPtr<StringImpl> create(const char* s, unsigned l ength) { return create(reinterpret_cast<const LChar*>(s), length); } 174 ALWAYS_INLINE static PassRefPtr<StringImpl> create(const char* s, unsigned l ength) { return create(reinterpret_cast<const LChar*>(s), length); }
(...skipping 13 matching lines...) Expand all
185 void truncateAssumingIsolated(unsigned length) 188 void truncateAssumingIsolated(unsigned length)
186 { 189 {
187 ASSERT(hasOneRef()); 190 ASSERT(hasOneRef());
188 ASSERT(length <= m_length); 191 ASSERT(length <= m_length);
189 m_length = length; 192 m_length = length;
190 } 193 }
191 194
192 unsigned length() const { return m_length; } 195 unsigned length() const { return m_length; }
193 bool is8Bit() const { return m_hashAndFlags & s_hashFlag8BitBuffer; } 196 bool is8Bit() const { return m_hashAndFlags & s_hashFlag8BitBuffer; }
194 197
195 ALWAYS_INLINE const LChar* characters8() const { ASSERT(is8Bit()); return m_ data8; } 198 ALWAYS_INLINE const LChar* characters8() const { ASSERT(is8Bit()); return re interpret_cast<const LChar*>(this + 1); }
196 ALWAYS_INLINE const UChar* characters16() const { ASSERT(!is8Bit()); return m_data16; } 199 ALWAYS_INLINE const UChar* characters16() const { ASSERT(!is8Bit()); return reinterpret_cast<const UChar*>(this + 1); }
197 200
198 template <typename CharType> 201 template <typename CharType>
199 ALWAYS_INLINE const CharType * getCharacters() const; 202 ALWAYS_INLINE const CharType * getCharacters() const;
200 203
201 size_t sizeInBytes() const; 204 size_t sizeInBytes() const;
202 205
203 bool isAtomic() const { return m_hashAndFlags & s_hashFlagIsAtomic; } 206 bool isAtomic() const { return m_hashAndFlags & s_hashFlagIsAtomic; }
204 void setIsAtomic(bool isAtomic) 207 void setIsAtomic(bool isAtomic)
205 { 208 {
206 if (isAtomic) 209 if (isAtomic)
207 m_hashAndFlags |= s_hashFlagIsAtomic; 210 m_hashAndFlags |= s_hashFlagIsAtomic;
208 else 211 else
209 m_hashAndFlags &= ~s_hashFlagIsAtomic; 212 m_hashAndFlags &= ~s_hashFlagIsAtomic;
210 } 213 }
211 214
212 bool isStatic() const { return m_refCount & s_refCountFlagIsStaticString; } 215 bool isStatic() const { return m_refCount & s_refCountFlagIsStaticString; }
213 216
214 private: 217 private:
215 // The high bits of 'hash' are always empty, but we prefer to store our flag s 218 // The high bits of 'hash' are always empty, but we prefer to store our flag s
216 // in the low bits because it makes them slightly more efficient to access. 219 // in the low bits because it makes them slightly more efficient to access.
217 // So, we shift left and right when setting and getting our hash code. 220 // So, we shift left and right when setting and getting our hash code.
218 void setHash(unsigned hash) const 221 void setHash(unsigned hash) const
219 { 222 {
220 ASSERT(!hasHash()); 223 ASSERT(!hasHash());
221 // Multiple clients assume that StringHasher is the canonical string has h function. 224 // Multiple clients assume that StringHasher is the canonical string has h function.
222 ASSERT(hash == (is8Bit() ? StringHasher::computeHashAndMaskTop8Bits(m_da ta8, m_length) : StringHasher::computeHashAndMaskTop8Bits(m_data16, m_length))); 225 ASSERT(hash == (is8Bit() ? StringHasher::computeHashAndMaskTop8Bits(char acters8(), m_length) : StringHasher::computeHashAndMaskTop8Bits(characters16(), m_length)));
223 ASSERT(!(hash & (s_flagMask << (8 * sizeof(hash) - s_flagCount)))); // V erify that enough high bits are empty. 226 ASSERT(!(hash & (s_flagMask << (8 * sizeof(hash) - s_flagCount)))); // V erify that enough high bits are empty.
224 227
225 hash <<= s_flagCount; 228 hash <<= s_flagCount;
226 ASSERT(!(hash & m_hashAndFlags)); // Verify that enough low bits are emp ty after shift. 229 ASSERT(!(hash & m_hashAndFlags)); // Verify that enough low bits are emp ty after shift.
227 ASSERT(hash); // Verify that 0 is a valid sentinel hash value. 230 ASSERT(hash); // Verify that 0 is a valid sentinel hash value.
228 231
229 m_hashAndFlags |= hash; // Store hash with flags in low bits. 232 m_hashAndFlags |= hash; // Store hash with flags in low bits.
230 } 233 }
231 234
232 unsigned rawHash() const 235 unsigned rawHash() const
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 // thread-safe. We achieve thread safety by isolation, giving each thread 317 // thread-safe. We achieve thread safety by isolation, giving each thread
315 // its own copy of the string. 318 // its own copy of the string.
316 PassRefPtr<StringImpl> isolatedCopy() const; 319 PassRefPtr<StringImpl> isolatedCopy() const;
317 320
318 PassRefPtr<StringImpl> substring(unsigned pos, unsigned len = UINT_MAX); 321 PassRefPtr<StringImpl> substring(unsigned pos, unsigned len = UINT_MAX);
319 322
320 UChar operator[](unsigned i) const 323 UChar operator[](unsigned i) const
321 { 324 {
322 ASSERT_WITH_SECURITY_IMPLICATION(i < m_length); 325 ASSERT_WITH_SECURITY_IMPLICATION(i < m_length);
323 if (is8Bit()) 326 if (is8Bit())
324 return m_data8[i]; 327 return characters8()[i];
325 return m_data16[i]; 328 return characters16()[i];
326 } 329 }
327 UChar32 characterStartingAt(unsigned); 330 UChar32 characterStartingAt(unsigned);
328 331
329 bool containsOnlyWhitespace(); 332 bool containsOnlyWhitespace();
330 333
331 int toIntStrict(bool* ok = 0, int base = 10); 334 int toIntStrict(bool* ok = 0, int base = 10);
332 unsigned toUIntStrict(bool* ok = 0, int base = 10); 335 unsigned toUIntStrict(bool* ok = 0, int base = 10);
333 int64_t toInt64Strict(bool* ok = 0, int base = 10); 336 int64_t toInt64Strict(bool* ok = 0, int base = 10);
334 uint64_t toUInt64Strict(bool* ok = 0, int base = 10); 337 uint64_t toUInt64Strict(bool* ok = 0, int base = 10);
335 intptr_t toIntPtrStrict(bool* ok = 0, int base = 10); 338 intptr_t toIntPtrStrict(bool* ok = 0, int base = 10);
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
432 static const unsigned s_flagMask = (1u << s_flagCount) - 1; 435 static const unsigned s_flagMask = (1u << s_flagCount) - 1;
433 COMPILE_ASSERT(s_flagCount == StringHasher::flagCount, StringHasher_reserves _enough_bits_for_StringImpl_flags); 436 COMPILE_ASSERT(s_flagCount == StringHasher::flagCount, StringHasher_reserves _enough_bits_for_StringImpl_flags);
434 437
435 static const unsigned s_hashFlagIsAtomic = 1u << 1; 438 static const unsigned s_hashFlagIsAtomic = 1u << 1;
436 static const unsigned s_hashFlag8BitBuffer = 1u << 0; 439 static const unsigned s_hashFlag8BitBuffer = 1u << 0;
437 440
438 #ifdef STRING_STATS 441 #ifdef STRING_STATS
439 static StringStats m_stringStats; 442 static StringStats m_stringStats;
440 #endif 443 #endif
441 444
442 public:
443 struct StaticASCIILiteral {
444 // These member variables must match the layout of StringImpl.
445 const LChar* m_data8;
446 unsigned m_refCount;
447 unsigned m_length;
448 unsigned m_hashAndFlags;
449
450 static const unsigned s_initialRefCount = s_refCountFlagIsStaticString;
451 static const unsigned s_initialFlags = s_hashFlag8BitBuffer;
452 static const unsigned s_hashShift = s_flagCount;
453 };
454
455 #ifndef NDEBUG 445 #ifndef NDEBUG
456 void assertHashIsCorrect() 446 void assertHashIsCorrect()
457 { 447 {
458 ASSERT(hasHash()); 448 ASSERT(hasHash());
459 ASSERT(existingHash() == StringHasher::computeHashAndMaskTop8Bits(charac ters8(), length())); 449 ASSERT(existingHash() == StringHasher::computeHashAndMaskTop8Bits(charac ters8(), length()));
460 } 450 }
461 #endif 451 #endif
462 452
463 private: 453 private:
464 // These member variables must match the layout of StaticASCIILiteral.
465 union { // Pointers first: crbug.com/232031
466 const LChar* m_data8;
467 const UChar* m_data16;
468 };
469 unsigned m_refCount; 454 unsigned m_refCount;
470 unsigned m_length; 455 unsigned m_length;
471 mutable unsigned m_hashAndFlags; 456 mutable unsigned m_hashAndFlags;
472 }; 457 };
473 458
474 COMPILE_ASSERT(sizeof(StringImpl) == sizeof(StringImpl::StaticASCIILiteral), Str ingImpl_should_match_its_StaticASCIILiteral);
475
476 template <> 459 template <>
477 ALWAYS_INLINE const LChar* StringImpl::getCharacters<LChar>() const { return cha racters8(); } 460 ALWAYS_INLINE const LChar* StringImpl::getCharacters<LChar>() const { return cha racters8(); }
478 461
479 template <> 462 template <>
480 ALWAYS_INLINE const UChar* StringImpl::getCharacters<UChar>() const { return cha racters16(); } 463 ALWAYS_INLINE const UChar* StringImpl::getCharacters<UChar>() const { return cha racters16(); }
481 464
482 WTF_EXPORT bool equal(const StringImpl*, const StringImpl*); 465 WTF_EXPORT bool equal(const StringImpl*, const StringImpl*);
483 WTF_EXPORT bool equal(const StringImpl*, const LChar*); 466 WTF_EXPORT bool equal(const StringImpl*, const LChar*);
484 inline bool equal(const StringImpl* a, const char* b) { return equal(a, reinterp ret_cast<const LChar*>(b)); } 467 inline bool equal(const StringImpl* a, const char* b) { return equal(a, reinterp ret_cast<const LChar*>(b)); }
485 WTF_EXPORT bool equal(const StringImpl*, const LChar*, unsigned); 468 WTF_EXPORT bool equal(const StringImpl*, const LChar*, unsigned);
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
735 static inline bool isSpaceOrNewline(UChar c) 718 static inline bool isSpaceOrNewline(UChar c)
736 { 719 {
737 // Use isASCIISpace() for basic Latin-1. 720 // Use isASCIISpace() for basic Latin-1.
738 // This will include newlines, which aren't included in Unicode DirWS. 721 // This will include newlines, which aren't included in Unicode DirWS.
739 return c <= 0x7F ? WTF::isASCIISpace(c) : WTF::Unicode::direction(c) == WTF: :Unicode::WhiteSpaceNeutral; 722 return c <= 0x7F ? WTF::isASCIISpace(c) : WTF::Unicode::direction(c) == WTF: :Unicode::WhiteSpaceNeutral;
740 } 723 }
741 724
742 inline PassRefPtr<StringImpl> StringImpl::isolatedCopy() const 725 inline PassRefPtr<StringImpl> StringImpl::isolatedCopy() const
743 { 726 {
744 if (is8Bit()) 727 if (is8Bit())
745 return create(m_data8, m_length); 728 return create(characters8(), m_length);
746 return create(m_data16, m_length); 729 return create(characters16(), m_length);
747 } 730 }
748 731
749 struct StringHash; 732 struct StringHash;
750 733
751 // StringHash is the default hash for StringImpl* and RefPtr<StringImpl> 734 // StringHash is the default hash for StringImpl* and RefPtr<StringImpl>
752 template<typename T> struct DefaultHash; 735 template<typename T> struct DefaultHash;
753 template<> struct DefaultHash<StringImpl*> { 736 template<> struct DefaultHash<StringImpl*> {
754 typedef StringHash Hash; 737 typedef StringHash Hash;
755 }; 738 };
756 template<> struct DefaultHash<RefPtr<StringImpl> > { 739 template<> struct DefaultHash<RefPtr<StringImpl> > {
757 typedef StringHash Hash; 740 typedef StringHash Hash;
758 }; 741 };
759 742
760 } 743 }
761 744
762 using WTF::StringImpl; 745 using WTF::StringImpl;
763 using WTF::equal; 746 using WTF::equal;
764 using WTF::equalNonNull; 747 using WTF::equalNonNull;
765 using WTF::TextCaseSensitivity; 748 using WTF::TextCaseSensitivity;
766 using WTF::TextCaseSensitive; 749 using WTF::TextCaseSensitive;
767 using WTF::TextCaseInsensitive; 750 using WTF::TextCaseInsensitive;
768 751
769 #endif 752 #endif
OLDNEW
« no previous file with comments | « Source/core/scripts/make_names.pl ('k') | Source/wtf/text/StringImpl.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698