| 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 |