OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/symbols.h" | 5 #include "vm/symbols.h" |
6 | 6 |
7 #include "vm/handles.h" | 7 #include "vm/handles.h" |
8 #include "vm/hash_table.h" | 8 #include "vm/hash_table.h" |
9 #include "vm/isolate.h" | 9 #include "vm/isolate.h" |
10 #include "vm/object.h" | 10 #include "vm/object.h" |
(...skipping 20 matching lines...) Expand all Loading... |
31 DART_TOKEN_LIST(DEFINE_TOKEN_SYMBOL_INDEX) | 31 DART_TOKEN_LIST(DEFINE_TOKEN_SYMBOL_INDEX) |
32 DART_KEYWORD_LIST(DEFINE_TOKEN_SYMBOL_INDEX) | 32 DART_KEYWORD_LIST(DEFINE_TOKEN_SYMBOL_INDEX) |
33 #undef DEFINE_TOKEN_SYMBOL_INDEX | 33 #undef DEFINE_TOKEN_SYMBOL_INDEX |
34 // clang-format on | 34 // clang-format on |
35 }; | 35 }; |
36 | 36 |
37 RawString* StringFrom(const uint8_t* data, intptr_t len, Heap::Space space) { | 37 RawString* StringFrom(const uint8_t* data, intptr_t len, Heap::Space space) { |
38 return String::FromLatin1(data, len, space); | 38 return String::FromLatin1(data, len, space); |
39 } | 39 } |
40 | 40 |
41 | |
42 RawString* StringFrom(const uint16_t* data, intptr_t len, Heap::Space space) { | 41 RawString* StringFrom(const uint16_t* data, intptr_t len, Heap::Space space) { |
43 return String::FromUTF16(data, len, space); | 42 return String::FromUTF16(data, len, space); |
44 } | 43 } |
45 | 44 |
46 | |
47 RawString* StringFrom(const int32_t* data, intptr_t len, Heap::Space space) { | 45 RawString* StringFrom(const int32_t* data, intptr_t len, Heap::Space space) { |
48 return String::FromUTF32(data, len, space); | 46 return String::FromUTF32(data, len, space); |
49 } | 47 } |
50 | 48 |
51 | |
52 template <typename CharType> | 49 template <typename CharType> |
53 class CharArray { | 50 class CharArray { |
54 public: | 51 public: |
55 CharArray(const CharType* data, intptr_t len) : data_(data), len_(len) { | 52 CharArray(const CharType* data, intptr_t len) : data_(data), len_(len) { |
56 hash_ = String::Hash(data, len); | 53 hash_ = String::Hash(data, len); |
57 } | 54 } |
58 RawString* ToSymbol() const { | 55 RawString* ToSymbol() const { |
59 String& result = String::Handle(StringFrom(data_, len_, Heap::kOld)); | 56 String& result = String::Handle(StringFrom(data_, len_, Heap::kOld)); |
60 result.SetCanonical(); | 57 result.SetCanonical(); |
61 result.SetHash(hash_); | 58 result.SetHash(hash_); |
(...skipping 10 matching lines...) Expand all Loading... |
72 | 69 |
73 private: | 70 private: |
74 const CharType* data_; | 71 const CharType* data_; |
75 intptr_t len_; | 72 intptr_t len_; |
76 intptr_t hash_; | 73 intptr_t hash_; |
77 }; | 74 }; |
78 typedef CharArray<uint8_t> Latin1Array; | 75 typedef CharArray<uint8_t> Latin1Array; |
79 typedef CharArray<uint16_t> UTF16Array; | 76 typedef CharArray<uint16_t> UTF16Array; |
80 typedef CharArray<int32_t> UTF32Array; | 77 typedef CharArray<int32_t> UTF32Array; |
81 | 78 |
82 | |
83 class StringSlice { | 79 class StringSlice { |
84 public: | 80 public: |
85 StringSlice(const String& str, intptr_t begin_index, intptr_t length) | 81 StringSlice(const String& str, intptr_t begin_index, intptr_t length) |
86 : str_(str), begin_index_(begin_index), len_(length) { | 82 : str_(str), begin_index_(begin_index), len_(length) { |
87 hash_ = is_all() ? str.Hash() : String::Hash(str, begin_index, length); | 83 hash_ = is_all() ? str.Hash() : String::Hash(str, begin_index, length); |
88 } | 84 } |
89 RawString* ToSymbol() const; | 85 RawString* ToSymbol() const; |
90 bool Equals(const String& other) const { | 86 bool Equals(const String& other) const { |
91 ASSERT(other.HasHash()); | 87 ASSERT(other.HasHash()); |
92 if (other.Hash() != hash_) { | 88 if (other.Hash() != hash_) { |
93 return false; | 89 return false; |
94 } | 90 } |
95 return other.Equals(str_, begin_index_, len_); | 91 return other.Equals(str_, begin_index_, len_); |
96 } | 92 } |
97 intptr_t Hash() const { return hash_; } | 93 intptr_t Hash() const { return hash_; } |
98 | 94 |
99 private: | 95 private: |
100 bool is_all() const { return begin_index_ == 0 && len_ == str_.Length(); } | 96 bool is_all() const { return begin_index_ == 0 && len_ == str_.Length(); } |
101 const String& str_; | 97 const String& str_; |
102 intptr_t begin_index_; | 98 intptr_t begin_index_; |
103 intptr_t len_; | 99 intptr_t len_; |
104 intptr_t hash_; | 100 intptr_t hash_; |
105 }; | 101 }; |
106 | 102 |
107 | |
108 RawString* StringSlice::ToSymbol() const { | 103 RawString* StringSlice::ToSymbol() const { |
109 if (is_all() && str_.IsOld()) { | 104 if (is_all() && str_.IsOld()) { |
110 str_.SetCanonical(); | 105 str_.SetCanonical(); |
111 return str_.raw(); | 106 return str_.raw(); |
112 } else { | 107 } else { |
113 String& result = | 108 String& result = |
114 String::Handle(String::SubString(str_, begin_index_, len_, Heap::kOld)); | 109 String::Handle(String::SubString(str_, begin_index_, len_, Heap::kOld)); |
115 result.SetCanonical(); | 110 result.SetCanonical(); |
116 result.SetHash(hash_); | 111 result.SetHash(hash_); |
117 return result.raw(); | 112 return result.raw(); |
118 } | 113 } |
119 } | 114 } |
120 | 115 |
121 | |
122 class ConcatString { | 116 class ConcatString { |
123 public: | 117 public: |
124 ConcatString(const String& str1, const String& str2) | 118 ConcatString(const String& str1, const String& str2) |
125 : str1_(str1), str2_(str2), hash_(String::HashConcat(str1, str2)) {} | 119 : str1_(str1), str2_(str2), hash_(String::HashConcat(str1, str2)) {} |
126 RawString* ToSymbol() const; | 120 RawString* ToSymbol() const; |
127 bool Equals(const String& other) const { | 121 bool Equals(const String& other) const { |
128 ASSERT(other.HasHash()); | 122 ASSERT(other.HasHash()); |
129 if (other.Hash() != hash_) { | 123 if (other.Hash() != hash_) { |
130 return false; | 124 return false; |
131 } | 125 } |
132 return other.EqualsConcat(str1_, str2_); | 126 return other.EqualsConcat(str1_, str2_); |
133 } | 127 } |
134 intptr_t Hash() const { return hash_; } | 128 intptr_t Hash() const { return hash_; } |
135 | 129 |
136 private: | 130 private: |
137 const String& str1_; | 131 const String& str1_; |
138 const String& str2_; | 132 const String& str2_; |
139 intptr_t hash_; | 133 intptr_t hash_; |
140 }; | 134 }; |
141 | 135 |
142 | |
143 RawString* ConcatString::ToSymbol() const { | 136 RawString* ConcatString::ToSymbol() const { |
144 String& result = String::Handle(String::Concat(str1_, str2_, Heap::kOld)); | 137 String& result = String::Handle(String::Concat(str1_, str2_, Heap::kOld)); |
145 result.SetCanonical(); | 138 result.SetCanonical(); |
146 result.SetHash(hash_); | 139 result.SetHash(hash_); |
147 return result.raw(); | 140 return result.raw(); |
148 } | 141 } |
149 | 142 |
150 | |
151 class SymbolTraits { | 143 class SymbolTraits { |
152 public: | 144 public: |
153 static const char* Name() { return "SymbolTraits"; } | 145 static const char* Name() { return "SymbolTraits"; } |
154 static bool ReportStats() { return false; } | 146 static bool ReportStats() { return false; } |
155 | 147 |
156 static bool IsMatch(const Object& a, const Object& b) { | 148 static bool IsMatch(const Object& a, const Object& b) { |
157 const String& a_str = String::Cast(a); | 149 const String& a_str = String::Cast(a); |
158 const String& b_str = String::Cast(b); | 150 const String& b_str = String::Cast(b); |
159 ASSERT(a_str.HasHash()); | 151 ASSERT(a_str.HasHash()); |
160 ASSERT(b_str.HasHash()); | 152 ASSERT(b_str.HasHash()); |
(...skipping 30 matching lines...) Expand all Loading... |
191 } | 183 } |
192 static RawObject* NewKey(const StringSlice& slice) { | 184 static RawObject* NewKey(const StringSlice& slice) { |
193 return slice.ToSymbol(); | 185 return slice.ToSymbol(); |
194 } | 186 } |
195 static RawObject* NewKey(const ConcatString& concat) { | 187 static RawObject* NewKey(const ConcatString& concat) { |
196 return concat.ToSymbol(); | 188 return concat.ToSymbol(); |
197 } | 189 } |
198 }; | 190 }; |
199 typedef UnorderedHashSet<SymbolTraits> SymbolTable; | 191 typedef UnorderedHashSet<SymbolTraits> SymbolTable; |
200 | 192 |
201 | |
202 const char* Symbols::Name(SymbolId symbol) { | 193 const char* Symbols::Name(SymbolId symbol) { |
203 ASSERT((symbol > kIllegal) && (symbol < kNullCharId)); | 194 ASSERT((symbol > kIllegal) && (symbol < kNullCharId)); |
204 return names[symbol]; | 195 return names[symbol]; |
205 } | 196 } |
206 | 197 |
207 | |
208 const String& Symbols::Token(Token::Kind token) { | 198 const String& Symbols::Token(Token::Kind token) { |
209 const int tok_index = token; | 199 const int tok_index = token; |
210 ASSERT((0 <= tok_index) && (tok_index < Token::kNumTokens)); | 200 ASSERT((0 <= tok_index) && (tok_index < Token::kNumTokens)); |
211 // First keyword symbol is in symbol_handles_[kTokenTableStart + 1]. | 201 // First keyword symbol is in symbol_handles_[kTokenTableStart + 1]. |
212 const intptr_t token_id = Symbols::kTokenTableStart + 1 + tok_index; | 202 const intptr_t token_id = Symbols::kTokenTableStart + 1 + tok_index; |
213 ASSERT(symbol_handles_[token_id] != NULL); | 203 ASSERT(symbol_handles_[token_id] != NULL); |
214 return *symbol_handles_[token_id]; | 204 return *symbol_handles_[token_id]; |
215 } | 205 } |
216 | 206 |
217 | |
218 void Symbols::InitOnce(Isolate* vm_isolate) { | 207 void Symbols::InitOnce(Isolate* vm_isolate) { |
219 // Should only be run by the vm isolate. | 208 // Should only be run by the vm isolate. |
220 ASSERT(Isolate::Current() == Dart::vm_isolate()); | 209 ASSERT(Isolate::Current() == Dart::vm_isolate()); |
221 ASSERT(vm_isolate == Dart::vm_isolate()); | 210 ASSERT(vm_isolate == Dart::vm_isolate()); |
222 Zone* zone = Thread::Current()->zone(); | 211 Zone* zone = Thread::Current()->zone(); |
223 | 212 |
224 // Create and setup a symbol table in the vm isolate. | 213 // Create and setup a symbol table in the vm isolate. |
225 SetupSymbolTable(vm_isolate); | 214 SetupSymbolTable(vm_isolate); |
226 | 215 |
227 // Create all predefined symbols. | 216 // Create all predefined symbols. |
(...skipping 26 matching lines...) Expand all Loading... |
254 *str ^= table.InsertOrGet(*str); | 243 *str ^= table.InsertOrGet(*str); |
255 ASSERT(predefined_[c] == NULL); | 244 ASSERT(predefined_[c] == NULL); |
256 str->SetCanonical(); // Make canonical once entered. | 245 str->SetCanonical(); // Make canonical once entered. |
257 predefined_[c] = str->raw(); | 246 predefined_[c] = str->raw(); |
258 symbol_handles_[idx] = str; | 247 symbol_handles_[idx] = str; |
259 } | 248 } |
260 | 249 |
261 vm_isolate->object_store()->set_symbol_table(table.Release()); | 250 vm_isolate->object_store()->set_symbol_table(table.Release()); |
262 } | 251 } |
263 | 252 |
264 | |
265 void Symbols::InitOnceFromSnapshot(Isolate* vm_isolate) { | 253 void Symbols::InitOnceFromSnapshot(Isolate* vm_isolate) { |
266 // Should only be run by the vm isolate. | 254 // Should only be run by the vm isolate. |
267 ASSERT(Isolate::Current() == Dart::vm_isolate()); | 255 ASSERT(Isolate::Current() == Dart::vm_isolate()); |
268 ASSERT(vm_isolate == Dart::vm_isolate()); | 256 ASSERT(vm_isolate == Dart::vm_isolate()); |
269 Zone* zone = Thread::Current()->zone(); | 257 Zone* zone = Thread::Current()->zone(); |
270 | 258 |
271 SymbolTable table(zone, vm_isolate->object_store()->symbol_table()); | 259 SymbolTable table(zone, vm_isolate->object_store()->symbol_table()); |
272 | 260 |
273 // Lookup all the predefined string symbols and language keyword symbols | 261 // Lookup all the predefined string symbols and language keyword symbols |
274 // and cache them in the read only handles for fast access. | 262 // and cache them in the read only handles for fast access. |
(...skipping 20 matching lines...) Expand all Loading... |
295 ASSERT(!str->IsNull()); | 283 ASSERT(!str->IsNull()); |
296 ASSERT(str->HasHash()); | 284 ASSERT(str->HasHash()); |
297 ASSERT(str->IsCanonical()); | 285 ASSERT(str->IsCanonical()); |
298 predefined_[c] = str->raw(); | 286 predefined_[c] = str->raw(); |
299 symbol_handles_[idx] = str; | 287 symbol_handles_[idx] = str; |
300 } | 288 } |
301 | 289 |
302 vm_isolate->object_store()->set_symbol_table(table.Release()); | 290 vm_isolate->object_store()->set_symbol_table(table.Release()); |
303 } | 291 } |
304 | 292 |
305 | |
306 void Symbols::SetupSymbolTable(Isolate* isolate) { | 293 void Symbols::SetupSymbolTable(Isolate* isolate) { |
307 ASSERT(isolate != NULL); | 294 ASSERT(isolate != NULL); |
308 | 295 |
309 // Setup the symbol table used within the String class. | 296 // Setup the symbol table used within the String class. |
310 const intptr_t initial_size = (isolate == Dart::vm_isolate()) | 297 const intptr_t initial_size = (isolate == Dart::vm_isolate()) |
311 ? kInitialVMIsolateSymtabSize | 298 ? kInitialVMIsolateSymtabSize |
312 : kInitialSymtabSize; | 299 : kInitialSymtabSize; |
313 Array& array = | 300 Array& array = |
314 Array::Handle(HashTables::New<SymbolTable>(initial_size, Heap::kOld)); | 301 Array::Handle(HashTables::New<SymbolTable>(initial_size, Heap::kOld)); |
315 isolate->object_store()->set_symbol_table(array); | 302 isolate->object_store()->set_symbol_table(array); |
316 } | 303 } |
317 | 304 |
318 | |
319 RawArray* Symbols::UnifiedSymbolTable() { | 305 RawArray* Symbols::UnifiedSymbolTable() { |
320 Thread* thread = Thread::Current(); | 306 Thread* thread = Thread::Current(); |
321 Isolate* isolate = thread->isolate(); | 307 Isolate* isolate = thread->isolate(); |
322 Zone* zone = thread->zone(); | 308 Zone* zone = thread->zone(); |
323 | 309 |
324 ASSERT(thread->IsMutatorThread()); | 310 ASSERT(thread->IsMutatorThread()); |
325 ASSERT(isolate->background_compiler() == NULL); | 311 ASSERT(isolate->background_compiler() == NULL); |
326 | 312 |
327 SymbolTable vm_table(zone, | 313 SymbolTable vm_table(zone, |
328 Dart::vm_isolate()->object_store()->symbol_table()); | 314 Dart::vm_isolate()->object_store()->symbol_table()); |
(...skipping 17 matching lines...) Expand all Loading... |
346 symbol ^= table.GetKey(iter.Current()); | 332 symbol ^= table.GetKey(iter.Current()); |
347 ASSERT(!symbol.IsNull()); | 333 ASSERT(!symbol.IsNull()); |
348 bool present = unified_table.Insert(symbol); | 334 bool present = unified_table.Insert(symbol); |
349 ASSERT(!present); | 335 ASSERT(!present); |
350 } | 336 } |
351 table.Release(); | 337 table.Release(); |
352 | 338 |
353 return unified_table.Release().raw(); | 339 return unified_table.Release().raw(); |
354 } | 340 } |
355 | 341 |
356 | |
357 void Symbols::Compact(Isolate* isolate) { | 342 void Symbols::Compact(Isolate* isolate) { |
358 ASSERT(isolate != Dart::vm_isolate()); | 343 ASSERT(isolate != Dart::vm_isolate()); |
359 Zone* zone = Thread::Current()->zone(); | 344 Zone* zone = Thread::Current()->zone(); |
360 | 345 |
361 // 1. Drop the symbol table and do a full garbage collection. | 346 // 1. Drop the symbol table and do a full garbage collection. |
362 isolate->object_store()->set_symbol_table(Object::empty_array()); | 347 isolate->object_store()->set_symbol_table(Object::empty_array()); |
363 isolate->heap()->CollectAllGarbage(); | 348 isolate->heap()->CollectAllGarbage(); |
364 | 349 |
365 // 2. Walk the heap to find surviving symbols. | 350 // 2. Walk the heap to find surviving symbols. |
366 GrowableArray<String*> symbols; | 351 GrowableArray<String*> symbols; |
(...skipping 23 matching lines...) Expand all Loading... |
390 for (intptr_t i = 0; i < symbols.length(); i++) { | 375 for (intptr_t i = 0; i < symbols.length(); i++) { |
391 String& symbol = *symbols[i]; | 376 String& symbol = *symbols[i]; |
392 ASSERT(symbol.IsString()); | 377 ASSERT(symbol.IsString()); |
393 ASSERT(symbol.IsCanonical()); | 378 ASSERT(symbol.IsCanonical()); |
394 bool present = table.Insert(symbol); | 379 bool present = table.Insert(symbol); |
395 ASSERT(!present); | 380 ASSERT(!present); |
396 } | 381 } |
397 isolate->object_store()->set_symbol_table(table.Release()); | 382 isolate->object_store()->set_symbol_table(table.Release()); |
398 } | 383 } |
399 | 384 |
400 | |
401 void Symbols::GetStats(Isolate* isolate, intptr_t* size, intptr_t* capacity) { | 385 void Symbols::GetStats(Isolate* isolate, intptr_t* size, intptr_t* capacity) { |
402 ASSERT(isolate != NULL); | 386 ASSERT(isolate != NULL); |
403 SymbolTable table(isolate->object_store()->symbol_table()); | 387 SymbolTable table(isolate->object_store()->symbol_table()); |
404 *size = table.NumOccupied(); | 388 *size = table.NumOccupied(); |
405 *capacity = table.NumEntries(); | 389 *capacity = table.NumEntries(); |
406 table.Release(); | 390 table.Release(); |
407 } | 391 } |
408 | 392 |
409 | |
410 RawString* Symbols::New(Thread* thread, const char* cstr, intptr_t len) { | 393 RawString* Symbols::New(Thread* thread, const char* cstr, intptr_t len) { |
411 ASSERT((cstr != NULL) && (len >= 0)); | 394 ASSERT((cstr != NULL) && (len >= 0)); |
412 const uint8_t* utf8_array = reinterpret_cast<const uint8_t*>(cstr); | 395 const uint8_t* utf8_array = reinterpret_cast<const uint8_t*>(cstr); |
413 return Symbols::FromUTF8(thread, utf8_array, len); | 396 return Symbols::FromUTF8(thread, utf8_array, len); |
414 } | 397 } |
415 | 398 |
416 | |
417 RawString* Symbols::FromUTF8(Thread* thread, | 399 RawString* Symbols::FromUTF8(Thread* thread, |
418 const uint8_t* utf8_array, | 400 const uint8_t* utf8_array, |
419 intptr_t array_len) { | 401 intptr_t array_len) { |
420 if (array_len == 0 || utf8_array == NULL) { | 402 if (array_len == 0 || utf8_array == NULL) { |
421 return FromLatin1(thread, reinterpret_cast<uint8_t*>(NULL), 0); | 403 return FromLatin1(thread, reinterpret_cast<uint8_t*>(NULL), 0); |
422 } | 404 } |
423 Utf8::Type type; | 405 Utf8::Type type; |
424 intptr_t len = Utf8::CodeUnitCount(utf8_array, array_len, &type); | 406 intptr_t len = Utf8::CodeUnitCount(utf8_array, array_len, &type); |
425 ASSERT(len != 0); | 407 ASSERT(len != 0); |
426 Zone* zone = thread->zone(); | 408 Zone* zone = thread->zone(); |
427 if (type == Utf8::kLatin1) { | 409 if (type == Utf8::kLatin1) { |
428 uint8_t* characters = zone->Alloc<uint8_t>(len); | 410 uint8_t* characters = zone->Alloc<uint8_t>(len); |
429 Utf8::DecodeToLatin1(utf8_array, array_len, characters, len); | 411 Utf8::DecodeToLatin1(utf8_array, array_len, characters, len); |
430 return FromLatin1(thread, characters, len); | 412 return FromLatin1(thread, characters, len); |
431 } | 413 } |
432 ASSERT((type == Utf8::kBMP) || (type == Utf8::kSupplementary)); | 414 ASSERT((type == Utf8::kBMP) || (type == Utf8::kSupplementary)); |
433 uint16_t* characters = zone->Alloc<uint16_t>(len); | 415 uint16_t* characters = zone->Alloc<uint16_t>(len); |
434 Utf8::DecodeToUTF16(utf8_array, array_len, characters, len); | 416 Utf8::DecodeToUTF16(utf8_array, array_len, characters, len); |
435 return FromUTF16(thread, characters, len); | 417 return FromUTF16(thread, characters, len); |
436 } | 418 } |
437 | 419 |
438 | |
439 RawString* Symbols::FromLatin1(Thread* thread, | 420 RawString* Symbols::FromLatin1(Thread* thread, |
440 const uint8_t* latin1_array, | 421 const uint8_t* latin1_array, |
441 intptr_t len) { | 422 intptr_t len) { |
442 return NewSymbol(thread, Latin1Array(latin1_array, len)); | 423 return NewSymbol(thread, Latin1Array(latin1_array, len)); |
443 } | 424 } |
444 | 425 |
445 | |
446 RawString* Symbols::FromUTF16(Thread* thread, | 426 RawString* Symbols::FromUTF16(Thread* thread, |
447 const uint16_t* utf16_array, | 427 const uint16_t* utf16_array, |
448 intptr_t len) { | 428 intptr_t len) { |
449 return NewSymbol(thread, UTF16Array(utf16_array, len)); | 429 return NewSymbol(thread, UTF16Array(utf16_array, len)); |
450 } | 430 } |
451 | 431 |
452 | |
453 RawString* Symbols::FromUTF32(Thread* thread, | 432 RawString* Symbols::FromUTF32(Thread* thread, |
454 const int32_t* utf32_array, | 433 const int32_t* utf32_array, |
455 intptr_t len) { | 434 intptr_t len) { |
456 return NewSymbol(thread, UTF32Array(utf32_array, len)); | 435 return NewSymbol(thread, UTF32Array(utf32_array, len)); |
457 } | 436 } |
458 | 437 |
459 | |
460 RawString* Symbols::FromConcat(Thread* thread, | 438 RawString* Symbols::FromConcat(Thread* thread, |
461 const String& str1, | 439 const String& str1, |
462 const String& str2) { | 440 const String& str2) { |
463 if (str1.Length() == 0) { | 441 if (str1.Length() == 0) { |
464 return New(thread, str2); | 442 return New(thread, str2); |
465 } else if (str2.Length() == 0) { | 443 } else if (str2.Length() == 0) { |
466 return New(thread, str1); | 444 return New(thread, str1); |
467 } else { | 445 } else { |
468 return NewSymbol(thread, ConcatString(str1, str2)); | 446 return NewSymbol(thread, ConcatString(str1, str2)); |
469 } | 447 } |
470 } | 448 } |
471 | 449 |
472 | |
473 RawString* Symbols::FromGet(Thread* thread, const String& str) { | 450 RawString* Symbols::FromGet(Thread* thread, const String& str) { |
474 return FromConcat(thread, GetterPrefix(), str); | 451 return FromConcat(thread, GetterPrefix(), str); |
475 } | 452 } |
476 | 453 |
477 | |
478 RawString* Symbols::FromSet(Thread* thread, const String& str) { | 454 RawString* Symbols::FromSet(Thread* thread, const String& str) { |
479 return FromConcat(thread, SetterPrefix(), str); | 455 return FromConcat(thread, SetterPrefix(), str); |
480 } | 456 } |
481 | 457 |
482 | |
483 RawString* Symbols::FromDot(Thread* thread, const String& str) { | 458 RawString* Symbols::FromDot(Thread* thread, const String& str) { |
484 return FromConcat(thread, str, Dot()); | 459 return FromConcat(thread, str, Dot()); |
485 } | 460 } |
486 | 461 |
487 | |
488 // TODO(srdjan): If this becomes performance critical code, consider looking | 462 // TODO(srdjan): If this becomes performance critical code, consider looking |
489 // up symbol from hash of pieces instead of concatenating them first into | 463 // up symbol from hash of pieces instead of concatenating them first into |
490 // a string. | 464 // a string. |
491 RawString* Symbols::FromConcatAll( | 465 RawString* Symbols::FromConcatAll( |
492 Thread* thread, | 466 Thread* thread, |
493 const GrowableHandlePtrArray<const String>& strs) { | 467 const GrowableHandlePtrArray<const String>& strs) { |
494 const intptr_t strs_length = strs.length(); | 468 const intptr_t strs_length = strs.length(); |
495 GrowableArray<intptr_t> lengths(strs_length); | 469 GrowableArray<intptr_t> lengths(strs_length); |
496 | 470 |
497 intptr_t len_sum = 0; | 471 intptr_t len_sum = 0; |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
553 } | 527 } |
554 } | 528 } |
555 buffer += str_len; | 529 buffer += str_len; |
556 } | 530 } |
557 } | 531 } |
558 ASSERT(len_sum == buffer - orig_buffer); | 532 ASSERT(len_sum == buffer - orig_buffer); |
559 return Symbols::FromUTF16(thread, orig_buffer, len_sum); | 533 return Symbols::FromUTF16(thread, orig_buffer, len_sum); |
560 } | 534 } |
561 } | 535 } |
562 | 536 |
563 | |
564 // StringType can be StringSlice, ConcatString, or {Latin1,UTF16,UTF32}Array. | 537 // StringType can be StringSlice, ConcatString, or {Latin1,UTF16,UTF32}Array. |
565 template <typename StringType> | 538 template <typename StringType> |
566 RawString* Symbols::NewSymbol(Thread* thread, const StringType& str) { | 539 RawString* Symbols::NewSymbol(Thread* thread, const StringType& str) { |
567 REUSABLE_OBJECT_HANDLESCOPE(thread); | 540 REUSABLE_OBJECT_HANDLESCOPE(thread); |
568 REUSABLE_SMI_HANDLESCOPE(thread); | 541 REUSABLE_SMI_HANDLESCOPE(thread); |
569 REUSABLE_ARRAY_HANDLESCOPE(thread); | 542 REUSABLE_ARRAY_HANDLESCOPE(thread); |
570 String& symbol = String::Handle(thread->zone()); | 543 String& symbol = String::Handle(thread->zone()); |
571 dart::Object& key = thread->ObjectHandle(); | 544 dart::Object& key = thread->ObjectHandle(); |
572 Smi& value = thread->SmiHandle(); | 545 Smi& value = thread->SmiHandle(); |
573 Array& data = thread->ArrayHandle(); | 546 Array& data = thread->ArrayHandle(); |
(...skipping 10 matching lines...) Expand all Loading... |
584 data ^= isolate->object_store()->symbol_table(); | 557 data ^= isolate->object_store()->symbol_table(); |
585 SymbolTable table(&key, &value, &data); | 558 SymbolTable table(&key, &value, &data); |
586 symbol ^= table.InsertNewOrGet(str); | 559 symbol ^= table.InsertNewOrGet(str); |
587 isolate->object_store()->set_symbol_table(table.Release()); | 560 isolate->object_store()->set_symbol_table(table.Release()); |
588 } | 561 } |
589 ASSERT(symbol.IsSymbol()); | 562 ASSERT(symbol.IsSymbol()); |
590 ASSERT(symbol.HasHash()); | 563 ASSERT(symbol.HasHash()); |
591 return symbol.raw(); | 564 return symbol.raw(); |
592 } | 565 } |
593 | 566 |
594 | |
595 template <typename StringType> | 567 template <typename StringType> |
596 RawString* Symbols::Lookup(Thread* thread, const StringType& str) { | 568 RawString* Symbols::Lookup(Thread* thread, const StringType& str) { |
597 REUSABLE_OBJECT_HANDLESCOPE(thread); | 569 REUSABLE_OBJECT_HANDLESCOPE(thread); |
598 REUSABLE_SMI_HANDLESCOPE(thread); | 570 REUSABLE_SMI_HANDLESCOPE(thread); |
599 REUSABLE_ARRAY_HANDLESCOPE(thread); | 571 REUSABLE_ARRAY_HANDLESCOPE(thread); |
600 String& symbol = String::Handle(thread->zone()); | 572 String& symbol = String::Handle(thread->zone()); |
601 dart::Object& key = thread->ObjectHandle(); | 573 dart::Object& key = thread->ObjectHandle(); |
602 Smi& value = thread->SmiHandle(); | 574 Smi& value = thread->SmiHandle(); |
603 Array& data = thread->ArrayHandle(); | 575 Array& data = thread->ArrayHandle(); |
604 { | 576 { |
605 Isolate* vm_isolate = Dart::vm_isolate(); | 577 Isolate* vm_isolate = Dart::vm_isolate(); |
606 data ^= vm_isolate->object_store()->symbol_table(); | 578 data ^= vm_isolate->object_store()->symbol_table(); |
607 SymbolTable table(&key, &value, &data); | 579 SymbolTable table(&key, &value, &data); |
608 symbol ^= table.GetOrNull(str); | 580 symbol ^= table.GetOrNull(str); |
609 table.Release(); | 581 table.Release(); |
610 } | 582 } |
611 if (symbol.IsNull()) { | 583 if (symbol.IsNull()) { |
612 Isolate* isolate = thread->isolate(); | 584 Isolate* isolate = thread->isolate(); |
613 SafepointMutexLocker ml(isolate->symbols_mutex()); | 585 SafepointMutexLocker ml(isolate->symbols_mutex()); |
614 data ^= isolate->object_store()->symbol_table(); | 586 data ^= isolate->object_store()->symbol_table(); |
615 SymbolTable table(&key, &value, &data); | 587 SymbolTable table(&key, &value, &data); |
616 symbol ^= table.GetOrNull(str); | 588 symbol ^= table.GetOrNull(str); |
617 table.Release(); | 589 table.Release(); |
618 } | 590 } |
619 ASSERT(symbol.IsNull() || symbol.IsSymbol()); | 591 ASSERT(symbol.IsNull() || symbol.IsSymbol()); |
620 ASSERT(symbol.IsNull() || symbol.HasHash()); | 592 ASSERT(symbol.IsNull() || symbol.HasHash()); |
621 return symbol.raw(); | 593 return symbol.raw(); |
622 } | 594 } |
623 | 595 |
624 | |
625 RawString* Symbols::LookupFromConcat(Thread* thread, | 596 RawString* Symbols::LookupFromConcat(Thread* thread, |
626 const String& str1, | 597 const String& str1, |
627 const String& str2) { | 598 const String& str2) { |
628 if (str1.Length() == 0) { | 599 if (str1.Length() == 0) { |
629 return Lookup(thread, str2); | 600 return Lookup(thread, str2); |
630 } else if (str2.Length() == 0) { | 601 } else if (str2.Length() == 0) { |
631 return Lookup(thread, str1); | 602 return Lookup(thread, str1); |
632 } else { | 603 } else { |
633 return Lookup(thread, ConcatString(str1, str2)); | 604 return Lookup(thread, ConcatString(str1, str2)); |
634 } | 605 } |
635 } | 606 } |
636 | 607 |
637 | |
638 RawString* Symbols::LookupFromGet(Thread* thread, const String& str) { | 608 RawString* Symbols::LookupFromGet(Thread* thread, const String& str) { |
639 return LookupFromConcat(thread, GetterPrefix(), str); | 609 return LookupFromConcat(thread, GetterPrefix(), str); |
640 } | 610 } |
641 | 611 |
642 | |
643 RawString* Symbols::LookupFromSet(Thread* thread, const String& str) { | 612 RawString* Symbols::LookupFromSet(Thread* thread, const String& str) { |
644 return LookupFromConcat(thread, SetterPrefix(), str); | 613 return LookupFromConcat(thread, SetterPrefix(), str); |
645 } | 614 } |
646 | 615 |
647 | |
648 RawString* Symbols::LookupFromDot(Thread* thread, const String& str) { | 616 RawString* Symbols::LookupFromDot(Thread* thread, const String& str) { |
649 return LookupFromConcat(thread, str, Dot()); | 617 return LookupFromConcat(thread, str, Dot()); |
650 } | 618 } |
651 | 619 |
652 | |
653 RawString* Symbols::New(Thread* thread, const String& str) { | 620 RawString* Symbols::New(Thread* thread, const String& str) { |
654 if (str.IsSymbol()) { | 621 if (str.IsSymbol()) { |
655 return str.raw(); | 622 return str.raw(); |
656 } | 623 } |
657 return New(thread, str, 0, str.Length()); | 624 return New(thread, str, 0, str.Length()); |
658 } | 625 } |
659 | 626 |
660 | |
661 RawString* Symbols::New(Thread* thread, | 627 RawString* Symbols::New(Thread* thread, |
662 const String& str, | 628 const String& str, |
663 intptr_t begin_index, | 629 intptr_t begin_index, |
664 intptr_t len) { | 630 intptr_t len) { |
665 return NewSymbol(thread, StringSlice(str, begin_index, len)); | 631 return NewSymbol(thread, StringSlice(str, begin_index, len)); |
666 } | 632 } |
667 | 633 |
668 | |
669 RawString* Symbols::NewFormatted(Thread* thread, const char* format, ...) { | 634 RawString* Symbols::NewFormatted(Thread* thread, const char* format, ...) { |
670 va_list args; | 635 va_list args; |
671 va_start(args, format); | 636 va_start(args, format); |
672 RawString* result = NewFormattedV(thread, format, args); | 637 RawString* result = NewFormattedV(thread, format, args); |
673 NoSafepointScope no_safepoint; | 638 NoSafepointScope no_safepoint; |
674 va_end(args); | 639 va_end(args); |
675 return result; | 640 return result; |
676 } | 641 } |
677 | 642 |
678 | |
679 RawString* Symbols::NewFormattedV(Thread* thread, | 643 RawString* Symbols::NewFormattedV(Thread* thread, |
680 const char* format, | 644 const char* format, |
681 va_list args) { | 645 va_list args) { |
682 va_list args_copy; | 646 va_list args_copy; |
683 va_copy(args_copy, args); | 647 va_copy(args_copy, args); |
684 intptr_t len = OS::VSNPrint(NULL, 0, format, args_copy); | 648 intptr_t len = OS::VSNPrint(NULL, 0, format, args_copy); |
685 va_end(args_copy); | 649 va_end(args_copy); |
686 | 650 |
687 Zone* zone = Thread::Current()->zone(); | 651 Zone* zone = Thread::Current()->zone(); |
688 char* buffer = zone->Alloc<char>(len + 1); | 652 char* buffer = zone->Alloc<char>(len + 1); |
689 OS::VSNPrint(buffer, (len + 1), format, args); | 653 OS::VSNPrint(buffer, (len + 1), format, args); |
690 | 654 |
691 return Symbols::New(thread, buffer); | 655 return Symbols::New(thread, buffer); |
692 } | 656 } |
693 | 657 |
694 | |
695 RawString* Symbols::FromCharCode(Thread* thread, int32_t char_code) { | 658 RawString* Symbols::FromCharCode(Thread* thread, int32_t char_code) { |
696 if (char_code > kMaxOneCharCodeSymbol) { | 659 if (char_code > kMaxOneCharCodeSymbol) { |
697 return FromUTF32(thread, &char_code, 1); | 660 return FromUTF32(thread, &char_code, 1); |
698 } | 661 } |
699 return predefined_[char_code]; | 662 return predefined_[char_code]; |
700 } | 663 } |
701 | 664 |
702 | |
703 void Symbols::DumpStats(Isolate* isolate) { | 665 void Symbols::DumpStats(Isolate* isolate) { |
704 intptr_t size = -1; | 666 intptr_t size = -1; |
705 intptr_t capacity = -1; | 667 intptr_t capacity = -1; |
706 // First dump VM symbol table stats. | 668 // First dump VM symbol table stats. |
707 GetStats(Dart::vm_isolate(), &size, &capacity); | 669 GetStats(Dart::vm_isolate(), &size, &capacity); |
708 OS::Print("VM Isolate: Number of symbols : %" Pd "\n", size); | 670 OS::Print("VM Isolate: Number of symbols : %" Pd "\n", size); |
709 OS::Print("VM Isolate: Symbol table capacity : %" Pd "\n", capacity); | 671 OS::Print("VM Isolate: Symbol table capacity : %" Pd "\n", capacity); |
710 // Now dump regular isolate symbol table stats. | 672 // Now dump regular isolate symbol table stats. |
711 GetStats(isolate, &size, &capacity); | 673 GetStats(isolate, &size, &capacity); |
712 OS::Print("Isolate: Number of symbols : %" Pd "\n", size); | 674 OS::Print("Isolate: Number of symbols : %" Pd "\n", size); |
713 OS::Print("Isolate: Symbol table capacity : %" Pd "\n", capacity); | 675 OS::Print("Isolate: Symbol table capacity : %" Pd "\n", capacity); |
714 // TODO(koda): Consider recording growth and collision stats in HashTable, | 676 // TODO(koda): Consider recording growth and collision stats in HashTable, |
715 // in DEBUG mode. | 677 // in DEBUG mode. |
716 } | 678 } |
717 | 679 |
718 | |
719 intptr_t Symbols::LookupPredefinedSymbol(RawObject* obj) { | 680 intptr_t Symbols::LookupPredefinedSymbol(RawObject* obj) { |
720 for (intptr_t i = 1; i < Symbols::kMaxPredefinedId; i++) { | 681 for (intptr_t i = 1; i < Symbols::kMaxPredefinedId; i++) { |
721 if (symbol_handles_[i]->raw() == obj) { | 682 if (symbol_handles_[i]->raw() == obj) { |
722 return (i + kMaxPredefinedObjectIds); | 683 return (i + kMaxPredefinedObjectIds); |
723 } | 684 } |
724 } | 685 } |
725 return kInvalidIndex; | 686 return kInvalidIndex; |
726 } | 687 } |
727 | 688 |
728 | |
729 RawObject* Symbols::GetPredefinedSymbol(intptr_t object_id) { | 689 RawObject* Symbols::GetPredefinedSymbol(intptr_t object_id) { |
730 ASSERT(IsPredefinedSymbolId(object_id)); | 690 ASSERT(IsPredefinedSymbolId(object_id)); |
731 intptr_t i = (object_id - kMaxPredefinedObjectIds); | 691 intptr_t i = (object_id - kMaxPredefinedObjectIds); |
732 if ((i > kIllegal) && (i < Symbols::kMaxPredefinedId)) { | 692 if ((i > kIllegal) && (i < Symbols::kMaxPredefinedId)) { |
733 return symbol_handles_[i]->raw(); | 693 return symbol_handles_[i]->raw(); |
734 } | 694 } |
735 return Object::null(); | 695 return Object::null(); |
736 } | 696 } |
737 | 697 |
738 } // namespace dart | 698 } // namespace dart |
OLD | NEW |