Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
symbols.cc
Go to the documentation of this 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
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/symbols.h"
6
7#include "platform/unicode.h"
9#include "vm/handles.h"
10#include "vm/hash_table.h"
11#include "vm/heap/safepoint.h"
12#include "vm/isolate.h"
13#include "vm/object.h"
14#include "vm/object_store.h"
15#include "vm/raw_object.h"
16#include "vm/reusable_handles.h"
17#include "vm/visitor.h"
18
19namespace dart {
20
21StringPtr Symbols::predefined_[Symbols::kNumberOfOneCharCodeSymbols];
22String* Symbols::symbol_handles_[Symbols::kMaxPredefinedId];
23
24static const char* const names[] = {
25 // clang-format off
26 nullptr,
27#define DEFINE_SYMBOL_LITERAL(symbol, literal) literal,
29#undef DEFINE_SYMBOL_LITERAL
30 "", // matches kTokenTableStart.
31#define DEFINE_TOKEN_SYMBOL_INDEX(t, s, p, a) s,
34#undef DEFINE_TOKEN_SYMBOL_INDEX
35 // clang-format on
36};
37
38StringPtr StringFrom(const uint8_t* data, intptr_t len, Heap::Space space) {
39 return String::FromLatin1(data, len, space);
40}
41
42StringPtr StringFrom(const uint16_t* data, intptr_t len, Heap::Space space) {
43 return String::FromUTF16(data, len, space);
44}
45
46StringPtr StringSlice::ToSymbol() const {
47 if (is_all() && str_.IsOld()) {
48 str_.SetCanonical();
49 return str_.ptr();
50 } else {
51 String& result =
52 String::Handle(String::SubString(str_, begin_index_, len_, Heap::kOld));
53 result.SetCanonical();
54 result.SetHash(hash_);
55 return result.ptr();
56 }
57}
58
59StringPtr ConcatString::ToSymbol() const {
61 result.SetCanonical();
62 result.SetHash(hash_);
63 return result.ptr();
64}
65
66const char* Symbols::Name(SymbolId symbol) {
67 ASSERT((symbol > kIllegal) && (symbol < kNullCharId));
68 return names[symbol];
69}
70
72 const int tok_index = token;
73 ASSERT((0 <= tok_index) && (tok_index < Token::kNumTokens));
74 // First keyword symbol is in symbol_handles_[kTokenTableStart + 1].
75 const intptr_t token_id = Symbols::kTokenTableStart + 1 + tok_index;
76 ASSERT(symbol_handles_[token_id] != nullptr);
77 return *symbol_handles_[token_id];
78}
79
80void Symbols::Init(IsolateGroup* vm_isolate_group) {
81 // Should only be run by the vm isolate.
83 ASSERT(vm_isolate_group == Dart::vm_isolate_group());
84 Zone* zone = Thread::Current()->zone();
85
86 // Create and setup a symbol table in the vm isolate.
87 SetupSymbolTable(vm_isolate_group);
88
89 // Create all predefined symbols.
90 ASSERT((sizeof(names) / sizeof(const char*)) == Symbols::kNullCharId);
91
93 vm_isolate_group->object_store()->symbol_table());
94
95 // First set up all the predefined string symbols.
96 // Create symbols for language keywords. Some keywords are equal to
97 // symbols we already created, so use New() instead of Add() to ensure
98 // that the symbols are canonicalized.
99 for (intptr_t i = 1; i < Symbols::kNullCharId; i++) {
102 str->Hash();
103 *str ^= table.InsertOrGet(*str);
104 str->SetCanonical(); // Make canonical once entered.
105 symbol_handles_[i] = str;
106 }
107
108 // Add Latin1 characters as Symbols, so that Symbols::FromCharCode is fast.
109 for (intptr_t c = 0; c < kNumberOfOneCharCodeSymbols; c++) {
110 intptr_t idx = (kNullCharId + c);
113 uint8_t ch = static_cast<uint8_t>(c);
115 *str = OneByteString::New(&ch, 1, Heap::kOld);
116 str->Hash();
117 *str ^= table.InsertOrGet(*str);
118 ASSERT(predefined_[c] == nullptr);
119 str->SetCanonical(); // Make canonical once entered.
120 predefined_[c] = str->ptr();
121 symbol_handles_[idx] = str;
122 }
123
124 vm_isolate_group->object_store()->set_symbol_table(table.Release());
125}
126
128 // Should only be run by the vm isolate.
130 ASSERT(vm_isolate_group == Dart::vm_isolate_group());
131 Zone* zone = Thread::Current()->zone();
132
134 vm_isolate_group->object_store()->symbol_table());
135
136 // Lookup all the predefined string symbols and language keyword symbols
137 // and cache them in the read only handles for fast access.
138 for (intptr_t i = 1; i < Symbols::kNullCharId; i++) {
140 const unsigned char* name =
141 reinterpret_cast<const unsigned char*>(names[i]);
142 *str ^= table.GetOrNull(Latin1Array(name, strlen(names[i])));
143 ASSERT(!str->IsNull());
144 ASSERT(str->HasHash());
145 ASSERT(str->IsCanonical());
146 symbol_handles_[i] = str;
147 }
148
149 // Lookup Latin1 character Symbols and cache them in read only handles,
150 // so that Symbols::FromCharCode is fast.
151 for (intptr_t c = 0; c < kNumberOfOneCharCodeSymbols; c++) {
152 intptr_t idx = (kNullCharId + c);
155 uint8_t ch = static_cast<uint8_t>(c);
157 *str ^= table.GetOrNull(Latin1Array(&ch, 1));
158 ASSERT(!str->IsNull());
159 ASSERT(str->HasHash());
160 ASSERT(str->IsCanonical());
161 predefined_[c] = str->ptr();
162 symbol_handles_[idx] = str;
163 }
164
165 vm_isolate_group->object_store()->set_symbol_table(table.Release());
166}
167
169 ASSERT(isolate_group != nullptr);
170
171 // Setup the symbol table used within the String class.
172 const intptr_t initial_size = (isolate_group == Dart::vm_isolate_group())
173 ? kInitialVMIsolateSymtabSize
174 : kInitialSymtabSize;
175 class WeakArray& array = WeakArray::Handle(
176 HashTables::New<CanonicalStringSet>(initial_size, Heap::kOld));
177 isolate_group->object_store()->set_symbol_table(array);
178}
179
180void Symbols::GetStats(IsolateGroup* isolate_group,
181 intptr_t* size,
182 intptr_t* capacity) {
183 ASSERT(isolate_group != nullptr);
184 CanonicalStringSet table(isolate_group->object_store()->symbol_table());
185 *size = table.NumOccupied();
186 *capacity = table.NumEntries();
187 table.Release();
188}
189
190StringPtr Symbols::New(Thread* thread, const char* cstr, intptr_t len) {
191 ASSERT((cstr != nullptr) && (len >= 0));
192 const uint8_t* utf8_array = reinterpret_cast<const uint8_t*>(cstr);
193 return Symbols::FromUTF8(thread, utf8_array, len);
194}
195
196StringPtr Symbols::FromUTF8(Thread* thread,
197 const uint8_t* utf8_array,
198 intptr_t array_len) {
199 if (array_len == 0 || utf8_array == nullptr) {
200 return FromLatin1(thread, static_cast<uint8_t*>(nullptr), 0);
201 }
203 intptr_t len = Utf8::CodeUnitCount(utf8_array, array_len, &type);
204 ASSERT(len != 0);
205 Zone* zone = thread->zone();
206 if (type == Utf8::kLatin1) {
207 uint8_t* characters = zone->Alloc<uint8_t>(len);
208 if (!Utf8::DecodeToLatin1(utf8_array, array_len, characters, len)) {
209 Utf8::ReportInvalidByte(utf8_array, array_len, len);
210 return String::null();
211 }
212 return FromLatin1(thread, characters, len);
213 }
215 uint16_t* characters = zone->Alloc<uint16_t>(len);
216 if (!Utf8::DecodeToUTF16(utf8_array, array_len, characters, len)) {
217 Utf8::ReportInvalidByte(utf8_array, array_len, len);
218 return String::null();
219 }
220 return FromUTF16(thread, characters, len);
221}
222
223StringPtr Symbols::FromLatin1(Thread* thread,
224 const uint8_t* latin1_array,
225 intptr_t len) {
226 return NewSymbol(thread, Latin1Array(latin1_array, len));
227}
228
229StringPtr Symbols::FromUTF16(Thread* thread,
230 const uint16_t* utf16_array,
231 intptr_t len) {
232 return NewSymbol(thread, UTF16Array(utf16_array, len));
233}
234
235StringPtr Symbols::FromConcat(Thread* thread,
236 const String& str1,
237 const String& str2) {
238 if (str1.Length() == 0) {
239 return New(thread, str2);
240 } else if (str2.Length() == 0) {
241 return New(thread, str1);
242 } else {
243 return NewSymbol(thread, ConcatString(str1, str2));
244 }
245}
246
247StringPtr Symbols::FromGet(Thread* thread, const String& str) {
248 return FromConcat(thread, GetterPrefix(), str);
249}
250
251StringPtr Symbols::FromSet(Thread* thread, const String& str) {
252 return FromConcat(thread, SetterPrefix(), str);
253}
254
255StringPtr Symbols::FromDot(Thread* thread, const String& str) {
256 return FromConcat(thread, str, Dot());
257}
258
259// TODO(srdjan): If this becomes performance critical code, consider looking
260// up symbol from hash of pieces instead of concatenating them first into
261// a string.
263 Thread* thread,
265 const intptr_t strs_length = strs.length();
266 GrowableArray<intptr_t> lengths(strs_length);
267
268 intptr_t len_sum = 0;
269 const intptr_t kOneByteChar = 1;
270 intptr_t char_size = kOneByteChar;
271
272 for (intptr_t i = 0; i < strs_length; i++) {
273 const String& str = strs[i];
274 const intptr_t str_len = str.Length();
275 if ((String::kMaxElements - len_sum) < str_len) {
277 UNREACHABLE();
278 }
279 len_sum += str_len;
280 lengths.Add(str_len);
281 char_size = Utils::Maximum(char_size, str.CharSize());
282 }
283 const bool is_one_byte_string = char_size == kOneByteChar;
284
285 Zone* zone = thread->zone();
286 if (is_one_byte_string) {
287 uint8_t* buffer = zone->Alloc<uint8_t>(len_sum);
288 const uint8_t* const orig_buffer = buffer;
289 for (intptr_t i = 0; i < strs_length; i++) {
290 NoSafepointScope no_safepoint;
291 intptr_t str_len = lengths[i];
292 if (str_len > 0) {
293 const String& str = strs[i];
294 ASSERT(str.IsOneByteString());
295 const uint8_t* src_p = OneByteString::DataStart(str);
296 memmove(buffer, src_p, str_len);
297 buffer += str_len;
298 }
299 }
300 ASSERT(len_sum == buffer - orig_buffer);
301 return Symbols::FromLatin1(thread, orig_buffer, len_sum);
302 } else {
303 uint16_t* buffer = zone->Alloc<uint16_t>(len_sum);
304 const uint16_t* const orig_buffer = buffer;
305 for (intptr_t i = 0; i < strs_length; i++) {
306 NoSafepointScope no_safepoint;
307 intptr_t str_len = lengths[i];
308 if (str_len > 0) {
309 const String& str = strs[i];
310 if (str.IsTwoByteString()) {
311 memmove(buffer, TwoByteString::DataStart(str), str_len * 2);
312 } else {
313 // One-byte to two-byte string copy.
314 ASSERT(str.IsOneByteString());
315 const uint8_t* src_p = OneByteString::DataStart(str);
316 for (int n = 0; n < str_len; n++) {
317 buffer[n] = src_p[n];
318 }
319 }
320 buffer += str_len;
321 }
322 }
323 ASSERT(len_sum == buffer - orig_buffer);
324 return Symbols::FromUTF16(thread, orig_buffer, len_sum);
325 }
326}
327
328// StringType can be StringSlice, ConcatString, or {Latin1,UTF16}Array.
329template <typename StringType>
330StringPtr Symbols::NewSymbol(Thread* thread, const StringType& str) {
334 String& symbol = String::Handle(thread->zone());
335 dart::Object& key = thread->ObjectHandle();
336 Smi& value = thread->SmiHandle();
337 class WeakArray& data = thread->WeakArrayHandle();
338 {
339 auto vm_isolate_group = Dart::vm_isolate_group();
340 data = vm_isolate_group->object_store()->symbol_table();
341 CanonicalStringSet table(&key, &value, &data);
342 symbol ^= table.GetOrNull(str);
343 table.Release();
344 }
345 if (symbol.IsNull()) {
346 IsolateGroup* group = thread->isolate_group();
347 ObjectStore* object_store = group->object_store();
349
350 // Most common case: The symbol is already in the table.
351 {
352 // We do allow lock-free concurrent read access to the symbol table.
353 // Both, the array in the ObjectStore as well as elements in the array
354 // are accessed via store-release/load-acquire barriers.
355 data = object_store->symbol_table();
356 CanonicalStringSet table(&key, &value, &data);
357 symbol ^= table.GetOrNull(str);
358 table.Release();
359 }
360 // Otherwise we'll have to get exclusive access and get-or-insert it.
361 if (symbol.IsNull()) {
362 SafepointMutexLocker ml(group->symbols_mutex());
363 data = object_store->symbol_table();
364 CanonicalStringSet table(&key, &value, &data);
365 symbol ^= table.InsertNewOrGet(str);
366 object_store->set_symbol_table(table.Release());
367 }
368 }
369 ASSERT(symbol.IsSymbol());
370 ASSERT(symbol.HasHash());
371 return symbol.ptr();
372}
373
374template <typename StringType>
375StringPtr Symbols::Lookup(Thread* thread, const StringType& str) {
379 String& symbol = String::Handle(thread->zone());
380 dart::Object& key = thread->ObjectHandle();
381 Smi& value = thread->SmiHandle();
382 class WeakArray& data = thread->WeakArrayHandle();
383 {
384 auto vm_isolate_group = Dart::vm_isolate_group();
385 data = vm_isolate_group->object_store()->symbol_table();
387 symbol ^= table.GetOrNull(str);
388 table.Release();
389 }
390 if (symbol.IsNull()) {
391 IsolateGroup* group = thread->isolate_group();
392 ObjectStore* object_store = group->object_store();
393 // See `Symbols::NewSymbol` for more information why we separate the two
394 // cases.
395 if (thread->OwnsSafepoint()) {
396 data = object_store->symbol_table();
398 symbol ^= table.GetOrNull(str);
399 table.Release();
400 } else {
401 data = object_store->symbol_table();
403 symbol ^= table.GetOrNull(str);
404 table.Release();
405 }
406 }
407 ASSERT(symbol.IsNull() || symbol.IsSymbol());
408 ASSERT(symbol.IsNull() || symbol.HasHash());
409 return symbol.ptr();
410}
411
413 const String& str1,
414 const String& str2) {
415 if (str1.Length() == 0) {
416 return Lookup(thread, str2);
417 } else if (str2.Length() == 0) {
418 return Lookup(thread, str1);
419 } else {
420 return Lookup(thread, ConcatString(str1, str2));
421 }
422}
423
424StringPtr Symbols::LookupFromGet(Thread* thread, const String& str) {
425 return LookupFromConcat(thread, GetterPrefix(), str);
426}
427
428StringPtr Symbols::LookupFromSet(Thread* thread, const String& str) {
429 return LookupFromConcat(thread, SetterPrefix(), str);
430}
431
432StringPtr Symbols::LookupFromDot(Thread* thread, const String& str) {
433 return LookupFromConcat(thread, str, Dot());
434}
435
436StringPtr Symbols::New(Thread* thread, const String& str) {
437 if (str.IsSymbol()) {
438 return str.ptr();
439 }
440 return New(thread, str, 0, str.Length());
441}
442
443StringPtr Symbols::New(Thread* thread,
444 const String& str,
445 intptr_t begin_index,
446 intptr_t len) {
447 return NewSymbol(thread, StringSlice(str, begin_index, len));
448}
449
450StringPtr Symbols::NewFormatted(Thread* thread, const char* format, ...) {
451 va_list args;
452 va_start(args, format);
453 StringPtr result = NewFormattedV(thread, format, args);
454 NoSafepointScope no_safepoint;
455 va_end(args);
456 return result;
457}
458
460 const char* format,
461 va_list args) {
462 va_list args_copy;
463 va_copy(args_copy, args);
464 intptr_t len = Utils::VSNPrint(nullptr, 0, format, args_copy);
465 va_end(args_copy);
466
467 Zone* zone = Thread::Current()->zone();
468 char* buffer = zone->Alloc<char>(len + 1);
469 Utils::VSNPrint(buffer, (len + 1), format, args);
470
471 return Symbols::New(thread, buffer);
472}
473
474StringPtr Symbols::FromCharCode(Thread* thread, uint16_t char_code) {
475 if (char_code > kMaxOneCharCodeSymbol) {
476 return FromUTF16(thread, &char_code, 1);
477 }
478 return predefined_[char_code];
479}
480
481void Symbols::DumpStats(IsolateGroup* isolate_group) {
482 intptr_t size = -1;
483 intptr_t capacity = -1;
484 // First dump VM symbol table stats.
485 GetStats(Dart::vm_isolate_group(), &size, &capacity);
486 OS::PrintErr("VM Isolate: Number of symbols : %" Pd "\n", size);
487 OS::PrintErr("VM Isolate: Symbol table capacity : %" Pd "\n", capacity);
488 // Now dump regular isolate symbol table stats.
489 GetStats(isolate_group, &size, &capacity);
490 OS::PrintErr("Isolate: Number of symbols : %" Pd "\n", size);
491 OS::PrintErr("Isolate: Symbol table capacity : %" Pd "\n", capacity);
492 // TODO(koda): Consider recording growth and collision stats in HashTable,
493 // in DEBUG mode.
494}
495
496void Symbols::DumpTable(IsolateGroup* isolate_group) {
497 OS::PrintErr("symbols:\n");
498 CanonicalStringSet table(isolate_group->object_store()->symbol_table());
499 table.Dump();
500 table.Release();
501}
502
503} // namespace dart
static uint8_t src_p(uint8_t src, uint8_t dst)
SI F table(const skcms_Curve *curve, F v)
#define UNREACHABLE()
Definition assert.h:248
#define RELEASE_ASSERT(cond)
Definition assert.h:327
void Add(const T &value)
StringPtr ToSymbol() const
Definition symbols.cc:59
static IsolateGroup * vm_isolate_group()
Definition dart.h:69
static DART_NORETURN void ThrowOOM()
@ kOld
Definition heap.h:39
ObjectStore * object_store() const
Definition isolate.h:505
static IsolateGroup * Current()
Definition isolate.h:534
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
static ObjectPtr null()
Definition object.h:433
ObjectPtr ptr() const
Definition object.h:332
static Object * ReadOnlyHandle()
Definition object.h:431
bool IsCanonical() const
Definition object.h:335
bool IsOld() const
Definition object.h:391
void SetCanonical() const
Definition object.h:336
bool IsNull() const
Definition object.h:363
static Object & Handle()
Definition object.h:407
static OneByteStringPtr New(intptr_t len, Heap::Space space)
Definition object.cc:24447
StringPtr ToSymbol() const
Definition symbols.cc:46
static StringPtr FromLatin1(const uint8_t *latin1_array, intptr_t array_len, Heap::Space space=Heap::kNew)
Definition object.cc:23812
static constexpr intptr_t kMaxElements
Definition object.h:10152
bool IsOneByteString() const
Definition object.h:10290
intptr_t Length() const
Definition object.h:10189
bool HasHash() const
Definition object.h:10208
intptr_t CharSize() const
Definition object.cc:23601
bool IsTwoByteString() const
Definition object.h:10294
static StringPtr SubString(const String &str, intptr_t begin_index, Heap::Space space=Heap::kNew)
Definition object.cc:24159
static StringPtr Concat(const String &str1, const String &str2, Heap::Space space=Heap::kNew)
Definition object.cc:24116
bool IsSymbol() const
Definition object.h:10288
static StringPtr FromUTF16(const uint16_t *utf16_array, intptr_t array_len, Heap::Space space=Heap::kNew)
Definition object.cc:23818
uword Hash() const
Definition object.h:10195
static void GetStats(IsolateGroup *isolate_group, intptr_t *size, intptr_t *capacity)
Definition symbols.cc:180
static void InitFromSnapshot(IsolateGroup *isolate_group)
Definition symbols.cc:127
static StringPtr Lookup(Thread *thread, const StringType &str)
Definition symbols.cc:375
static const char * Name(SymbolId symbol)
Definition symbols.cc:66
static StringPtr LookupFromDot(Thread *thread, const String &str)
Definition symbols.cc:432
static StringPtr static StringPtr NewFormattedV(Thread *thread, const char *format, va_list args)
Definition symbols.cc:459
static StringPtr LookupFromGet(Thread *thread, const String &str)
Definition symbols.cc:424
static void Init(IsolateGroup *isolate_group)
Definition symbols.cc:80
static StringPtr FromConcat(Thread *thread, const String &str1, const String &str2)
Definition symbols.cc:235
@ kMaxOneCharCodeSymbol
Definition symbols.h:576
static StringPtr LookupFromSet(Thread *thread, const String &str)
Definition symbols.cc:428
static StringPtr FromUTF16(Thread *thread, const uint16_t *utf16_array, intptr_t len)
Definition symbols.cc:229
static constexpr int kNumberOfOneCharCodeSymbols
Definition symbols.h:600
static StringPtr FromGet(Thread *thread, const String &str)
Definition symbols.cc:247
static StringPtr FromSet(Thread *thread, const String &str)
Definition symbols.cc:251
static StringPtr FromDot(Thread *thread, const String &str)
Definition symbols.cc:255
static StringPtr FromCharCode(Thread *thread, uint16_t char_code)
Definition symbols.cc:474
static void SetupSymbolTable(IsolateGroup *isolate_group)
Definition symbols.cc:168
static StringPtr FromConcatAll(Thread *thread, const GrowableHandlePtrArray< const String > &strs)
Definition symbols.cc:262
static StringPtr FromUTF8(Thread *thread, const uint8_t *utf8_array, intptr_t len)
Definition symbols.cc:196
static StringPtr New(Thread *thread, const char *cstr)
Definition symbols.h:722
static void DumpStats(IsolateGroup *isolate_group)
Definition symbols.cc:481
static const String & Dot()
Definition symbols.h:612
static StringPtr LookupFromConcat(Thread *thread, const String &str1, const String &str2)
Definition symbols.cc:412
static StringPtr NewFormatted(Thread *thread, const char *format,...) PRINTF_ATTRIBUTE(2
Definition symbols.cc:450
static void DumpTable(IsolateGroup *isolate_group)
Definition symbols.cc:496
static StringPtr FromLatin1(Thread *thread, const uint8_t *latin1_array, intptr_t len)
Definition symbols.cc:223
static const String & Token(Token::Kind token)
Definition symbols.cc:71
Zone * zone() const
bool CanAcquireSafepointLocks() const
Definition thread.cc:1306
bool OwnsSafepoint() const
Definition thread.cc:1301
static Thread * Current()
Definition thread.h:361
IsolateGroup * isolate_group() const
Definition thread.h:540
@ kSupplementary
Definition unicode.h:46
static intptr_t CodeUnitCount(const uint8_t *utf8_array, intptr_t array_len, Type *type)
Definition unicode.cc:46
static intptr_t ReportInvalidByte(const uint8_t *utf8_array, intptr_t array_len, intptr_t len)
Definition unicode.cc:163
static bool DecodeToUTF16(const uint8_t *utf8_array, intptr_t array_len, uint16_t *dst, intptr_t len)
Definition unicode.cc:217
static bool DecodeToLatin1(const uint8_t *utf8_array, intptr_t array_len, uint8_t *dst, intptr_t len)
Definition unicode.cc:194
static bool IsLatin1(int32_t code_point)
Definition unicode.h:23
static constexpr T Maximum(T x, T y)
Definition utils.h:26
static int static int VSNPrint(char *str, size_t size, const char *format, va_list args)
ElementType * Alloc(intptr_t length)
#define ASSERT(E)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
static const uint8_t buffer[]
uint8_t value
GAsyncResult * result
uint32_t uint32_t * format
static const char *const names[]
Definition symbols.cc:24
const char *const name
CharArray< uint8_t > Latin1Array
CharArray< uint16_t > UTF16Array
StringPtr StringFrom(const uint8_t *data, intptr_t len, Heap::Space space)
Definition symbols.cc:38
static int8_t data[kExtLength]
UnorderedHashSet< SymbolTraits, WeakAcqRelStorageTraits > CanonicalStringSet
#define Pd
Definition globals.h:408
#define REUSABLE_ARRAY_HANDLESCOPE(thread)
#define REUSABLE_SMI_HANDLESCOPE(thread)
#define REUSABLE_WEAK_ARRAY_HANDLESCOPE(thread)
#define REUSABLE_OBJECT_HANDLESCOPE(thread)
#define DEFINE_SYMBOL_LITERAL(symbol, literal)
#define DEFINE_TOKEN_SYMBOL_INDEX(t, s, p, a)
#define PREDEFINED_SYMBOLS_LIST(V)
Definition symbols.h:18
#define DART_KEYWORD_LIST(KW)
Definition token.h:159
#define DART_TOKEN_LIST(TOK)
Definition token.h:34