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/handles_impl.h" | 8 #include "vm/handles_impl.h" |
9 #include "vm/hash_table.h" | 9 #include "vm/hash_table.h" |
10 #include "vm/isolate.h" | 10 #include "vm/isolate.h" |
(...skipping 21 matching lines...) Expand all Loading... |
32 | 32 |
33 #define DEFINE_KEYWORD_SYMBOL_INDEX(t, s, p, a) \ | 33 #define DEFINE_KEYWORD_SYMBOL_INDEX(t, s, p, a) \ |
34 s, | 34 s, |
35 DART_KEYWORD_LIST(DEFINE_KEYWORD_SYMBOL_INDEX) | 35 DART_KEYWORD_LIST(DEFINE_KEYWORD_SYMBOL_INDEX) |
36 #undef DEFINE_KEYWORD_SYMBOL_INDEX | 36 #undef DEFINE_KEYWORD_SYMBOL_INDEX |
37 }; | 37 }; |
38 | 38 |
39 DEFINE_FLAG(bool, dump_symbol_stats, false, "Dump symbol table statistics"); | 39 DEFINE_FLAG(bool, dump_symbol_stats, false, "Dump symbol table statistics"); |
40 | 40 |
41 | 41 |
42 const char* Symbols::Name(SymbolId symbol) { | |
43 ASSERT((symbol > kIllegal) && (symbol < kNullCharId)); | |
44 return names[symbol]; | |
45 } | |
46 | |
47 | |
48 const String& Symbols::Keyword(Token::Kind keyword) { | |
49 const int kw_index = keyword - Token::kFirstKeyword; | |
50 ASSERT((0 <= kw_index) && (kw_index < Token::kNumKeywords)); | |
51 // First keyword symbol is in symbol_handles_[kKwTableStart + 1]. | |
52 const intptr_t keyword_id = Symbols::kKwTableStart + 1 + kw_index; | |
53 ASSERT(symbol_handles_[keyword_id] != NULL); | |
54 return *symbol_handles_[keyword_id]; | |
55 } | |
56 | |
57 | |
58 void Symbols::InitOnce(Isolate* isolate) { | |
59 // Should only be run by the vm isolate. | |
60 ASSERT(isolate == Dart::vm_isolate()); | |
61 | |
62 // Create and setup a symbol table in the vm isolate. | |
63 SetupSymbolTable(isolate); | |
64 | |
65 // Create all predefined symbols. | |
66 ASSERT((sizeof(names) / sizeof(const char*)) == Symbols::kNullCharId); | |
67 | |
68 // Set up all the predefined string symbols and create symbols for language | |
69 // keywords. We don't expect to find any overlaps between the predefined | |
70 // string symbols and the language keywords. If an overlap is introduced | |
71 // inadvertantly the ASSERT in AddToVMIsolate while fail. | |
72 for (intptr_t i = 1; i < Symbols::kNullCharId; i++) { | |
73 String* str = String::ReadOnlyHandle(); | |
74 *str = OneByteString::New(names[i], Heap::kOld); | |
75 AddToVMIsolate(*str); | |
76 symbol_handles_[i] = str; | |
77 } | |
78 | |
79 // Add Latin1 characters as Symbols, so that Symbols::FromCharCode is fast. | |
80 for (intptr_t c = 0; c < kNumberOfOneCharCodeSymbols; c++) { | |
81 intptr_t idx = (kNullCharId + c); | |
82 ASSERT(idx < kMaxPredefinedId); | |
83 ASSERT(Utf::IsLatin1(c)); | |
84 uint8_t ch = static_cast<uint8_t>(c); | |
85 String* str = String::ReadOnlyHandle(); | |
86 *str = OneByteString::New(&ch, 1, Heap::kOld); | |
87 AddToVMIsolate(*str); | |
88 predefined_[c] = str->raw(); | |
89 symbol_handles_[idx] = str; | |
90 } | |
91 } | |
92 | |
93 | |
94 RawString* StringFrom(const uint8_t* data, intptr_t len, Heap::Space space) { | 42 RawString* StringFrom(const uint8_t* data, intptr_t len, Heap::Space space) { |
95 return String::FromLatin1(data, len, space); | 43 return String::FromLatin1(data, len, space); |
96 } | 44 } |
97 RawString* StringFrom(const uint16_t* data, intptr_t len, Heap::Space space) { | 45 RawString* StringFrom(const uint16_t* data, intptr_t len, Heap::Space space) { |
98 return String::FromUTF16(data, len, space); | 46 return String::FromUTF16(data, len, space); |
99 } | 47 } |
100 RawString* StringFrom(const int32_t* data, intptr_t len, Heap::Space space) { | 48 RawString* StringFrom(const int32_t* data, intptr_t len, Heap::Space space) { |
101 return String::FromUTF32(data, len, space); | 49 return String::FromUTF32(data, len, space); |
102 } | 50 } |
103 | 51 |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
222 static RawObject* NewKey(const StringSlice& slice) { | 170 static RawObject* NewKey(const StringSlice& slice) { |
223 return slice.ToSymbol(); | 171 return slice.ToSymbol(); |
224 } | 172 } |
225 static RawObject* NewKey(const ConcatString& concat) { | 173 static RawObject* NewKey(const ConcatString& concat) { |
226 return concat.ToSymbol(); | 174 return concat.ToSymbol(); |
227 } | 175 } |
228 }; | 176 }; |
229 typedef UnorderedHashSet<SymbolTraits> SymbolTable; | 177 typedef UnorderedHashSet<SymbolTraits> SymbolTable; |
230 | 178 |
231 | 179 |
| 180 const char* Symbols::Name(SymbolId symbol) { |
| 181 ASSERT((symbol > kIllegal) && (symbol < kNullCharId)); |
| 182 return names[symbol]; |
| 183 } |
| 184 |
| 185 |
| 186 const String& Symbols::Keyword(Token::Kind keyword) { |
| 187 const int kw_index = keyword - Token::kFirstKeyword; |
| 188 ASSERT((0 <= kw_index) && (kw_index < Token::kNumKeywords)); |
| 189 // First keyword symbol is in symbol_handles_[kKwTableStart + 1]. |
| 190 const intptr_t keyword_id = Symbols::kKwTableStart + 1 + kw_index; |
| 191 ASSERT(symbol_handles_[keyword_id] != NULL); |
| 192 return *symbol_handles_[keyword_id]; |
| 193 } |
| 194 |
| 195 |
| 196 void Symbols::InitOnce(Isolate* vm_isolate) { |
| 197 // Should only be run by the vm isolate. |
| 198 ASSERT(Isolate::Current() == Dart::vm_isolate()); |
| 199 ASSERT(vm_isolate == Dart::vm_isolate()); |
| 200 |
| 201 // Create and setup a symbol table in the vm isolate. |
| 202 SetupSymbolTable(vm_isolate); |
| 203 |
| 204 // Create all predefined symbols. |
| 205 ASSERT((sizeof(names) / sizeof(const char*)) == Symbols::kNullCharId); |
| 206 |
| 207 SymbolTable table(vm_isolate, vm_isolate->object_store()->symbol_table()); |
| 208 |
| 209 // First set up all the predefined string symbols. |
| 210 // Create symbols for language keywords. Some keywords are equal to |
| 211 // symbols we already created, so use New() instead of Add() to ensure |
| 212 // that the symbols are canonicalized. |
| 213 for (intptr_t i = 1; i < Symbols::kNullCharId; i++) { |
| 214 String* str = String::ReadOnlyHandle(); |
| 215 *str = OneByteString::New(names[i], Heap::kOld); |
| 216 str->Hash(); |
| 217 str->SetCanonical(); |
| 218 bool present = table.Insert(*str); |
| 219 ASSERT(!present); |
| 220 symbol_handles_[i] = str; |
| 221 } |
| 222 |
| 223 // Add Latin1 characters as Symbols, so that Symbols::FromCharCode is fast. |
| 224 for (intptr_t c = 0; c < kNumberOfOneCharCodeSymbols; c++) { |
| 225 intptr_t idx = (kNullCharId + c); |
| 226 ASSERT(idx < kMaxPredefinedId); |
| 227 ASSERT(Utf::IsLatin1(c)); |
| 228 uint8_t ch = static_cast<uint8_t>(c); |
| 229 String* str = String::ReadOnlyHandle(); |
| 230 *str = OneByteString::New(&ch, 1, Heap::kOld); |
| 231 str->Hash(); |
| 232 str->SetCanonical(); |
| 233 bool present = table.Insert(*str); |
| 234 ASSERT(!present); |
| 235 predefined_[c] = str->raw(); |
| 236 symbol_handles_[idx] = str; |
| 237 } |
| 238 |
| 239 vm_isolate->object_store()->set_symbol_table(table.Release()); |
| 240 } |
| 241 |
| 242 |
| 243 void Symbols::InitOnceFromSnapshot(Isolate* vm_isolate) { |
| 244 // Should only be run by the vm isolate. |
| 245 ASSERT(Isolate::Current() == Dart::vm_isolate()); |
| 246 ASSERT(vm_isolate == Dart::vm_isolate()); |
| 247 |
| 248 SymbolTable table(vm_isolate, vm_isolate->object_store()->symbol_table()); |
| 249 |
| 250 // Lookup all the predefined string symbols and language keyword symbols |
| 251 // and cache them in the read only handles for fast access. |
| 252 for (intptr_t i = 1; i < Symbols::kNullCharId; i++) { |
| 253 String* str = String::ReadOnlyHandle(); |
| 254 const unsigned char* name = |
| 255 reinterpret_cast<const unsigned char*>(names[i]); |
| 256 *str ^= table.GetOrNull(Latin1Array(name, strlen(names[i]))); |
| 257 ASSERT(!str->IsNull()); |
| 258 ASSERT(str->HasHash()); |
| 259 ASSERT(str->IsCanonical()); |
| 260 symbol_handles_[i] = str; |
| 261 } |
| 262 |
| 263 // Lookup Latin1 character Symbols and cache them in read only handles, |
| 264 // so that Symbols::FromCharCode is fast. |
| 265 for (intptr_t c = 0; c < kNumberOfOneCharCodeSymbols; c++) { |
| 266 intptr_t idx = (kNullCharId + c); |
| 267 ASSERT(idx < kMaxPredefinedId); |
| 268 ASSERT(Utf::IsLatin1(c)); |
| 269 uint8_t ch = static_cast<uint8_t>(c); |
| 270 String* str = String::ReadOnlyHandle(); |
| 271 *str ^= table.GetOrNull(Latin1Array(&ch, 1)); |
| 272 ASSERT(!str->IsNull()); |
| 273 ASSERT(str->HasHash()); |
| 274 ASSERT(str->IsCanonical()); |
| 275 predefined_[c] = str->raw(); |
| 276 symbol_handles_[idx] = str; |
| 277 } |
| 278 |
| 279 vm_isolate->object_store()->set_symbol_table(table.Release()); |
| 280 } |
| 281 |
| 282 |
| 283 void Symbols::AddPredefinedSymbolsToIsolate() { |
| 284 // Should only be run by regular Dart isolates. |
| 285 Isolate* isolate = Isolate::Current(); |
| 286 ASSERT(isolate != Dart::vm_isolate()); |
| 287 String& str = String::Handle(isolate); |
| 288 |
| 289 SymbolTable table(isolate, isolate->object_store()->symbol_table()); |
| 290 |
| 291 // Set up all the predefined string symbols and create symbols for |
| 292 // language keywords. |
| 293 for (intptr_t i = 1; i < Symbols::kNullCharId; i++) { |
| 294 str = OneByteString::New(names[i], Heap::kOld); |
| 295 str.Hash(); |
| 296 str.SetCanonical(); |
| 297 bool present = table.Insert(str); |
| 298 ASSERT(!present); |
| 299 } |
| 300 |
| 301 // Add Latin1 characters as Symbols, so that Symbols::FromCharCode is fast. |
| 302 for (intptr_t c = 0; c < kNumberOfOneCharCodeSymbols; c++) { |
| 303 intptr_t idx = (kNullCharId + c); |
| 304 ASSERT(idx < kMaxPredefinedId); |
| 305 ASSERT(Utf::IsLatin1(c)); |
| 306 uint8_t ch = static_cast<uint8_t>(c); |
| 307 str = OneByteString::New(&ch, 1, Heap::kOld); |
| 308 str.Hash(); |
| 309 str.SetCanonical(); |
| 310 bool present = table.Insert(str); |
| 311 ASSERT(!present); |
| 312 } |
| 313 |
| 314 isolate->object_store()->set_symbol_table(table.Release()); |
| 315 } |
| 316 |
| 317 |
232 void Symbols::SetupSymbolTable(Isolate* isolate) { | 318 void Symbols::SetupSymbolTable(Isolate* isolate) { |
233 ASSERT(isolate != NULL); | 319 ASSERT(isolate != NULL); |
234 | 320 |
235 // Setup the symbol table used within the String class. | 321 // Setup the symbol table used within the String class. |
236 const intptr_t initial_size = (isolate == Dart::vm_isolate()) ? | 322 const intptr_t initial_size = (isolate == Dart::vm_isolate()) ? |
237 kInitialVMIsolateSymtabSize : kInitialSymtabSize; | 323 kInitialVMIsolateSymtabSize : kInitialSymtabSize; |
238 Array& array = | 324 Array& array = |
239 Array::Handle(HashTables::New<SymbolTable>(initial_size, Heap::kOld)); | 325 Array::Handle(HashTables::New<SymbolTable>(initial_size, Heap::kOld)); |
240 isolate->object_store()->set_symbol_table(array); | 326 isolate->object_store()->set_symbol_table(array); |
241 } | 327 } |
242 | 328 |
243 | 329 |
244 void Symbols::GetStats(Isolate* isolate, intptr_t* size, intptr_t* capacity) { | 330 void Symbols::GetStats(Isolate* isolate, intptr_t* size, intptr_t* capacity) { |
245 ASSERT(isolate != NULL); | 331 ASSERT(isolate != NULL); |
246 SymbolTable table(isolate, isolate->object_store()->symbol_table()); | 332 SymbolTable table(isolate, isolate->object_store()->symbol_table()); |
247 *size = table.NumOccupied(); | 333 *size = table.NumOccupied(); |
248 *capacity = table.NumEntries(); | 334 *capacity = table.NumEntries(); |
249 table.Release(); | 335 table.Release(); |
250 } | 336 } |
251 | 337 |
252 | 338 |
253 void Symbols::AddToVMIsolate(const String& str) { | |
254 // Should only be run by the vm isolate. | |
255 ASSERT(Isolate::Current() == Dart::vm_isolate()); | |
256 Isolate* isolate = Dart::vm_isolate(); | |
257 SymbolTable table(isolate, isolate->object_store()->symbol_table()); | |
258 bool present = table.Insert(str); | |
259 str.SetCanonical(); | |
260 ASSERT(!present); | |
261 isolate->object_store()->set_symbol_table(table.Release()); | |
262 } | |
263 | |
264 | |
265 RawString* Symbols::New(const char* cstr, intptr_t len) { | 339 RawString* Symbols::New(const char* cstr, intptr_t len) { |
266 ASSERT((cstr != NULL) && (len >= 0)); | 340 ASSERT((cstr != NULL) && (len >= 0)); |
267 const uint8_t* utf8_array = reinterpret_cast<const uint8_t*>(cstr); | 341 const uint8_t* utf8_array = reinterpret_cast<const uint8_t*>(cstr); |
268 return Symbols::FromUTF8(utf8_array, len); | 342 return Symbols::FromUTF8(utf8_array, len); |
269 } | 343 } |
270 | 344 |
271 | 345 |
272 RawString* Symbols::FromUTF8(const uint8_t* utf8_array, intptr_t array_len) { | 346 RawString* Symbols::FromUTF8(const uint8_t* utf8_array, intptr_t array_len) { |
273 if (array_len == 0 || utf8_array == NULL) { | 347 if (array_len == 0 || utf8_array == NULL) { |
274 return FromLatin1(reinterpret_cast<uint8_t*>(NULL), 0); | 348 return FromLatin1(reinterpret_cast<uint8_t*>(NULL), 0); |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
383 RawObject* Symbols::GetVMSymbol(intptr_t object_id) { | 457 RawObject* Symbols::GetVMSymbol(intptr_t object_id) { |
384 ASSERT(IsVMSymbolId(object_id)); | 458 ASSERT(IsVMSymbolId(object_id)); |
385 intptr_t i = (object_id - kMaxPredefinedObjectIds); | 459 intptr_t i = (object_id - kMaxPredefinedObjectIds); |
386 if ((i > kIllegal) && (i < Symbols::kMaxPredefinedId)) { | 460 if ((i > kIllegal) && (i < Symbols::kMaxPredefinedId)) { |
387 return symbol_handles_[i]->raw(); | 461 return symbol_handles_[i]->raw(); |
388 } | 462 } |
389 return Object::null(); | 463 return Object::null(); |
390 } | 464 } |
391 | 465 |
392 } // namespace dart | 466 } // namespace dart |
OLD | NEW |