Changeset 58712 in webkit for trunk/JavaScriptCore/wtf/text/AtomicString.cpp
- Timestamp:
- May 3, 2010, 4:03:37 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/wtf/text/AtomicString.cpp
r58179 r58712 32 32 #include <wtf/Threading.h> 33 33 #include <wtf/WTFThreadData.h> 34 #include <wtf/text/AtomicStringTable.h>35 34 36 35 namespace WebCore { 37 36 38 static inline AtomicStringTable& table() 39 { 40 return wtfThreadData().atomicStringTable(); 41 } 37 class AtomicStringTable { 38 public: 39 static AtomicStringTable* create() 40 { 41 AtomicStringTable* table = new AtomicStringTable; 42 43 WTFThreadData& data = wtfThreadData(); 44 data.m_atomicStringTable = table; 45 data.m_atomicStringTableDestructor = AtomicStringTable::destroy; 46 47 return table; 48 } 49 50 HashSet<StringImpl*>& table() 51 { 52 return m_table; 53 } 54 55 private: 56 static void destroy(AtomicStringTable* table) 57 { 58 delete table; 59 } 60 61 HashSet<StringImpl*> m_table; 62 }; 63 64 static inline HashSet<StringImpl*>& stringTable() 65 { 66 // Once possible we should make this non-lazy (constructed in WTFThreadData's constructor). 67 AtomicStringTable* table = wtfThreadData().atomicStringTable(); 68 if (UNLIKELY(!table)) 69 table = AtomicStringTable::create(); 70 return table->table(); 71 } 72 73 struct CStringTranslator { 74 static unsigned hash(const char* c) 75 { 76 return StringImpl::computeHash(c); 77 } 78 79 static bool equal(StringImpl* r, const char* s) 80 { 81 int length = r->length(); 82 const UChar* d = r->characters(); 83 for (int i = 0; i != length; ++i) { 84 unsigned char c = s[i]; 85 if (d[i] != c) 86 return false; 87 } 88 return s[length] == 0; 89 } 90 91 static void translate(StringImpl*& location, const char* const& c, unsigned hash) 92 { 93 location = StringImpl::create(c).releaseRef(); 94 location->setHash(hash); 95 location->setInTable(); 96 } 97 }; 42 98 43 99 bool operator==(const AtomicString& a, const char* b) … … 48 104 if ((!impl || !impl->characters()) || !b) 49 105 return false; 50 return ::equal(impl, b);106 return CStringTranslator::equal(impl, b); 51 107 } 52 108 … … 56 112 return 0; 57 113 if (!*c) 58 return StringImpl::empty(); 59 return table().add(c); 60 } 114 return StringImpl::empty(); 115 pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<const char*, CStringTranslator>(c); 116 if (!addResult.second) 117 return *addResult.first; 118 return adoptRef(*addResult.first); 119 } 120 121 struct UCharBuffer { 122 const UChar* s; 123 unsigned length; 124 }; 125 126 static inline bool equal(StringImpl* string, const UChar* characters, unsigned length) 127 { 128 if (string->length() != length) 129 return false; 130 131 // FIXME: perhaps we should have a more abstract macro that indicates when 132 // going 4 bytes at a time is unsafe 133 #if CPU(ARM) || CPU(SH4) 134 const UChar* stringCharacters = string->characters(); 135 for (unsigned i = 0; i != length; ++i) { 136 if (*stringCharacters++ != *characters++) 137 return false; 138 } 139 return true; 140 #else 141 /* Do it 4-bytes-at-a-time on architectures where it's safe */ 142 143 const uint32_t* stringCharacters = reinterpret_cast<const uint32_t*>(string->characters()); 144 const uint32_t* bufferCharacters = reinterpret_cast<const uint32_t*>(characters); 145 146 unsigned halfLength = length >> 1; 147 for (unsigned i = 0; i != halfLength; ++i) { 148 if (*stringCharacters++ != *bufferCharacters++) 149 return false; 150 } 151 152 if (length & 1 && *reinterpret_cast<const uint16_t*>(stringCharacters) != *reinterpret_cast<const uint16_t*>(bufferCharacters)) 153 return false; 154 155 return true; 156 #endif 157 } 158 159 struct UCharBufferTranslator { 160 static unsigned hash(const UCharBuffer& buf) 161 { 162 return StringImpl::computeHash(buf.s, buf.length); 163 } 164 165 static bool equal(StringImpl* const& str, const UCharBuffer& buf) 166 { 167 return WebCore::equal(str, buf.s, buf.length); 168 } 169 170 static void translate(StringImpl*& location, const UCharBuffer& buf, unsigned hash) 171 { 172 location = StringImpl::create(buf.s, buf.length).releaseRef(); 173 location->setHash(hash); 174 location->setInTable(); 175 } 176 }; 177 178 struct HashAndCharacters { 179 unsigned hash; 180 const UChar* characters; 181 unsigned length; 182 }; 183 184 struct HashAndCharactersTranslator { 185 static unsigned hash(const HashAndCharacters& buffer) 186 { 187 ASSERT(buffer.hash == StringImpl::computeHash(buffer.characters, buffer.length)); 188 return buffer.hash; 189 } 190 191 static bool equal(StringImpl* const& string, const HashAndCharacters& buffer) 192 { 193 return WebCore::equal(string, buffer.characters, buffer.length); 194 } 195 196 static void translate(StringImpl*& location, const HashAndCharacters& buffer, unsigned hash) 197 { 198 location = StringImpl::create(buffer.characters, buffer.length).releaseRef(); 199 location->setHash(hash); 200 location->setInTable(); 201 } 202 }; 61 203 62 204 PassRefPtr<StringImpl> AtomicString::add(const UChar* s, unsigned length) … … 68 210 return StringImpl::empty(); 69 211 70 return table().add(s, length); 212 UCharBuffer buf = { s, length }; 213 pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<UCharBuffer, UCharBufferTranslator>(buf); 214 215 // If the string is newly-translated, then we need to adopt it. 216 // The boolean in the pair tells us if that is so. 217 return addResult.second ? adoptRef(*addResult.first) : *addResult.first; 71 218 } 72 219 … … 78 225 if (length == 0) 79 226 return StringImpl::empty(); 80 81 return table().add(s, length, existingHash); 227 228 HashAndCharacters buffer = { existingHash, s, length }; 229 pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<HashAndCharacters, HashAndCharactersTranslator>(buffer); 230 if (!addResult.second) 231 return *addResult.first; 232 return adoptRef(*addResult.first); 82 233 } 83 234 … … 87 238 return 0; 88 239 89 unsignedlength = 0;240 int length = 0; 90 241 while (s[length] != UChar(0)) 91 242 length++; … … 94 245 return StringImpl::empty(); 95 246 96 return table().add(s, length); 247 UCharBuffer buf = {s, length}; 248 pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<UCharBuffer, UCharBufferTranslator>(buf); 249 250 // If the string is newly-translated, then we need to adopt it. 251 // The boolean in the pair tells us if that is so. 252 return addResult.second ? adoptRef(*addResult.first) : *addResult.first; 97 253 } 98 254 99 255 PassRefPtr<StringImpl> AtomicString::add(StringImpl* r) 100 256 { 101 if (!r || r->i sAtomic())257 if (!r || r->inTable()) 102 258 return r; 103 259 104 // The singleton empty string is atomic.105 ASSERT(r->length());260 if (r->length() == 0) 261 return StringImpl::empty(); 106 262 107 return table().add(r); 263 StringImpl* result = *stringTable().add(r).first; 264 if (result == r) 265 r->setInTable(); 266 return result; 108 267 } 109 268 … … 115 274 if (length == 0) 116 275 return static_cast<AtomicStringImpl*>(StringImpl::empty()); 117 118 return static_cast<AtomicStringImpl*>(table().find(s, length, existingHash)); 276 277 HashAndCharacters buffer = { existingHash, s, length }; 278 HashSet<StringImpl*>::iterator iterator = stringTable().find<HashAndCharacters, HashAndCharactersTranslator>(buffer); 279 if (iterator == stringTable().end()) 280 return 0; 281 return static_cast<AtomicStringImpl*>(*iterator); 119 282 } 120 283 121 284 void AtomicString::remove(StringImpl* r) 122 285 { 123 table().remove(r);286 stringTable().remove(r); 124 287 } 125 288
Note:
See TracChangeset
for help on using the changeset viewer.