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

Side by Side Diff: third_party/WebKit/Source/wtf/text/AtomicString.cpp

Issue 2110813003: Move all the AtomicString table into AtomicStringTable. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix comments. Created 4 years, 5 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
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2013 Apple Inc. All rights reserv ed. 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2013 Apple Inc. All rights reserv ed.
3 * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com> 3 * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
4 * Copyright (C) 2012 Google Inc. All rights reserved. 4 * Copyright (C) 2012 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 *
11 * This library is distributed in the hope that it will be useful, 11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details. 14 * Library General Public License for more details.
15 * 15 *
16 * You should have received a copy of the GNU Library General Public License 16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to 17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA. 19 * Boston, MA 02110-1301, USA.
20 * 20 *
21 */ 21 */
22 22
23 #include "wtf/text/AtomicString.h" 23 #include "wtf/text/AtomicString.h"
24 24
25 #include "wtf/HashSet.h"
26 #include "wtf/WTFThreadData.h"
27 #include "wtf/dtoa.h" 25 #include "wtf/dtoa.h"
26 #include "wtf/text/AtomicStringTable.h"
28 #include "wtf/text/IntegerToStringConversion.h" 27 #include "wtf/text/IntegerToStringConversion.h"
29 #include "wtf/text/StringHash.h"
30 #include "wtf/text/UTF8.h"
31 28
32 namespace WTF { 29 namespace WTF {
33 30
34 using namespace Unicode;
35
36 static_assert(sizeof(AtomicString) == sizeof(String), "AtomicString and String m ust be same size"); 31 static_assert(sizeof(AtomicString) == sizeof(String), "AtomicString and String m ust be same size");
37 32
38 static inline HashSet<StringImpl*>& atomicStrings() 33 AtomicString::AtomicString(const LChar* chars, unsigned length)
34 : m_string(AtomicStringTable::instance().add(chars, length)) {}
35
36 AtomicString::AtomicString(const UChar* chars, unsigned length)
37 : m_string(AtomicStringTable::instance().add(chars, length)) {}
38
39 AtomicString::AtomicString(const UChar* chars, unsigned length, unsigned existin gHash)
40 : m_string(AtomicStringTable::instance().add(chars, length, existingHash)) { }
41
42 AtomicString::AtomicString(const UChar* chars)
43 : m_string(AtomicStringTable::instance().add(chars)) {}
44
45 AtomicString::AtomicString(StringImpl* string, unsigned offset, unsigned length)
46 : m_string(AtomicStringTable::instance().add(string, offset, length)) {}
47
48 PassRefPtr<StringImpl> AtomicString::addSlowCase(StringImpl* chars)
39 { 49 {
40 return wtfThreadData().getAtomicStringTable().table(); 50 DCHECK(!chars->isAtomic());
51 return AtomicStringTable::instance().add(chars);
41 } 52 }
42 53
43 void AtomicString::reserveTableCapacity(size_t size) 54 AtomicString AtomicString::fromUTF8(const char* chars, size_t length)
44 { 55 {
45 wtfThreadData().getAtomicStringTable().table().reserveCapacityForSize(size); 56 if (!chars)
57 return nullAtom;
58 if (!length)
59 return emptyAtom;
60 return AtomicString(AtomicStringTable::instance().addUTF8(chars, chars + len gth));
46 } 61 }
47 62
48 template<typename T, typename HashTranslator> 63 AtomicString AtomicString::fromUTF8(const char* chars)
49 static inline PassRefPtr<StringImpl> addToStringTable(const T& value)
50 { 64 {
51 HashSet<StringImpl*>::AddResult addResult = atomicStrings().addWithTranslato r<HashTranslator>(value); 65 if (!chars)
52 66 return nullAtom;
53 // If the string is newly-translated, then we need to adopt it. 67 if (!*chars)
54 // The boolean in the pair tells us if that is so. 68 return emptyAtom;
55 return addResult.isNewEntry ? adoptRef(*addResult.storedValue) : *addResult. storedValue; 69 return AtomicString(AtomicStringTable::instance().addUTF8(chars, nullptr));
56 }
57
58 template<typename CharacterType>
59 struct HashTranslatorCharBuffer {
60 const CharacterType* s;
61 unsigned length;
62 };
63
64 typedef HashTranslatorCharBuffer<UChar> UCharBuffer;
65 struct UCharBufferTranslator {
66 static unsigned hash(const UCharBuffer& buf)
67 {
68 return StringHasher::computeHashAndMaskTop8Bits(buf.s, buf.length);
69 }
70
71 static bool equal(StringImpl* const& str, const UCharBuffer& buf)
72 {
73 return WTF::equal(str, buf.s, buf.length);
74 }
75
76 static void translate(StringImpl*& location, const UCharBuffer& buf, unsigne d hash)
77 {
78 location = StringImpl::create8BitIfPossible(buf.s, buf.length).leakRef() ;
79 location->setHash(hash);
80 location->setIsAtomic(true);
81 }
82 };
83
84 template<typename CharacterType>
85 struct HashAndCharacters {
86 unsigned hash;
87 const CharacterType* characters;
88 unsigned length;
89 };
90
91 template<typename CharacterType>
92 struct HashAndCharactersTranslator {
93 static unsigned hash(const HashAndCharacters<CharacterType>& buffer)
94 {
95 ASSERT(buffer.hash == StringHasher::computeHashAndMaskTop8Bits(buffer.ch aracters, buffer.length));
96 return buffer.hash;
97 }
98
99 static bool equal(StringImpl* const& string, const HashAndCharacters<Charact erType>& buffer)
100 {
101 return WTF::equal(string, buffer.characters, buffer.length);
102 }
103
104 static void translate(StringImpl*& location, const HashAndCharacters<Charact erType>& buffer, unsigned hash)
105 {
106 location = StringImpl::create(buffer.characters, buffer.length).leakRef( );
107 location->setHash(hash);
108 location->setIsAtomic(true);
109 }
110 };
111
112 struct HashAndUTF8Characters {
113 unsigned hash;
114 const char* characters;
115 unsigned length;
116 unsigned utf16Length;
117 };
118
119 struct HashAndUTF8CharactersTranslator {
120 static unsigned hash(const HashAndUTF8Characters& buffer)
121 {
122 return buffer.hash;
123 }
124
125 static bool equal(StringImpl* const& string, const HashAndUTF8Characters& bu ffer)
126 {
127 if (buffer.utf16Length != string->length())
128 return false;
129
130 // If buffer contains only ASCII characters UTF-8 and UTF16 length are t he same.
131 if (buffer.utf16Length != buffer.length) {
132 if (string->is8Bit()) {
133 const LChar* characters8 = string->characters8();
134 return equalLatin1WithUTF8(characters8, characters8 + string->le ngth(), buffer.characters, buffer.characters + buffer.length);
135 }
136 const UChar* characters16 = string->characters16();
137 return equalUTF16WithUTF8(characters16, characters16 + string->lengt h(), buffer.characters, buffer.characters + buffer.length);
138 }
139
140 if (string->is8Bit()) {
141 const LChar* stringCharacters = string->characters8();
142
143 for (unsigned i = 0; i < buffer.length; ++i) {
144 ASSERT(isASCII(buffer.characters[i]));
145 if (stringCharacters[i] != buffer.characters[i])
146 return false;
147 }
148
149 return true;
150 }
151
152 const UChar* stringCharacters = string->characters16();
153
154 for (unsigned i = 0; i < buffer.length; ++i) {
155 ASSERT(isASCII(buffer.characters[i]));
156 if (stringCharacters[i] != buffer.characters[i])
157 return false;
158 }
159
160 return true;
161 }
162
163 static void translate(StringImpl*& location, const HashAndUTF8Characters& bu ffer, unsigned hash)
164 {
165 UChar* target;
166 RefPtr<StringImpl> newString = StringImpl::createUninitialized(buffer.ut f16Length, target);
167
168 bool isAllASCII;
169 const char* source = buffer.characters;
170 if (convertUTF8ToUTF16(&source, source + buffer.length, &target, target + buffer.utf16Length, &isAllASCII) != conversionOK)
171 ASSERT_NOT_REACHED();
172
173 if (isAllASCII)
174 newString = StringImpl::create(buffer.characters, buffer.length);
175
176 location = newString.release().leakRef();
177 location->setHash(hash);
178 location->setIsAtomic(true);
179 }
180 };
181
182 PassRefPtr<StringImpl> AtomicString::add(const UChar* s, unsigned length)
183 {
184 if (!s)
185 return nullptr;
186
187 if (!length)
188 return StringImpl::empty();
189
190 UCharBuffer buffer = { s, length };
191 return addToStringTable<UCharBuffer, UCharBufferTranslator>(buffer);
192 }
193
194 PassRefPtr<StringImpl> AtomicString::add(const UChar* s, unsigned length, unsign ed existingHash)
195 {
196 ASSERT(s);
197 ASSERT(existingHash);
198
199 if (!length)
200 return StringImpl::empty();
201
202 HashAndCharacters<UChar> buffer = { existingHash, s, length };
203 return addToStringTable<HashAndCharacters<UChar>, HashAndCharactersTranslato r<UChar>>(buffer);
204 }
205
206 PassRefPtr<StringImpl> AtomicString::add(const UChar* s)
207 {
208 if (!s)
209 return nullptr;
210
211 unsigned length = 0;
212 while (s[length] != UChar(0))
213 ++length;
214
215 if (!length)
216 return StringImpl::empty();
217
218 UCharBuffer buffer = { s, length };
219 return addToStringTable<UCharBuffer, UCharBufferTranslator>(buffer);
220 }
221
222 struct SubstringLocation {
223 StringImpl* baseString;
224 unsigned start;
225 unsigned length;
226 };
227
228 struct SubstringTranslator {
229 static unsigned hash(const SubstringLocation& buffer)
230 {
231 if (buffer.baseString->is8Bit())
232 return StringHasher::computeHashAndMaskTop8Bits(buffer.baseString->c haracters8() + buffer.start, buffer.length);
233 return StringHasher::computeHashAndMaskTop8Bits(buffer.baseString->chara cters16() + buffer.start, buffer.length);
234 }
235
236 static bool equal(StringImpl* const& string, const SubstringLocation& buffer )
237 {
238 if (buffer.baseString->is8Bit())
239 return WTF::equal(string, buffer.baseString->characters8() + buffer. start, buffer.length);
240 return WTF::equal(string, buffer.baseString->characters16() + buffer.sta rt, buffer.length);
241 }
242
243 static void translate(StringImpl*& location, const SubstringLocation& buffer , unsigned hash)
244 {
245 location = buffer.baseString->substring(buffer.start, buffer.length).lea kRef();
246 location->setHash(hash);
247 location->setIsAtomic(true);
248 }
249 };
250
251 PassRefPtr<StringImpl> AtomicString::add(StringImpl* baseString, unsigned start, unsigned length)
252 {
253 if (!baseString)
254 return nullptr;
255
256 if (!length || start >= baseString->length())
257 return StringImpl::empty();
258
259 unsigned maxLength = baseString->length() - start;
260 if (length >= maxLength) {
261 if (!start)
262 return add(baseString);
263 length = maxLength;
264 }
265
266 SubstringLocation buffer = { baseString, start, length };
267 return addToStringTable<SubstringLocation, SubstringTranslator>(buffer);
268 }
269
270 typedef HashTranslatorCharBuffer<LChar> LCharBuffer;
271 struct LCharBufferTranslator {
272 static unsigned hash(const LCharBuffer& buf)
273 {
274 return StringHasher::computeHashAndMaskTop8Bits(buf.s, buf.length);
275 }
276
277 static bool equal(StringImpl* const& str, const LCharBuffer& buf)
278 {
279 return WTF::equal(str, buf.s, buf.length);
280 }
281
282 static void translate(StringImpl*& location, const LCharBuffer& buf, unsigne d hash)
283 {
284 location = StringImpl::create(buf.s, buf.length).leakRef();
285 location->setHash(hash);
286 location->setIsAtomic(true);
287 }
288 };
289
290 PassRefPtr<StringImpl> AtomicString::add(const LChar* s, unsigned length)
291 {
292 if (!s)
293 return nullptr;
294
295 if (!length)
296 return StringImpl::empty();
297
298 LCharBuffer buffer = { s, length };
299 return addToStringTable<LCharBuffer, LCharBufferTranslator>(buffer);
300 }
301
302 PassRefPtr<StringImpl> AtomicString::addSlowCase(StringImpl* string)
303 {
304 return wtfThreadData().getAtomicStringTable().addStringImpl(string);
305 }
306
307 template<typename CharacterType>
308 static inline HashSet<StringImpl*>::iterator findString(const StringImpl* string Impl)
309 {
310 HashAndCharacters<CharacterType> buffer = { stringImpl->existingHash(), stri ngImpl->getCharacters<CharacterType>(), stringImpl->length() };
311 return atomicStrings().find<HashAndCharactersTranslator<CharacterType>>(buff er);
312 }
313
314 StringImpl* AtomicString::find(const StringImpl* stringImpl)
315 {
316 ASSERT(stringImpl);
317 ASSERT(stringImpl->existingHash());
318
319 if (!stringImpl->length())
320 return StringImpl::empty();
321
322 HashSet<StringImpl*>::iterator iterator;
323 if (stringImpl->is8Bit())
324 iterator = findString<LChar>(stringImpl);
325 else
326 iterator = findString<UChar>(stringImpl);
327 if (iterator == atomicStrings().end())
328 return 0;
329 return *iterator;
330 }
331
332 void AtomicString::remove(StringImpl* r)
333 {
334 HashSet<StringImpl*>::iterator iterator;
335 if (r->is8Bit())
336 iterator = findString<LChar>(r);
337 else
338 iterator = findString<UChar>(r);
339 RELEASE_ASSERT(iterator != atomicStrings().end());
340 atomicStrings().remove(iterator);
341 } 70 }
342 71
343 AtomicString AtomicString::lower() const 72 AtomicString AtomicString::lower() const
344 { 73 {
345 // Note: This is a hot function in the Dromaeo benchmark. 74 // Note: This is a hot function in the Dromaeo benchmark.
346 StringImpl* impl = this->impl(); 75 StringImpl* impl = this->impl();
347 if (UNLIKELY(!impl)) 76 if (UNLIKELY(!impl))
348 return *this; 77 return *this;
349 RefPtr<StringImpl> newImpl = impl->lower(); 78 RefPtr<StringImpl> newImpl = impl->lower();
350 if (LIKELY(newImpl == impl)) 79 if (LIKELY(newImpl == impl))
351 return *this; 80 return *this;
352 return AtomicString(newImpl.release()); 81 return AtomicString(newImpl.release());
353 } 82 }
354 83
355 AtomicString AtomicString::lowerASCII() const 84 AtomicString AtomicString::lowerASCII() const
356 { 85 {
357 StringImpl* impl = this->impl(); 86 StringImpl* impl = this->impl();
358 if (UNLIKELY(!impl)) 87 if (UNLIKELY(!impl))
359 return *this; 88 return *this;
360 RefPtr<StringImpl> newImpl = impl->lowerASCII(); 89 RefPtr<StringImpl> newImpl = impl->lowerASCII();
361 if (LIKELY(newImpl == impl)) 90 if (LIKELY(newImpl == impl))
362 return *this; 91 return *this;
363 return AtomicString(newImpl.release()); 92 return AtomicString(newImpl.release());
364 } 93 }
365 94
366
367 AtomicString AtomicString::fromUTF8Internal(const char* charactersStart, const c har* charactersEnd)
368 {
369 HashAndUTF8Characters buffer;
370 buffer.characters = charactersStart;
371 buffer.hash = calculateStringHashAndLengthFromUTF8MaskingTop8Bits(characters Start, charactersEnd, buffer.length, buffer.utf16Length);
372
373 if (!buffer.hash)
374 return nullAtom;
375
376 AtomicString atomicString;
377 atomicString.m_string = addToStringTable<HashAndUTF8Characters, HashAndUTF8C haractersTranslator>(buffer);
378 return atomicString;
379 }
380
381 template<typename IntegerType> 95 template<typename IntegerType>
382 static AtomicString integerToAtomicString(IntegerType input) 96 static AtomicString integerToAtomicString(IntegerType input)
383 { 97 {
384 IntegerToStringConverter<IntegerType> converter(input); 98 IntegerToStringConverter<IntegerType> converter(input);
385 return AtomicString(converter.characters8(), converter.length()); 99 return AtomicString(converter.characters8(), converter.length());
386 } 100 }
387 101
388 AtomicString AtomicString::number(int number) 102 AtomicString AtomicString::number(int number)
389 { 103 {
390 return integerToAtomicString(number); 104 return integerToAtomicString(number);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
427 } 141 }
428 142
429 #ifndef NDEBUG 143 #ifndef NDEBUG
430 void AtomicString::show() const 144 void AtomicString::show() const
431 { 145 {
432 m_string.show(); 146 m_string.show();
433 } 147 }
434 #endif 148 #endif
435 149
436 } // namespace WTF 150 } // namespace WTF
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/wtf/text/AtomicString.h ('k') | third_party/WebKit/Source/wtf/text/AtomicStringCF.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698