1 | // Copyright (c) 2018, 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/compiler/frontend/kernel_translation_helper.h" |
6 | |
7 | #include "vm/class_finalizer.h" |
8 | #include "vm/compiler/aot/precompiler.h" |
9 | #include "vm/compiler/backend/flow_graph_compiler.h" |
10 | #include "vm/compiler/frontend/constant_reader.h" |
11 | #include "vm/flags.h" |
12 | #include "vm/log.h" |
13 | #include "vm/object_store.h" |
14 | #include "vm/parser.h" // for ParsedFunction |
15 | #include "vm/symbols.h" |
16 | |
17 | #define Z (zone_) |
18 | #define H (translation_helper_) |
19 | #define T (type_translator_) |
20 | #define I Isolate::Current() |
21 | |
22 | namespace dart { |
23 | namespace kernel { |
24 | |
25 | TranslationHelper::TranslationHelper(Thread* thread) |
26 | : thread_(thread), |
27 | zone_(thread->zone()), |
28 | isolate_(thread->isolate()), |
29 | allocation_space_(Heap::kNew), |
30 | string_offsets_(TypedData::Handle(Z)), |
31 | string_data_(ExternalTypedData::Handle(Z)), |
32 | canonical_names_(TypedData::Handle(Z)), |
33 | metadata_payloads_(ExternalTypedData::Handle(Z)), |
34 | metadata_mappings_(ExternalTypedData::Handle(Z)), |
35 | constants_(Array::Handle(Z)), |
36 | constants_table_(ExternalTypedData::Handle(Z)), |
37 | info_(KernelProgramInfo::Handle(Z)), |
38 | name_index_handle_(Smi::Handle(Z)) {} |
39 | |
40 | TranslationHelper::TranslationHelper(Thread* thread, Heap::Space space) |
41 | : thread_(thread), |
42 | zone_(thread->zone()), |
43 | isolate_(thread->isolate()), |
44 | allocation_space_(space), |
45 | string_offsets_(TypedData::Handle(Z)), |
46 | string_data_(ExternalTypedData::Handle(Z)), |
47 | canonical_names_(TypedData::Handle(Z)), |
48 | metadata_payloads_(ExternalTypedData::Handle(Z)), |
49 | metadata_mappings_(ExternalTypedData::Handle(Z)), |
50 | constants_(Array::Handle(Z)), |
51 | constants_table_(ExternalTypedData::Handle(Z)), |
52 | info_(KernelProgramInfo::Handle(Z)), |
53 | name_index_handle_(Smi::Handle(Z)) {} |
54 | |
55 | void TranslationHelper::Reset() { |
56 | string_offsets_ = TypedData::null(); |
57 | string_data_ = ExternalTypedData::null(); |
58 | canonical_names_ = TypedData::null(); |
59 | metadata_payloads_ = ExternalTypedData::null(); |
60 | metadata_mappings_ = ExternalTypedData::null(); |
61 | constants_ = Array::null(); |
62 | } |
63 | |
64 | void TranslationHelper::InitFromScript(const Script& script) { |
65 | const KernelProgramInfo& info = |
66 | KernelProgramInfo::Handle(Z, script.kernel_program_info()); |
67 | if (info.IsNull()) { |
68 | // If there is no kernel data associated with the script, then |
69 | // do not bother initializing!. |
70 | // This can happen with few special functions like |
71 | // NoSuchMethodDispatcher and InvokeFieldDispatcher. |
72 | return; |
73 | } |
74 | InitFromKernelProgramInfo(info); |
75 | } |
76 | |
77 | void TranslationHelper::InitFromKernelProgramInfo( |
78 | const KernelProgramInfo& info) { |
79 | SetStringOffsets(TypedData::Handle(Z, info.string_offsets())); |
80 | SetStringData(ExternalTypedData::Handle(Z, info.string_data())); |
81 | SetCanonicalNames(TypedData::Handle(Z, info.canonical_names())); |
82 | SetMetadataPayloads(ExternalTypedData::Handle(Z, info.metadata_payloads())); |
83 | SetMetadataMappings(ExternalTypedData::Handle(Z, info.metadata_mappings())); |
84 | SetConstants(Array::Handle(Z, info.constants())); |
85 | SetConstantsTable(ExternalTypedData::Handle(Z, info.constants_table())); |
86 | SetKernelProgramInfo(info); |
87 | } |
88 | |
89 | GrowableObjectArrayPtr TranslationHelper::EnsurePotentialPragmaFunctions() { |
90 | auto& funcs = |
91 | GrowableObjectArray::Handle(Z, info_.potential_pragma_functions()); |
92 | if (funcs.IsNull()) { |
93 | funcs = GrowableObjectArray::New(16, Heap::kNew); |
94 | info_.set_potential_pragma_functions(funcs); |
95 | } |
96 | return funcs.raw(); |
97 | } |
98 | |
99 | void TranslationHelper::AddPotentialExtensionLibrary(const Library& library) { |
100 | if (potential_extension_libraries_ == nullptr) { |
101 | potential_extension_libraries_ = |
102 | &GrowableObjectArray::Handle(Z, GrowableObjectArray::New()); |
103 | } |
104 | potential_extension_libraries_->Add(library); |
105 | } |
106 | |
107 | GrowableObjectArrayPtr TranslationHelper::GetPotentialExtensionLibraries() { |
108 | if (potential_extension_libraries_ != nullptr) { |
109 | GrowableObjectArray* result = potential_extension_libraries_; |
110 | potential_extension_libraries_ = nullptr; |
111 | return result->raw(); |
112 | } |
113 | return GrowableObjectArray::null(); |
114 | } |
115 | |
116 | void TranslationHelper::SetStringOffsets(const TypedData& string_offsets) { |
117 | ASSERT(string_offsets_.IsNull()); |
118 | string_offsets_ = string_offsets.raw(); |
119 | } |
120 | |
121 | void TranslationHelper::SetStringData(const ExternalTypedData& string_data) { |
122 | ASSERT(string_data_.IsNull()); |
123 | string_data_ = string_data.raw(); |
124 | } |
125 | |
126 | void TranslationHelper::SetCanonicalNames(const TypedData& canonical_names) { |
127 | ASSERT(canonical_names_.IsNull()); |
128 | canonical_names_ = canonical_names.raw(); |
129 | } |
130 | |
131 | void TranslationHelper::SetMetadataPayloads( |
132 | const ExternalTypedData& metadata_payloads) { |
133 | ASSERT(metadata_payloads_.IsNull()); |
134 | ASSERT(Utils::IsAligned(metadata_payloads.DataAddr(0), kWordSize)); |
135 | metadata_payloads_ = metadata_payloads.raw(); |
136 | } |
137 | |
138 | void TranslationHelper::SetMetadataMappings( |
139 | const ExternalTypedData& metadata_mappings) { |
140 | ASSERT(metadata_mappings_.IsNull()); |
141 | metadata_mappings_ = metadata_mappings.raw(); |
142 | } |
143 | |
144 | void TranslationHelper::SetConstants(const Array& constants) { |
145 | ASSERT(constants_.IsNull() || |
146 | (constants.IsNull() || constants.Length() == 0)); |
147 | constants_ = constants.raw(); |
148 | } |
149 | |
150 | void TranslationHelper::SetConstantsTable( |
151 | const ExternalTypedData& constants_table) { |
152 | ASSERT(constants_table_.IsNull()); |
153 | constants_table_ = constants_table.raw(); |
154 | } |
155 | |
156 | void TranslationHelper::SetKernelProgramInfo(const KernelProgramInfo& info) { |
157 | info_ = info.raw(); |
158 | } |
159 | |
160 | intptr_t TranslationHelper::StringOffset(StringIndex index) const { |
161 | return string_offsets_.GetUint32(index << 2); |
162 | } |
163 | |
164 | intptr_t TranslationHelper::StringSize(StringIndex index) const { |
165 | return StringOffset(StringIndex(index + 1)) - StringOffset(index); |
166 | } |
167 | |
168 | uint8_t TranslationHelper::CharacterAt(StringIndex string_index, |
169 | intptr_t index) { |
170 | ASSERT(index < StringSize(string_index)); |
171 | return string_data_.GetUint8(StringOffset(string_index) + index); |
172 | } |
173 | |
174 | uint8_t* TranslationHelper::StringBuffer(StringIndex string_index) const { |
175 | // Though this implementation appears like it could be replaced by |
176 | // string_data_.DataAddr(StringOffset(string_index)), it can't quite. If the |
177 | // last string in the string table is a zero length string, then the latter |
178 | // expression will try to return the address that is one past the backing |
179 | // store of the string_data_ table. Though this is safe in C++ as long as the |
180 | // address is not dereferenced, it will trigger the assert in |
181 | // ExternalTypedData::DataAddr. |
182 | ASSERT(Thread::Current()->no_safepoint_scope_depth() > 0); |
183 | return reinterpret_cast<uint8_t*>(string_data_.DataAddr(0)) + |
184 | StringOffset(string_index); |
185 | } |
186 | |
187 | bool TranslationHelper::StringEquals(StringIndex string_index, |
188 | const char* other) { |
189 | intptr_t length = strlen(other); |
190 | if (length != StringSize(string_index)) return false; |
191 | |
192 | NoSafepointScope no_safepoint; |
193 | return memcmp(StringBuffer(string_index), other, length) == 0; |
194 | } |
195 | |
196 | NameIndex TranslationHelper::CanonicalNameParent(NameIndex name) { |
197 | // Canonical names are pairs of 4-byte parent and string indexes, so the size |
198 | // of an entry is 8 bytes. The parent is biased: 0 represents the root name |
199 | // and N+1 represents the name with index N. |
200 | return NameIndex(static_cast<intptr_t>(canonical_names_.GetUint32(8 * name)) - |
201 | 1); |
202 | } |
203 | |
204 | StringIndex TranslationHelper::CanonicalNameString(NameIndex name) { |
205 | return StringIndex(canonical_names_.GetUint32((8 * name) + 4)); |
206 | } |
207 | |
208 | bool TranslationHelper::IsAdministrative(NameIndex name) { |
209 | // Administrative names start with '@'. |
210 | StringIndex name_string = CanonicalNameString(name); |
211 | return (StringSize(name_string) > 0) && (CharacterAt(name_string, 0) == '@'); |
212 | } |
213 | |
214 | bool TranslationHelper::IsPrivate(NameIndex name) { |
215 | // Private names start with '_'. |
216 | StringIndex name_string = CanonicalNameString(name); |
217 | return (StringSize(name_string) > 0) && (CharacterAt(name_string, 0) == '_'); |
218 | } |
219 | |
220 | bool TranslationHelper::IsRoot(NameIndex name) { |
221 | return name == -1; |
222 | } |
223 | |
224 | bool TranslationHelper::IsLibrary(NameIndex name) { |
225 | // Libraries are the only canonical names with the root as their parent. |
226 | return !IsRoot(name) && IsRoot(CanonicalNameParent(name)); |
227 | } |
228 | |
229 | bool TranslationHelper::IsClass(NameIndex name) { |
230 | // Classes have the library as their parent and are not an administrative |
231 | // name starting with @. |
232 | return !IsAdministrative(name) && !IsRoot(name) && |
233 | IsLibrary(CanonicalNameParent(name)); |
234 | } |
235 | |
236 | bool TranslationHelper::IsMember(NameIndex name) { |
237 | return IsConstructor(name) || IsField(name) || IsProcedure(name); |
238 | } |
239 | |
240 | bool TranslationHelper::IsField(NameIndex name) { |
241 | // Fields with private names have the import URI of the library where they are |
242 | // visible as the parent and the string "@fields" as the parent's parent. |
243 | // Fields with non-private names have the string "@fields' as the parent. |
244 | if (IsRoot(name)) { |
245 | return false; |
246 | } |
247 | NameIndex kind = CanonicalNameParent(name); |
248 | if (IsPrivate(name)) { |
249 | kind = CanonicalNameParent(kind); |
250 | } |
251 | return StringEquals(CanonicalNameString(kind), "@fields" ); |
252 | } |
253 | |
254 | bool TranslationHelper::IsConstructor(NameIndex name) { |
255 | // Constructors with private names have the import URI of the library where |
256 | // they are visible as the parent and the string "@constructors" as the |
257 | // parent's parent. Constructors with non-private names have the string |
258 | // "@constructors" as the parent. |
259 | if (IsRoot(name)) { |
260 | return false; |
261 | } |
262 | NameIndex kind = CanonicalNameParent(name); |
263 | if (IsPrivate(name)) { |
264 | kind = CanonicalNameParent(kind); |
265 | } |
266 | return StringEquals(CanonicalNameString(kind), "@constructors" ); |
267 | } |
268 | |
269 | bool TranslationHelper::IsProcedure(NameIndex name) { |
270 | return IsMethod(name) || IsGetter(name) || IsSetter(name) || IsFactory(name); |
271 | } |
272 | |
273 | bool TranslationHelper::IsMethod(NameIndex name) { |
274 | // Methods with private names have the import URI of the library where they |
275 | // are visible as the parent and the string "@methods" as the parent's parent. |
276 | // Methods with non-private names have the string "@methods" as the parent. |
277 | if (IsRoot(name)) { |
278 | return false; |
279 | } |
280 | NameIndex kind = CanonicalNameParent(name); |
281 | if (IsPrivate(name)) { |
282 | kind = CanonicalNameParent(kind); |
283 | } |
284 | return StringEquals(CanonicalNameString(kind), "@methods" ); |
285 | } |
286 | |
287 | bool TranslationHelper::IsGetter(NameIndex name) { |
288 | // Getters with private names have the import URI of the library where they |
289 | // are visible as the parent and the string "@getters" as the parent's parent. |
290 | // Getters with non-private names have the string "@getters" as the parent. |
291 | if (IsRoot(name)) { |
292 | return false; |
293 | } |
294 | NameIndex kind = CanonicalNameParent(name); |
295 | if (IsPrivate(name)) { |
296 | kind = CanonicalNameParent(kind); |
297 | } |
298 | return StringEquals(CanonicalNameString(kind), "@getters" ); |
299 | } |
300 | |
301 | bool TranslationHelper::IsSetter(NameIndex name) { |
302 | // Setters with private names have the import URI of the library where they |
303 | // are visible as the parent and the string "@setters" as the parent's parent. |
304 | // Setters with non-private names have the string "@setters" as the parent. |
305 | if (IsRoot(name)) { |
306 | return false; |
307 | } |
308 | NameIndex kind = CanonicalNameParent(name); |
309 | if (IsPrivate(name)) { |
310 | kind = CanonicalNameParent(kind); |
311 | } |
312 | return StringEquals(CanonicalNameString(kind), "@setters" ); |
313 | } |
314 | |
315 | bool TranslationHelper::IsFactory(NameIndex name) { |
316 | // Factories with private names have the import URI of the library where they |
317 | // are visible as the parent and the string "@factories" as the parent's |
318 | // parent. Factories with non-private names have the string "@factories" as |
319 | // the parent. |
320 | if (IsRoot(name)) { |
321 | return false; |
322 | } |
323 | NameIndex kind = CanonicalNameParent(name); |
324 | if (IsPrivate(name)) { |
325 | kind = CanonicalNameParent(kind); |
326 | } |
327 | return StringEquals(CanonicalNameString(kind), "@factories" ); |
328 | } |
329 | |
330 | NameIndex TranslationHelper::EnclosingName(NameIndex name) { |
331 | ASSERT(IsField(name) || IsConstructor(name) || IsProcedure(name)); |
332 | NameIndex enclosing = CanonicalNameParent(CanonicalNameParent(name)); |
333 | if (IsPrivate(name)) { |
334 | enclosing = CanonicalNameParent(enclosing); |
335 | } |
336 | ASSERT(IsLibrary(enclosing) || IsClass(enclosing)); |
337 | return enclosing; |
338 | } |
339 | |
340 | InstancePtr TranslationHelper::Canonicalize(const Instance& instance) { |
341 | if (instance.IsNull()) return instance.raw(); |
342 | |
343 | const char* error_str = NULL; |
344 | InstancePtr result = instance.CheckAndCanonicalize(thread(), &error_str); |
345 | if (result == Object::null()) { |
346 | ReportError("Invalid const object %s" , error_str); |
347 | } |
348 | return result; |
349 | } |
350 | |
351 | const String& TranslationHelper::DartString(const char* content, |
352 | Heap::Space space) { |
353 | return String::ZoneHandle(Z, String::New(content, space)); |
354 | } |
355 | |
356 | String& TranslationHelper::DartString(StringIndex string_index, |
357 | Heap::Space space) { |
358 | intptr_t length = StringSize(string_index); |
359 | uint8_t* buffer = Z->Alloc<uint8_t>(length); |
360 | { |
361 | NoSafepointScope no_safepoint; |
362 | memmove(buffer, StringBuffer(string_index), length); |
363 | } |
364 | return String::ZoneHandle(Z, String::FromUTF8(buffer, length, space)); |
365 | } |
366 | |
367 | String& TranslationHelper::DartString(const uint8_t* utf8_array, |
368 | intptr_t len, |
369 | Heap::Space space) { |
370 | return String::ZoneHandle(Z, String::FromUTF8(utf8_array, len, space)); |
371 | } |
372 | |
373 | const String& TranslationHelper::DartSymbolPlain(const char* content) const { |
374 | return String::ZoneHandle(Z, Symbols::New(thread_, content)); |
375 | } |
376 | |
377 | String& TranslationHelper::DartSymbolPlain(StringIndex string_index) const { |
378 | intptr_t length = StringSize(string_index); |
379 | uint8_t* buffer = Z->Alloc<uint8_t>(length); |
380 | { |
381 | NoSafepointScope no_safepoint; |
382 | memmove(buffer, StringBuffer(string_index), length); |
383 | } |
384 | String& result = |
385 | String::ZoneHandle(Z, Symbols::FromUTF8(thread_, buffer, length)); |
386 | return result; |
387 | } |
388 | |
389 | const String& TranslationHelper::DartSymbolObfuscate( |
390 | const char* content) const { |
391 | String& result = String::ZoneHandle(Z, Symbols::New(thread_, content)); |
392 | if (I->obfuscate()) { |
393 | Obfuscator obfuscator(thread_, String::Handle(Z)); |
394 | result = obfuscator.Rename(result, true); |
395 | } |
396 | return result; |
397 | } |
398 | |
399 | String& TranslationHelper::DartSymbolObfuscate(StringIndex string_index) const { |
400 | intptr_t length = StringSize(string_index); |
401 | uint8_t* buffer = Z->Alloc<uint8_t>(length); |
402 | { |
403 | NoSafepointScope no_safepoint; |
404 | memmove(buffer, StringBuffer(string_index), length); |
405 | } |
406 | String& result = |
407 | String::ZoneHandle(Z, Symbols::FromUTF8(thread_, buffer, length)); |
408 | if (I->obfuscate()) { |
409 | Obfuscator obfuscator(thread_, String::Handle(Z)); |
410 | result = obfuscator.Rename(result, true); |
411 | } |
412 | return result; |
413 | } |
414 | |
415 | String& TranslationHelper::DartIdentifier(const Library& lib, |
416 | StringIndex string_index) { |
417 | String& name = DartString(string_index); |
418 | ManglePrivateName(lib, &name); |
419 | return name; |
420 | } |
421 | |
422 | const String& TranslationHelper::DartClassName(NameIndex kernel_class) { |
423 | ASSERT(IsClass(kernel_class)); |
424 | String& name = DartString(CanonicalNameString(kernel_class)); |
425 | return ManglePrivateName(CanonicalNameParent(kernel_class), &name); |
426 | } |
427 | |
428 | const String& TranslationHelper::DartConstructorName(NameIndex constructor) { |
429 | ASSERT(IsConstructor(constructor)); |
430 | return DartFactoryName(constructor); |
431 | } |
432 | |
433 | const String& TranslationHelper::DartProcedureName(NameIndex procedure) { |
434 | ASSERT(IsProcedure(procedure)); |
435 | if (IsSetter(procedure)) { |
436 | return DartSetterName(procedure); |
437 | } else if (IsGetter(procedure)) { |
438 | return DartGetterName(procedure); |
439 | } else if (IsFactory(procedure)) { |
440 | return DartFactoryName(procedure); |
441 | } else { |
442 | return DartMethodName(procedure); |
443 | } |
444 | } |
445 | |
446 | const String& TranslationHelper::DartSetterName(NameIndex setter) { |
447 | return DartSetterName(CanonicalNameParent(setter), |
448 | CanonicalNameString(setter)); |
449 | } |
450 | |
451 | const String& TranslationHelper::DartSetterName(NameIndex parent, |
452 | StringIndex setter) { |
453 | // The names flowing into [setter] are coming from the Kernel file: |
454 | // * user-defined setters: `fieldname=` |
455 | // * property-set expressions: `fieldname` |
456 | // |
457 | // The VM uses `get:fieldname` and `set:fieldname`. |
458 | // |
459 | // => In order to be consistent, we remove the `=` always and adopt the VM |
460 | // conventions. |
461 | intptr_t size = StringSize(setter); |
462 | ASSERT(size > 0); |
463 | if (CharacterAt(setter, size - 1) == '=') { |
464 | --size; |
465 | } |
466 | uint8_t* buffer = Z->Alloc<uint8_t>(size); |
467 | { |
468 | NoSafepointScope no_safepoint; |
469 | memmove(buffer, StringBuffer(setter), size); |
470 | } |
471 | String& name = |
472 | String::ZoneHandle(Z, String::FromUTF8(buffer, size, allocation_space_)); |
473 | ManglePrivateName(parent, &name); |
474 | name = Field::SetterSymbol(name); |
475 | return name; |
476 | } |
477 | |
478 | const String& TranslationHelper::DartGetterName(NameIndex getter) { |
479 | return DartGetterName(CanonicalNameParent(getter), |
480 | CanonicalNameString(getter)); |
481 | } |
482 | |
483 | const String& TranslationHelper::DartGetterName(NameIndex parent, |
484 | StringIndex getter) { |
485 | String& name = DartString(getter); |
486 | ManglePrivateName(parent, &name); |
487 | name = Field::GetterSymbol(name); |
488 | return name; |
489 | } |
490 | |
491 | const String& TranslationHelper::DartFieldName(NameIndex field) { |
492 | return DartFieldName(CanonicalNameParent(field), CanonicalNameString(field)); |
493 | } |
494 | |
495 | const String& TranslationHelper::DartFieldName(NameIndex parent, |
496 | StringIndex field) { |
497 | String& name = DartString(field); |
498 | return ManglePrivateName(parent, &name); |
499 | } |
500 | |
501 | const String& TranslationHelper::DartMethodName(NameIndex method) { |
502 | return DartMethodName(CanonicalNameParent(method), |
503 | CanonicalNameString(method)); |
504 | } |
505 | |
506 | const String& TranslationHelper::DartMethodName(NameIndex parent, |
507 | StringIndex method) { |
508 | String& name = DartString(method); |
509 | return ManglePrivateName(parent, &name); |
510 | } |
511 | |
512 | const String& TranslationHelper::DartFactoryName(NameIndex factory) { |
513 | ASSERT(IsConstructor(factory) || IsFactory(factory)); |
514 | GrowableHandlePtrArray<const String> pieces(Z, 3); |
515 | pieces.Add(DartClassName(EnclosingName(factory))); |
516 | pieces.Add(Symbols::Dot()); |
517 | // [DartMethodName] will mangle the name. |
518 | pieces.Add(DartMethodName(factory)); |
519 | return String::ZoneHandle(Z, Symbols::FromConcatAll(thread_, pieces)); |
520 | } |
521 | |
522 | // TODO(https://github.com/dart-lang/sdk/issues/37517): Should emit code to |
523 | // throw a NoSuchMethodError. |
524 | static void CheckStaticLookup(const Object& target) { |
525 | if (target.IsNull()) { |
526 | #ifndef PRODUCT |
527 | ASSERT(Isolate::Current()->HasAttemptedReload()); |
528 | Report::LongJump(LanguageError::Handle(LanguageError::New(String::Handle( |
529 | String::New("Unimplemented handling of missing static target" ))))); |
530 | #else |
531 | UNREACHABLE(); |
532 | #endif |
533 | } |
534 | } |
535 | |
536 | LibraryPtr TranslationHelper::LookupLibraryByKernelLibrary( |
537 | NameIndex kernel_library) { |
538 | // We only use the string and don't rely on having any particular parent. |
539 | // This ASSERT is just a sanity check. |
540 | ASSERT(IsLibrary(kernel_library) || |
541 | IsAdministrative(CanonicalNameParent(kernel_library))); |
542 | { |
543 | name_index_handle_ = Smi::New(kernel_library); |
544 | LibraryPtr raw_lib = info_.LookupLibrary(thread_, name_index_handle_); |
545 | NoSafepointScope no_safepoint_scope(thread_); |
546 | if (raw_lib != Library::null()) { |
547 | return raw_lib; |
548 | } |
549 | } |
550 | |
551 | const String& library_name = |
552 | DartSymbolPlain(CanonicalNameString(kernel_library)); |
553 | ASSERT(!library_name.IsNull()); |
554 | const Library& library = |
555 | Library::Handle(Z, Library::LookupLibrary(thread_, library_name)); |
556 | CheckStaticLookup(library); |
557 | name_index_handle_ = Smi::New(kernel_library); |
558 | return info_.InsertLibrary(thread_, name_index_handle_, library); |
559 | } |
560 | |
561 | ClassPtr TranslationHelper::LookupClassByKernelClass(NameIndex kernel_class) { |
562 | ASSERT(IsClass(kernel_class)); |
563 | { |
564 | name_index_handle_ = Smi::New(kernel_class); |
565 | ClassPtr raw_class = info_.LookupClass(thread_, name_index_handle_); |
566 | NoSafepointScope no_safepoint_scope(thread_); |
567 | if (raw_class != Class::null()) { |
568 | return raw_class; |
569 | } |
570 | } |
571 | |
572 | const String& class_name = DartClassName(kernel_class); |
573 | NameIndex kernel_library = CanonicalNameParent(kernel_class); |
574 | Library& library = |
575 | Library::Handle(Z, LookupLibraryByKernelLibrary(kernel_library)); |
576 | ASSERT(!library.IsNull()); |
577 | const Class& klass = |
578 | Class::Handle(Z, library.LookupClassAllowPrivate(class_name)); |
579 | CheckStaticLookup(klass); |
580 | ASSERT(!klass.IsNull()); |
581 | if (klass.is_declared_in_bytecode()) { |
582 | klass.EnsureDeclarationLoaded(); |
583 | } |
584 | name_index_handle_ = Smi::New(kernel_class); |
585 | return info_.InsertClass(thread_, name_index_handle_, klass); |
586 | } |
587 | |
588 | FieldPtr TranslationHelper::LookupFieldByKernelField(NameIndex kernel_field) { |
589 | ASSERT(IsField(kernel_field)); |
590 | NameIndex enclosing = EnclosingName(kernel_field); |
591 | |
592 | Class& klass = Class::Handle(Z); |
593 | if (IsLibrary(enclosing)) { |
594 | Library& library = |
595 | Library::Handle(Z, LookupLibraryByKernelLibrary(enclosing)); |
596 | klass = library.toplevel_class(); |
597 | CheckStaticLookup(klass); |
598 | } else { |
599 | ASSERT(IsClass(enclosing)); |
600 | klass = LookupClassByKernelClass(enclosing); |
601 | } |
602 | Field& field = Field::Handle( |
603 | Z, klass.LookupFieldAllowPrivate( |
604 | DartSymbolObfuscate(CanonicalNameString(kernel_field)))); |
605 | CheckStaticLookup(field); |
606 | return field.raw(); |
607 | } |
608 | |
609 | FunctionPtr TranslationHelper::LookupStaticMethodByKernelProcedure( |
610 | NameIndex procedure) { |
611 | const String& procedure_name = DartProcedureName(procedure); |
612 | |
613 | // The parent is either a library or a class (in which case the procedure is a |
614 | // static method). |
615 | NameIndex enclosing = EnclosingName(procedure); |
616 | if (IsLibrary(enclosing)) { |
617 | Library& library = |
618 | Library::Handle(Z, LookupLibraryByKernelLibrary(enclosing)); |
619 | Function& function = |
620 | Function::Handle(Z, library.LookupFunctionAllowPrivate(procedure_name)); |
621 | CheckStaticLookup(function); |
622 | return function.raw(); |
623 | } else { |
624 | ASSERT(IsClass(enclosing)); |
625 | Class& klass = Class::Handle(Z, LookupClassByKernelClass(enclosing)); |
626 | Function& function = Function::ZoneHandle( |
627 | Z, klass.LookupFunctionAllowPrivate(procedure_name)); |
628 | CheckStaticLookup(function); |
629 | // Redirecting factory must be resolved. |
630 | ASSERT(!function.IsRedirectingFactory() || |
631 | function.RedirectionTarget() != Function::null()); |
632 | return function.raw(); |
633 | } |
634 | } |
635 | |
636 | FunctionPtr TranslationHelper::LookupConstructorByKernelConstructor( |
637 | NameIndex constructor) { |
638 | ASSERT(IsConstructor(constructor)); |
639 | Class& klass = |
640 | Class::Handle(Z, LookupClassByKernelClass(EnclosingName(constructor))); |
641 | CheckStaticLookup(klass); |
642 | return LookupConstructorByKernelConstructor(klass, constructor); |
643 | } |
644 | |
645 | FunctionPtr TranslationHelper::LookupConstructorByKernelConstructor( |
646 | const Class& owner, |
647 | NameIndex constructor) { |
648 | ASSERT(IsConstructor(constructor)); |
649 | Function& function = Function::Handle( |
650 | Z, owner.LookupConstructorAllowPrivate(DartConstructorName(constructor))); |
651 | CheckStaticLookup(function); |
652 | return function.raw(); |
653 | } |
654 | |
655 | FunctionPtr TranslationHelper::LookupConstructorByKernelConstructor( |
656 | const Class& owner, |
657 | StringIndex constructor_name) { |
658 | GrowableHandlePtrArray<const String> pieces(Z, 3); |
659 | pieces.Add(String::Handle(Z, owner.Name())); |
660 | pieces.Add(Symbols::Dot()); |
661 | String& name = DartSymbolPlain(constructor_name); |
662 | pieces.Add(ManglePrivateName(Library::Handle(owner.library()), &name)); |
663 | |
664 | String& new_name = |
665 | String::ZoneHandle(Z, Symbols::FromConcatAll(thread_, pieces)); |
666 | FunctionPtr function = owner.LookupConstructorAllowPrivate(new_name); |
667 | ASSERT(function != Object::null()); |
668 | return function; |
669 | } |
670 | |
671 | FunctionPtr TranslationHelper::LookupMethodByMember(NameIndex target, |
672 | const String& method_name) { |
673 | NameIndex kernel_class = EnclosingName(target); |
674 | Class& klass = Class::Handle(Z, LookupClassByKernelClass(kernel_class)); |
675 | |
676 | Function& function = |
677 | Function::Handle(Z, klass.LookupFunctionAllowPrivate(method_name)); |
678 | #ifdef DEBUG |
679 | if (function.IsNull()) { |
680 | THR_Print("Unable to find \'%s\' in %s\n" , method_name.ToCString(), |
681 | klass.ToCString()); |
682 | } |
683 | #endif |
684 | CheckStaticLookup(function); |
685 | ASSERT(!function.IsNull()); |
686 | return function.raw(); |
687 | } |
688 | |
689 | FunctionPtr TranslationHelper::LookupDynamicFunction(const Class& klass, |
690 | const String& name) { |
691 | // Search the superclass chain for the selector. |
692 | Class& iterate_klass = Class::Handle(Z, klass.raw()); |
693 | while (!iterate_klass.IsNull()) { |
694 | FunctionPtr function = |
695 | iterate_klass.LookupDynamicFunctionAllowPrivate(name); |
696 | if (function != Object::null()) { |
697 | return function; |
698 | } |
699 | iterate_klass = iterate_klass.SuperClass(); |
700 | } |
701 | return Function::null(); |
702 | } |
703 | |
704 | Type& TranslationHelper::GetDeclarationType(const Class& klass) { |
705 | ASSERT(!klass.IsNull()); |
706 | // Note that if cls is _Closure, the returned type will be _Closure, |
707 | // and not the signature type. |
708 | Type& type = Type::ZoneHandle(Z); |
709 | if (klass.is_type_finalized()) { |
710 | type = klass.DeclarationType(); |
711 | } else { |
712 | // Note that the type argument vector is not yet extended. |
713 | type = Type::New(klass, TypeArguments::Handle(Z, klass.type_parameters()), |
714 | klass.token_pos()); |
715 | } |
716 | return type; |
717 | } |
718 | |
719 | void TranslationHelper::SetupFieldAccessorFunction( |
720 | const Class& klass, |
721 | const Function& function, |
722 | const AbstractType& field_type) { |
723 | bool is_setter = function.IsImplicitSetterFunction(); |
724 | bool is_method = !function.IsStaticFunction(); |
725 | intptr_t parameter_count = (is_method ? 1 : 0) + (is_setter ? 1 : 0); |
726 | |
727 | function.SetNumOptionalParameters(0, false); |
728 | function.set_num_fixed_parameters(parameter_count); |
729 | function.set_parameter_types( |
730 | Array::Handle(Z, Array::New(parameter_count, Heap::kOld))); |
731 | function.set_parameter_names( |
732 | Array::Handle(Z, Array::New(parameter_count, Heap::kOld))); |
733 | |
734 | intptr_t pos = 0; |
735 | if (is_method) { |
736 | function.SetParameterTypeAt(pos, GetDeclarationType(klass)); |
737 | function.SetParameterNameAt(pos, Symbols::This()); |
738 | pos++; |
739 | } |
740 | if (is_setter) { |
741 | function.SetParameterTypeAt(pos, field_type); |
742 | function.SetParameterNameAt(pos, Symbols::Value()); |
743 | pos++; |
744 | } |
745 | } |
746 | |
747 | void TranslationHelper::ReportError(const char* format, ...) { |
748 | const Script& null_script = Script::Handle(Z); |
749 | |
750 | va_list args; |
751 | va_start(args, format); |
752 | Report::MessageV(Report::kError, null_script, TokenPosition::kNoSource, |
753 | Report::AtLocation, format, args); |
754 | va_end(args); |
755 | UNREACHABLE(); |
756 | } |
757 | |
758 | void TranslationHelper::ReportError(const Script& script, |
759 | const TokenPosition position, |
760 | const char* format, |
761 | ...) { |
762 | va_list args; |
763 | va_start(args, format); |
764 | Report::MessageV(Report::kError, script, position, Report::AtLocation, format, |
765 | args); |
766 | va_end(args); |
767 | UNREACHABLE(); |
768 | } |
769 | |
770 | void TranslationHelper::ReportError(const Error& prev_error, |
771 | const char* format, |
772 | ...) { |
773 | const Script& null_script = Script::Handle(Z); |
774 | |
775 | va_list args; |
776 | va_start(args, format); |
777 | Report::LongJumpV(prev_error, null_script, TokenPosition::kNoSource, format, |
778 | args); |
779 | va_end(args); |
780 | UNREACHABLE(); |
781 | } |
782 | |
783 | void TranslationHelper::ReportError(const Error& prev_error, |
784 | const Script& script, |
785 | const TokenPosition position, |
786 | const char* format, |
787 | ...) { |
788 | va_list args; |
789 | va_start(args, format); |
790 | Report::LongJumpV(prev_error, script, position, format, args); |
791 | va_end(args); |
792 | UNREACHABLE(); |
793 | } |
794 | |
795 | String& TranslationHelper::ManglePrivateName(NameIndex parent, |
796 | String* name_to_modify, |
797 | bool symbolize, |
798 | bool obfuscate) { |
799 | if (name_to_modify->Length() >= 1 && name_to_modify->CharAt(0) == '_') { |
800 | const Library& library = |
801 | Library::Handle(Z, LookupLibraryByKernelLibrary(parent)); |
802 | *name_to_modify = library.PrivateName(*name_to_modify); |
803 | if (obfuscate && I->obfuscate()) { |
804 | const String& library_key = String::Handle(library.private_key()); |
805 | Obfuscator obfuscator(thread_, library_key); |
806 | *name_to_modify = obfuscator.Rename(*name_to_modify); |
807 | } |
808 | } else if (symbolize) { |
809 | *name_to_modify = Symbols::New(thread_, *name_to_modify); |
810 | if (obfuscate && I->obfuscate()) { |
811 | const String& library_key = String::Handle(); |
812 | Obfuscator obfuscator(thread_, library_key); |
813 | *name_to_modify = obfuscator.Rename(*name_to_modify); |
814 | } |
815 | } |
816 | return *name_to_modify; |
817 | } |
818 | |
819 | String& TranslationHelper::ManglePrivateName(const Library& library, |
820 | String* name_to_modify, |
821 | bool symbolize, |
822 | bool obfuscate) { |
823 | if (name_to_modify->Length() >= 1 && name_to_modify->CharAt(0) == '_') { |
824 | *name_to_modify = library.PrivateName(*name_to_modify); |
825 | if (obfuscate && I->obfuscate()) { |
826 | const String& library_key = String::Handle(library.private_key()); |
827 | Obfuscator obfuscator(thread_, library_key); |
828 | *name_to_modify = obfuscator.Rename(*name_to_modify); |
829 | } |
830 | } else if (symbolize) { |
831 | *name_to_modify = Symbols::New(thread_, *name_to_modify); |
832 | if (obfuscate && I->obfuscate()) { |
833 | const String& library_key = String::Handle(); |
834 | Obfuscator obfuscator(thread_, library_key); |
835 | *name_to_modify = obfuscator.Rename(*name_to_modify); |
836 | } |
837 | } |
838 | return *name_to_modify; |
839 | } |
840 | |
841 | void FunctionNodeHelper::ReadUntilExcluding(Field field) { |
842 | if (field <= next_read_) return; |
843 | |
844 | // Ordered with fall-through. |
845 | switch (next_read_) { |
846 | case kStart: { |
847 | Tag tag = helper_->ReadTag(); // read tag. |
848 | ASSERT(tag == kFunctionNode); |
849 | if (++next_read_ == field) return; |
850 | } |
851 | FALL_THROUGH; |
852 | case kPosition: |
853 | position_ = helper_->ReadPosition(); // read position. |
854 | if (++next_read_ == field) return; |
855 | FALL_THROUGH; |
856 | case kEndPosition: |
857 | end_position_ = helper_->ReadPosition(); // read end position. |
858 | if (++next_read_ == field) return; |
859 | FALL_THROUGH; |
860 | case kAsyncMarker: |
861 | async_marker_ = static_cast<AsyncMarker>(helper_->ReadByte()); |
862 | if (++next_read_ == field) return; |
863 | FALL_THROUGH; |
864 | case kDartAsyncMarker: |
865 | dart_async_marker_ = static_cast<AsyncMarker>( |
866 | helper_->ReadByte()); // read dart async marker. |
867 | if (++next_read_ == field) return; |
868 | FALL_THROUGH; |
869 | case kTypeParameters: |
870 | helper_->SkipTypeParametersList(); // read type parameters. |
871 | if (++next_read_ == field) return; |
872 | FALL_THROUGH; |
873 | case kTotalParameterCount: |
874 | total_parameter_count_ = |
875 | helper_->ReadUInt(); // read total parameter count. |
876 | if (++next_read_ == field) return; |
877 | FALL_THROUGH; |
878 | case kRequiredParameterCount: |
879 | required_parameter_count_ = |
880 | helper_->ReadUInt(); // read required parameter count. |
881 | if (++next_read_ == field) return; |
882 | FALL_THROUGH; |
883 | case kPositionalParameters: |
884 | helper_->SkipListOfVariableDeclarations(); // read positionals. |
885 | if (++next_read_ == field) return; |
886 | FALL_THROUGH; |
887 | case kNamedParameters: |
888 | helper_->SkipListOfVariableDeclarations(); // read named. |
889 | if (++next_read_ == field) return; |
890 | FALL_THROUGH; |
891 | case kReturnType: |
892 | helper_->SkipDartType(); // read return type. |
893 | if (++next_read_ == field) return; |
894 | FALL_THROUGH; |
895 | case kBody: |
896 | if (helper_->ReadTag() == kSomething) |
897 | helper_->SkipStatement(); // read body. |
898 | if (++next_read_ == field) return; |
899 | FALL_THROUGH; |
900 | case kEnd: |
901 | return; |
902 | } |
903 | } |
904 | |
905 | void TypeParameterHelper::ReadUntilExcluding(Field field) { |
906 | for (; next_read_ < field; ++next_read_) { |
907 | switch (next_read_) { |
908 | case kFlags: |
909 | flags_ = helper_->ReadFlags(); |
910 | break; |
911 | case kAnnotations: |
912 | helper_->SkipListOfExpressions(); // read annotations. |
913 | break; |
914 | case kVariance: |
915 | helper_->ReadVariance(); |
916 | break; |
917 | case kName: |
918 | name_index_ = helper_->ReadStringReference(); // read name index. |
919 | break; |
920 | case kBound: |
921 | helper_->SkipDartType(); |
922 | break; |
923 | case kDefaultType: |
924 | if (helper_->ReadTag() == kSomething) { |
925 | helper_->SkipDartType(); |
926 | } |
927 | break; |
928 | case kEnd: |
929 | return; |
930 | } |
931 | } |
932 | } |
933 | |
934 | void VariableDeclarationHelper::ReadUntilExcluding(Field field) { |
935 | if (field <= next_read_) return; |
936 | |
937 | // Ordered with fall-through. |
938 | switch (next_read_) { |
939 | case kPosition: |
940 | position_ = helper_->ReadPosition(); // read position. |
941 | if (++next_read_ == field) return; |
942 | FALL_THROUGH; |
943 | case kEqualPosition: |
944 | equals_position_ = helper_->ReadPosition(); // read equals position. |
945 | if (++next_read_ == field) return; |
946 | FALL_THROUGH; |
947 | case kAnnotations: |
948 | annotation_count_ = helper_->ReadListLength(); // read list length. |
949 | for (intptr_t i = 0; i < annotation_count_; ++i) { |
950 | helper_->SkipExpression(); // read ith expression. |
951 | } |
952 | if (++next_read_ == field) return; |
953 | FALL_THROUGH; |
954 | case kFlags: |
955 | flags_ = helper_->ReadFlags(); |
956 | if (++next_read_ == field) return; |
957 | FALL_THROUGH; |
958 | case kNameIndex: |
959 | name_index_ = helper_->ReadStringReference(); // read name index. |
960 | if (++next_read_ == field) return; |
961 | FALL_THROUGH; |
962 | case kType: |
963 | helper_->SkipDartType(); // read type. |
964 | if (++next_read_ == field) return; |
965 | FALL_THROUGH; |
966 | case kInitializer: |
967 | if (helper_->ReadTag() == kSomething) |
968 | helper_->SkipExpression(); // read initializer. |
969 | if (++next_read_ == field) return; |
970 | FALL_THROUGH; |
971 | case kEnd: |
972 | return; |
973 | } |
974 | } |
975 | |
976 | FieldHelper::FieldHelper(KernelReaderHelper* helper, intptr_t offset) |
977 | : helper_(helper), next_read_(kStart) { |
978 | helper_->SetOffset(offset); |
979 | } |
980 | |
981 | void FieldHelper::ReadUntilExcluding(Field field) { |
982 | if (field <= next_read_) return; |
983 | |
984 | // Ordered with fall-through. |
985 | switch (next_read_) { |
986 | case kStart: { |
987 | Tag tag = helper_->ReadTag(); // read tag. |
988 | ASSERT(tag == kField); |
989 | if (++next_read_ == field) return; |
990 | } |
991 | FALL_THROUGH; |
992 | case kCanonicalName: |
993 | canonical_name_ = |
994 | helper_->ReadCanonicalNameReference(); // read canonical_name. |
995 | if (++next_read_ == field) return; |
996 | FALL_THROUGH; |
997 | case kSourceUriIndex: |
998 | source_uri_index_ = helper_->ReadUInt(); // read source_uri_index. |
999 | helper_->set_current_script_id(source_uri_index_); |
1000 | if (++next_read_ == field) return; |
1001 | FALL_THROUGH; |
1002 | case kPosition: |
1003 | position_ = helper_->ReadPosition(); // read position. |
1004 | if (++next_read_ == field) return; |
1005 | FALL_THROUGH; |
1006 | case kEndPosition: |
1007 | end_position_ = helper_->ReadPosition(); // read end position. |
1008 | if (++next_read_ == field) return; |
1009 | FALL_THROUGH; |
1010 | case kFlags: |
1011 | flags_ = helper_->ReadUInt(); |
1012 | if (++next_read_ == field) return; |
1013 | FALL_THROUGH; |
1014 | case kName: |
1015 | helper_->SkipName(); // read name. |
1016 | if (++next_read_ == field) return; |
1017 | FALL_THROUGH; |
1018 | case kAnnotations: { |
1019 | annotation_count_ = helper_->ReadListLength(); // read list length. |
1020 | for (intptr_t i = 0; i < annotation_count_; ++i) { |
1021 | helper_->SkipExpression(); // read ith expression. |
1022 | } |
1023 | if (++next_read_ == field) return; |
1024 | } |
1025 | FALL_THROUGH; |
1026 | case kType: |
1027 | helper_->SkipDartType(); // read type. |
1028 | if (++next_read_ == field) return; |
1029 | FALL_THROUGH; |
1030 | case kInitializer: |
1031 | if (helper_->ReadTag() == kSomething) { |
1032 | helper_->SkipExpression(); // read initializer. |
1033 | } |
1034 | if (++next_read_ == field) return; |
1035 | FALL_THROUGH; |
1036 | case kEnd: |
1037 | return; |
1038 | } |
1039 | } |
1040 | |
1041 | void ProcedureHelper::ReadUntilExcluding(Field field) { |
1042 | if (field <= next_read_) return; |
1043 | |
1044 | // Ordered with fall-through. |
1045 | switch (next_read_) { |
1046 | case kStart: { |
1047 | Tag tag = helper_->ReadTag(); // read tag. |
1048 | ASSERT(tag == kProcedure); |
1049 | if (++next_read_ == field) return; |
1050 | } |
1051 | FALL_THROUGH; |
1052 | case kCanonicalName: |
1053 | canonical_name_ = |
1054 | helper_->ReadCanonicalNameReference(); // read canonical_name. |
1055 | if (++next_read_ == field) return; |
1056 | FALL_THROUGH; |
1057 | case kSourceUriIndex: |
1058 | source_uri_index_ = helper_->ReadUInt(); // read source_uri_index. |
1059 | helper_->set_current_script_id(source_uri_index_); |
1060 | if (++next_read_ == field) return; |
1061 | FALL_THROUGH; |
1062 | case kStartPosition: |
1063 | start_position_ = helper_->ReadPosition(); // read position. |
1064 | if (++next_read_ == field) return; |
1065 | FALL_THROUGH; |
1066 | case kPosition: |
1067 | position_ = helper_->ReadPosition(); // read position. |
1068 | if (++next_read_ == field) return; |
1069 | FALL_THROUGH; |
1070 | case kEndPosition: |
1071 | end_position_ = helper_->ReadPosition(); // read end position. |
1072 | if (++next_read_ == field) return; |
1073 | FALL_THROUGH; |
1074 | case kKind: |
1075 | kind_ = static_cast<Kind>(helper_->ReadByte()); |
1076 | if (++next_read_ == field) return; |
1077 | FALL_THROUGH; |
1078 | case kFlags: |
1079 | flags_ = helper_->ReadUInt(); |
1080 | if (++next_read_ == field) return; |
1081 | FALL_THROUGH; |
1082 | case kName: |
1083 | helper_->SkipName(); // read name. |
1084 | if (++next_read_ == field) return; |
1085 | FALL_THROUGH; |
1086 | case kAnnotations: { |
1087 | annotation_count_ = helper_->ReadListLength(); // read list length. |
1088 | for (intptr_t i = 0; i < annotation_count_; ++i) { |
1089 | helper_->SkipExpression(); // read ith expression. |
1090 | } |
1091 | if (++next_read_ == field) return; |
1092 | } |
1093 | FALL_THROUGH; |
1094 | case kForwardingStubSuperTarget: |
1095 | forwarding_stub_super_target_ = helper_->ReadCanonicalNameReference(); |
1096 | if (++next_read_ == field) return; |
1097 | FALL_THROUGH; |
1098 | case kForwardingStubInterfaceTarget: |
1099 | helper_->ReadCanonicalNameReference(); |
1100 | if (++next_read_ == field) return; |
1101 | FALL_THROUGH; |
1102 | case kMemberSignatureTarget: |
1103 | helper_->ReadCanonicalNameReference(); |
1104 | if (++next_read_ == field) return; |
1105 | FALL_THROUGH; |
1106 | case kFunction: |
1107 | if (helper_->ReadTag() == kSomething) { |
1108 | helper_->SkipFunctionNode(); // read function node. |
1109 | } |
1110 | if (++next_read_ == field) return; |
1111 | FALL_THROUGH; |
1112 | case kEnd: |
1113 | return; |
1114 | } |
1115 | } |
1116 | |
1117 | void ConstructorHelper::ReadUntilExcluding(Field field) { |
1118 | if (field <= next_read_) return; |
1119 | |
1120 | // Ordered with fall-through. |
1121 | switch (next_read_) { |
1122 | case kStart: { |
1123 | Tag tag = helper_->ReadTag(); // read tag. |
1124 | ASSERT(tag == kConstructor); |
1125 | if (++next_read_ == field) return; |
1126 | } |
1127 | FALL_THROUGH; |
1128 | case kCanonicalName: |
1129 | canonical_name_ = |
1130 | helper_->ReadCanonicalNameReference(); // read canonical_name. |
1131 | if (++next_read_ == field) return; |
1132 | FALL_THROUGH; |
1133 | case kSourceUriIndex: |
1134 | source_uri_index_ = helper_->ReadUInt(); // read source_uri_index. |
1135 | helper_->set_current_script_id(source_uri_index_); |
1136 | if (++next_read_ == field) return; |
1137 | FALL_THROUGH; |
1138 | case kStartPosition: |
1139 | start_position_ = helper_->ReadPosition(); // read position. |
1140 | if (++next_read_ == field) return; |
1141 | FALL_THROUGH; |
1142 | case kPosition: |
1143 | position_ = helper_->ReadPosition(); // read position. |
1144 | if (++next_read_ == field) return; |
1145 | FALL_THROUGH; |
1146 | case kEndPosition: |
1147 | end_position_ = helper_->ReadPosition(); // read end position. |
1148 | if (++next_read_ == field) return; |
1149 | FALL_THROUGH; |
1150 | case kFlags: |
1151 | flags_ = helper_->ReadFlags(); |
1152 | if (++next_read_ == field) return; |
1153 | FALL_THROUGH; |
1154 | case kName: |
1155 | helper_->SkipName(); // read name. |
1156 | if (++next_read_ == field) return; |
1157 | FALL_THROUGH; |
1158 | case kAnnotations: { |
1159 | annotation_count_ = helper_->ReadListLength(); // read list length. |
1160 | for (intptr_t i = 0; i < annotation_count_; ++i) { |
1161 | helper_->SkipExpression(); // read ith expression. |
1162 | } |
1163 | if (++next_read_ == field) return; |
1164 | } |
1165 | FALL_THROUGH; |
1166 | case kFunction: |
1167 | helper_->SkipFunctionNode(); // read function. |
1168 | if (++next_read_ == field) return; |
1169 | FALL_THROUGH; |
1170 | case kInitializers: { |
1171 | intptr_t list_length = |
1172 | helper_->ReadListLength(); // read initializers list length. |
1173 | for (intptr_t i = 0; i < list_length; i++) { |
1174 | helper_->SkipInitializer(); |
1175 | } |
1176 | if (++next_read_ == field) return; |
1177 | } |
1178 | FALL_THROUGH; |
1179 | case kEnd: |
1180 | return; |
1181 | } |
1182 | } |
1183 | |
1184 | void ClassHelper::ReadUntilExcluding(Field field) { |
1185 | if (field <= next_read_) return; |
1186 | |
1187 | // Ordered with fall-through. |
1188 | switch (next_read_) { |
1189 | case kStart: { |
1190 | Tag tag = helper_->ReadTag(); // read tag. |
1191 | ASSERT(tag == kClass); |
1192 | if (++next_read_ == field) return; |
1193 | } |
1194 | FALL_THROUGH; |
1195 | case kCanonicalName: |
1196 | canonical_name_ = |
1197 | helper_->ReadCanonicalNameReference(); // read canonical_name. |
1198 | if (++next_read_ == field) return; |
1199 | FALL_THROUGH; |
1200 | case kSourceUriIndex: |
1201 | source_uri_index_ = helper_->ReadUInt(); // read source_uri_index. |
1202 | helper_->set_current_script_id(source_uri_index_); |
1203 | if (++next_read_ == field) return; |
1204 | FALL_THROUGH; |
1205 | case kStartPosition: |
1206 | start_position_ = helper_->ReadPosition(); // read position. |
1207 | if (++next_read_ == field) return; |
1208 | FALL_THROUGH; |
1209 | case kPosition: |
1210 | position_ = helper_->ReadPosition(); // read position. |
1211 | if (++next_read_ == field) return; |
1212 | FALL_THROUGH; |
1213 | case kEndPosition: |
1214 | end_position_ = helper_->ReadPosition(); // read end position. |
1215 | if (++next_read_ == field) return; |
1216 | FALL_THROUGH; |
1217 | case kFlags: |
1218 | flags_ = helper_->ReadFlags(); // read flags. |
1219 | if (++next_read_ == field) return; |
1220 | FALL_THROUGH; |
1221 | case kNameIndex: |
1222 | name_index_ = helper_->ReadStringReference(); // read name index. |
1223 | if (++next_read_ == field) return; |
1224 | FALL_THROUGH; |
1225 | case kAnnotations: { |
1226 | annotation_count_ = helper_->ReadListLength(); // read list length. |
1227 | for (intptr_t i = 0; i < annotation_count_; ++i) { |
1228 | helper_->SkipExpression(); // read ith expression. |
1229 | } |
1230 | if (++next_read_ == field) return; |
1231 | } |
1232 | FALL_THROUGH; |
1233 | case kTypeParameters: |
1234 | helper_->SkipTypeParametersList(); // read type parameters. |
1235 | if (++next_read_ == field) return; |
1236 | FALL_THROUGH; |
1237 | case kSuperClass: { |
1238 | Tag type_tag = helper_->ReadTag(); // read super class type (part 1). |
1239 | if (type_tag == kSomething) { |
1240 | helper_->SkipDartType(); // read super class type (part 2). |
1241 | } |
1242 | if (++next_read_ == field) return; |
1243 | } |
1244 | FALL_THROUGH; |
1245 | case kMixinType: { |
1246 | Tag type_tag = helper_->ReadTag(); // read mixin type (part 1). |
1247 | if (type_tag == kSomething) { |
1248 | helper_->SkipDartType(); // read mixin type (part 2). |
1249 | } |
1250 | if (++next_read_ == field) return; |
1251 | } |
1252 | FALL_THROUGH; |
1253 | case kImplementedClasses: |
1254 | helper_->SkipListOfDartTypes(); // read implemented_classes. |
1255 | if (++next_read_ == field) return; |
1256 | FALL_THROUGH; |
1257 | case kFields: { |
1258 | intptr_t list_length = |
1259 | helper_->ReadListLength(); // read fields list length. |
1260 | for (intptr_t i = 0; i < list_length; i++) { |
1261 | FieldHelper field_helper(helper_); |
1262 | field_helper.ReadUntilExcluding(FieldHelper::kEnd); // read field. |
1263 | } |
1264 | if (++next_read_ == field) return; |
1265 | } |
1266 | FALL_THROUGH; |
1267 | case kConstructors: { |
1268 | intptr_t list_length = |
1269 | helper_->ReadListLength(); // read constructors list length. |
1270 | for (intptr_t i = 0; i < list_length; i++) { |
1271 | ConstructorHelper constructor_helper(helper_); |
1272 | constructor_helper.ReadUntilExcluding( |
1273 | ConstructorHelper::kEnd); // read constructor. |
1274 | } |
1275 | if (++next_read_ == field) return; |
1276 | } |
1277 | FALL_THROUGH; |
1278 | case kProcedures: { |
1279 | procedure_count_ = helper_->ReadListLength(); // read procedures #. |
1280 | for (intptr_t i = 0; i < procedure_count_; i++) { |
1281 | ProcedureHelper procedure_helper(helper_); |
1282 | procedure_helper.ReadUntilExcluding( |
1283 | ProcedureHelper::kEnd); // read procedure. |
1284 | } |
1285 | if (++next_read_ == field) return; |
1286 | } |
1287 | FALL_THROUGH; |
1288 | case kClassIndex: |
1289 | // Read class index. |
1290 | for (intptr_t i = 0; i < procedure_count_; ++i) { |
1291 | helper_->reader_.ReadUInt32(); |
1292 | } |
1293 | helper_->reader_.ReadUInt32(); |
1294 | helper_->reader_.ReadUInt32(); |
1295 | if (++next_read_ == field) return; |
1296 | FALL_THROUGH; |
1297 | case kEnd: |
1298 | return; |
1299 | } |
1300 | } |
1301 | |
1302 | void LibraryHelper::ReadUntilExcluding(Field field) { |
1303 | if (field <= next_read_) return; |
1304 | |
1305 | // Ordered with fall-through. |
1306 | switch (next_read_) { |
1307 | // Note that this (up to canonical name) needs to be kept in sync with |
1308 | // "library_canonical_name" (currently in "kernel_loader.h"). |
1309 | case kFlags: { |
1310 | flags_ = helper_->ReadFlags(); |
1311 | if (++next_read_ == field) return; |
1312 | FALL_THROUGH; |
1313 | } |
1314 | case kLanguageVersion: { |
1315 | helper_->ReadUInt(); // Read major language version. |
1316 | helper_->ReadUInt(); // Read minor language version. |
1317 | if (++next_read_ == field) return; |
1318 | FALL_THROUGH; |
1319 | } |
1320 | case kCanonicalName: |
1321 | canonical_name_ = |
1322 | helper_->ReadCanonicalNameReference(); // read canonical_name. |
1323 | if (++next_read_ == field) return; |
1324 | FALL_THROUGH; |
1325 | case kName: |
1326 | name_index_ = helper_->ReadStringReference(); // read name index. |
1327 | if (++next_read_ == field) return; |
1328 | FALL_THROUGH; |
1329 | case kSourceUriIndex: |
1330 | source_uri_index_ = helper_->ReadUInt(); // read source_uri_index. |
1331 | helper_->set_current_script_id(source_uri_index_); |
1332 | if (++next_read_ == field) return; |
1333 | FALL_THROUGH; |
1334 | case kProblemsAsJson: { |
1335 | intptr_t length = helper_->ReadUInt(); // read length of table. |
1336 | for (intptr_t i = 0; i < length; ++i) { |
1337 | helper_->SkipBytes(helper_->ReadUInt()); // read strings. |
1338 | } |
1339 | if (++next_read_ == field) return; |
1340 | } |
1341 | FALL_THROUGH; |
1342 | case kAnnotations: |
1343 | helper_->SkipListOfExpressions(); // read annotations. |
1344 | if (++next_read_ == field) return; |
1345 | FALL_THROUGH; |
1346 | case kDependencies: { |
1347 | intptr_t dependency_count = helper_->ReadUInt(); // read list length. |
1348 | for (intptr_t i = 0; i < dependency_count; ++i) { |
1349 | helper_->SkipLibraryDependency(); |
1350 | } |
1351 | if (++next_read_ == field) return; |
1352 | } |
1353 | return; |
1354 | } |
1355 | } |
1356 | |
1357 | void LibraryDependencyHelper::ReadUntilExcluding(Field field) { |
1358 | if (field <= next_read_) return; |
1359 | |
1360 | // Ordered with fall-through. |
1361 | switch (next_read_) { |
1362 | case kFileOffset: { |
1363 | helper_->ReadPosition(); |
1364 | if (++next_read_ == field) return; |
1365 | FALL_THROUGH; |
1366 | } |
1367 | case kFlags: { |
1368 | flags_ = helper_->ReadFlags(); |
1369 | if (++next_read_ == field) return; |
1370 | FALL_THROUGH; |
1371 | } |
1372 | case kAnnotations: { |
1373 | annotation_count_ = helper_->ReadListLength(); |
1374 | for (intptr_t i = 0; i < annotation_count_; ++i) { |
1375 | helper_->SkipExpression(); // read ith expression. |
1376 | } |
1377 | if (++next_read_ == field) return; |
1378 | } |
1379 | FALL_THROUGH; |
1380 | case kTargetLibrary: { |
1381 | target_library_canonical_name_ = helper_->ReadCanonicalNameReference(); |
1382 | if (++next_read_ == field) return; |
1383 | } |
1384 | FALL_THROUGH; |
1385 | case kName: { |
1386 | name_index_ = helper_->ReadStringReference(); |
1387 | if (++next_read_ == field) return; |
1388 | } |
1389 | FALL_THROUGH; |
1390 | case kCombinators: { |
1391 | intptr_t count = helper_->ReadListLength(); |
1392 | for (intptr_t i = 0; i < count; ++i) { |
1393 | // Skip flags |
1394 | helper_->SkipBytes(1); |
1395 | // Skip list of names. |
1396 | helper_->SkipListOfStrings(); |
1397 | } |
1398 | if (++next_read_ == field) return; |
1399 | } |
1400 | FALL_THROUGH; |
1401 | case kEnd: |
1402 | return; |
1403 | } |
1404 | } |
1405 | |
1406 | #if defined(DEBUG) |
1407 | |
1408 | void MetadataHelper::VerifyMetadataMappings( |
1409 | const ExternalTypedData& metadata_mappings) { |
1410 | const intptr_t kUInt32Size = 4; |
1411 | Reader reader(metadata_mappings); |
1412 | if (reader.size() == 0) { |
1413 | return; |
1414 | } |
1415 | |
1416 | // Scan through metadata mappings in reverse direction. |
1417 | |
1418 | // Read metadataMappings length. |
1419 | intptr_t offset = reader.size() - kUInt32Size; |
1420 | const intptr_t metadata_num = reader.ReadUInt32At(offset); |
1421 | |
1422 | if (metadata_num == 0) { |
1423 | ASSERT(metadata_mappings.LengthInBytes() == kUInt32Size); |
1424 | return; |
1425 | } |
1426 | |
1427 | // Read metadataMappings elements. |
1428 | for (intptr_t i = 0; i < metadata_num; ++i) { |
1429 | // Read nodeOffsetToMetadataOffset length. |
1430 | offset -= kUInt32Size; |
1431 | const intptr_t mappings_num = reader.ReadUInt32At(offset); |
1432 | |
1433 | // Skip nodeOffsetToMetadataOffset. |
1434 | offset -= mappings_num * 2 * kUInt32Size; |
1435 | |
1436 | // Verify that node offsets are sorted. |
1437 | intptr_t prev_node_offset = -1; |
1438 | reader.set_offset(offset); |
1439 | for (intptr_t j = 0; j < mappings_num; ++j) { |
1440 | const intptr_t node_offset = reader.ReadUInt32(); |
1441 | const intptr_t md_offset = reader.ReadUInt32(); |
1442 | |
1443 | ASSERT(node_offset >= 0 && md_offset >= 0); |
1444 | ASSERT(node_offset > prev_node_offset); |
1445 | prev_node_offset = node_offset; |
1446 | } |
1447 | |
1448 | // Skip tag. |
1449 | offset -= kUInt32Size; |
1450 | } |
1451 | } |
1452 | |
1453 | #endif // defined(DEBUG) |
1454 | |
1455 | MetadataHelper::MetadataHelper(KernelReaderHelper* helper, |
1456 | const char* tag, |
1457 | bool precompiler_only) |
1458 | : helper_(helper), |
1459 | translation_helper_(helper->translation_helper_), |
1460 | tag_(tag), |
1461 | mappings_scanned_(false), |
1462 | precompiler_only_(precompiler_only), |
1463 | mappings_offset_(0), |
1464 | mappings_num_(0), |
1465 | last_node_offset_(0), |
1466 | last_mapping_index_(0) {} |
1467 | |
1468 | void MetadataHelper::SetMetadataMappings(intptr_t mappings_offset, |
1469 | intptr_t mappings_num) { |
1470 | ASSERT((mappings_offset_ == 0) && (mappings_num_ == 0)); |
1471 | ASSERT((mappings_offset != 0) && (mappings_num != 0)); |
1472 | mappings_offset_ = mappings_offset; |
1473 | mappings_num_ = mappings_num; |
1474 | last_node_offset_ = kIntptrMax; |
1475 | last_mapping_index_ = 0; |
1476 | } |
1477 | |
1478 | void MetadataHelper::ScanMetadataMappings() { |
1479 | const intptr_t kUInt32Size = 4; |
1480 | Reader reader(H.metadata_mappings()); |
1481 | if (reader.size() == 0) { |
1482 | return; |
1483 | } |
1484 | |
1485 | // Scan through metadata mappings in reverse direction. |
1486 | |
1487 | // Read metadataMappings length. |
1488 | intptr_t offset = reader.size() - kUInt32Size; |
1489 | uint32_t metadata_num = reader.ReadUInt32At(offset); |
1490 | |
1491 | if (metadata_num == 0) { |
1492 | ASSERT(H.metadata_mappings().LengthInBytes() == kUInt32Size); |
1493 | return; |
1494 | } |
1495 | |
1496 | // Read metadataMappings elements. |
1497 | for (uint32_t i = 0; i < metadata_num; ++i) { |
1498 | // Read nodeOffsetToMetadataOffset length. |
1499 | offset -= kUInt32Size; |
1500 | uint32_t mappings_num = reader.ReadUInt32At(offset); |
1501 | |
1502 | // Skip nodeOffsetToMetadataOffset and read tag. |
1503 | offset -= mappings_num * 2 * kUInt32Size + kUInt32Size; |
1504 | StringIndex tag = StringIndex(reader.ReadUInt32At(offset)); |
1505 | |
1506 | if (mappings_num == 0) { |
1507 | continue; |
1508 | } |
1509 | |
1510 | if (H.StringEquals(tag, tag_)) { |
1511 | if ((!FLAG_precompiled_mode) && precompiler_only_) { |
1512 | FATAL1("%s metadata is allowed in precompiled mode only" , tag_); |
1513 | } |
1514 | SetMetadataMappings(offset + kUInt32Size, mappings_num); |
1515 | return; |
1516 | } |
1517 | } |
1518 | } |
1519 | |
1520 | intptr_t MetadataHelper::FindMetadataMapping(intptr_t node_offset) { |
1521 | const intptr_t kUInt32Size = 4; |
1522 | ASSERT(mappings_num_ > 0); |
1523 | |
1524 | Reader reader(H.metadata_mappings()); |
1525 | |
1526 | intptr_t left = 0; |
1527 | intptr_t right = mappings_num_ - 1; |
1528 | while (left < right) { |
1529 | intptr_t mid = ((right - left) / 2) + left; |
1530 | intptr_t mid_node_offset = |
1531 | reader.ReadUInt32At(mappings_offset_ + mid * 2 * kUInt32Size); |
1532 | |
1533 | if (node_offset < mid_node_offset) { |
1534 | right = mid - 1; |
1535 | } else if (node_offset > mid_node_offset) { |
1536 | left = mid + 1; |
1537 | } else { |
1538 | return mid; // Exact match found. |
1539 | } |
1540 | } |
1541 | ASSERT((0 <= left) && (left <= mappings_num_)); |
1542 | |
1543 | // Approximate match is found. Make sure it has an offset greater or equal |
1544 | // to the given node offset. |
1545 | if (left < mappings_num_) { |
1546 | intptr_t found_node_offset = |
1547 | reader.ReadUInt32At(mappings_offset_ + left * 2 * kUInt32Size); |
1548 | |
1549 | if (found_node_offset < node_offset) { |
1550 | ++left; |
1551 | } |
1552 | } |
1553 | ASSERT((left == mappings_num_) || |
1554 | static_cast<intptr_t>(reader.ReadUInt32At( |
1555 | mappings_offset_ + left * 2 * kUInt32Size)) >= node_offset); |
1556 | |
1557 | return left; |
1558 | } |
1559 | |
1560 | intptr_t MetadataHelper::GetNextMetadataPayloadOffset(intptr_t node_offset) { |
1561 | if (!mappings_scanned_) { |
1562 | ScanMetadataMappings(); |
1563 | mappings_scanned_ = true; |
1564 | } |
1565 | |
1566 | if (mappings_num_ == 0) { |
1567 | return -1; // No metadata. |
1568 | } |
1569 | |
1570 | node_offset += helper_->data_program_offset_; |
1571 | |
1572 | // Nodes are parsed in linear order most of the time, so do the search |
1573 | // only if looking back. |
1574 | if (node_offset < last_node_offset_) { |
1575 | last_mapping_index_ = FindMetadataMapping(node_offset); |
1576 | } |
1577 | |
1578 | intptr_t index = last_mapping_index_; |
1579 | intptr_t mapping_node_offset = 0; |
1580 | intptr_t mapping_md_offset = -1; |
1581 | |
1582 | Reader reader(H.metadata_mappings()); |
1583 | const intptr_t kUInt32Size = 4; |
1584 | reader.set_offset(mappings_offset_ + index * 2 * kUInt32Size); |
1585 | |
1586 | for (; index < mappings_num_; ++index) { |
1587 | mapping_node_offset = reader.ReadUInt32(); |
1588 | mapping_md_offset = reader.ReadUInt32(); |
1589 | |
1590 | if (mapping_node_offset >= node_offset) { |
1591 | break; |
1592 | } |
1593 | } |
1594 | |
1595 | last_mapping_index_ = index; |
1596 | last_node_offset_ = node_offset; |
1597 | |
1598 | if ((index < mappings_num_) && (mapping_node_offset == node_offset)) { |
1599 | ASSERT(mapping_md_offset >= 0); |
1600 | return mapping_md_offset; |
1601 | } else { |
1602 | return -1; |
1603 | } |
1604 | } |
1605 | |
1606 | intptr_t MetadataHelper::GetComponentMetadataPayloadOffset() { |
1607 | const intptr_t kComponentNodeOffset = 0; |
1608 | return GetNextMetadataPayloadOffset(kComponentNodeOffset - |
1609 | helper_->data_program_offset_); |
1610 | } |
1611 | |
1612 | DirectCallMetadataHelper::DirectCallMetadataHelper(KernelReaderHelper* helper) |
1613 | : MetadataHelper(helper, tag(), /* precompiler_only = */ true) {} |
1614 | |
1615 | bool DirectCallMetadataHelper::ReadMetadata(intptr_t node_offset, |
1616 | NameIndex* target_name, |
1617 | bool* check_receiver_for_null) { |
1618 | intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset); |
1619 | if (md_offset < 0) { |
1620 | return false; |
1621 | } |
1622 | |
1623 | AlternativeReadingScopeWithNewData alt(&helper_->reader_, |
1624 | &H.metadata_payloads(), md_offset); |
1625 | |
1626 | *target_name = helper_->ReadCanonicalNameReference(); |
1627 | *check_receiver_for_null = helper_->ReadBool(); |
1628 | return true; |
1629 | } |
1630 | |
1631 | DirectCallMetadata DirectCallMetadataHelper::GetDirectTargetForPropertyGet( |
1632 | intptr_t node_offset) { |
1633 | NameIndex kernel_name; |
1634 | bool check_receiver_for_null = false; |
1635 | if (!ReadMetadata(node_offset, &kernel_name, &check_receiver_for_null)) { |
1636 | return DirectCallMetadata(Function::null_function(), false); |
1637 | } |
1638 | |
1639 | if (H.IsProcedure(kernel_name) && !H.IsGetter(kernel_name)) { |
1640 | // Tear-off. Use method extractor as direct call target. |
1641 | const String& method_name = H.DartMethodName(kernel_name); |
1642 | const Function& target_method = Function::ZoneHandle( |
1643 | helper_->zone_, H.LookupMethodByMember(kernel_name, method_name)); |
1644 | const String& getter_name = H.DartGetterName(kernel_name); |
1645 | return DirectCallMetadata( |
1646 | Function::ZoneHandle(helper_->zone_, |
1647 | target_method.GetMethodExtractor(getter_name)), |
1648 | check_receiver_for_null); |
1649 | } else { |
1650 | const String& getter_name = H.DartGetterName(kernel_name); |
1651 | const Function& target = Function::ZoneHandle( |
1652 | helper_->zone_, H.LookupMethodByMember(kernel_name, getter_name)); |
1653 | ASSERT(target.IsGetterFunction() || target.IsImplicitGetterFunction()); |
1654 | return DirectCallMetadata(target, check_receiver_for_null); |
1655 | } |
1656 | } |
1657 | |
1658 | DirectCallMetadata DirectCallMetadataHelper::GetDirectTargetForPropertySet( |
1659 | intptr_t node_offset) { |
1660 | NameIndex kernel_name; |
1661 | bool check_receiver_for_null = false; |
1662 | if (!ReadMetadata(node_offset, &kernel_name, &check_receiver_for_null)) { |
1663 | return DirectCallMetadata(Function::null_function(), false); |
1664 | } |
1665 | |
1666 | const String& method_name = H.DartSetterName(kernel_name); |
1667 | const Function& target = Function::ZoneHandle( |
1668 | helper_->zone_, H.LookupMethodByMember(kernel_name, method_name)); |
1669 | ASSERT(target.IsSetterFunction() || target.IsImplicitSetterFunction()); |
1670 | |
1671 | return DirectCallMetadata(target, check_receiver_for_null); |
1672 | } |
1673 | |
1674 | DirectCallMetadata DirectCallMetadataHelper::GetDirectTargetForMethodInvocation( |
1675 | intptr_t node_offset) { |
1676 | NameIndex kernel_name; |
1677 | bool check_receiver_for_null = false; |
1678 | if (!ReadMetadata(node_offset, &kernel_name, &check_receiver_for_null)) { |
1679 | return DirectCallMetadata(Function::null_function(), false); |
1680 | } |
1681 | |
1682 | const String& method_name = H.DartProcedureName(kernel_name); |
1683 | const Function& target = Function::ZoneHandle( |
1684 | helper_->zone_, H.LookupMethodByMember(kernel_name, method_name)); |
1685 | |
1686 | return DirectCallMetadata(target, check_receiver_for_null); |
1687 | } |
1688 | |
1689 | InferredTypeMetadataHelper::InferredTypeMetadataHelper( |
1690 | KernelReaderHelper* helper, |
1691 | ConstantReader* constant_reader) |
1692 | : MetadataHelper(helper, tag(), /* precompiler_only = */ true), |
1693 | constant_reader_(constant_reader) {} |
1694 | |
1695 | InferredTypeMetadata InferredTypeMetadataHelper::GetInferredType( |
1696 | intptr_t node_offset, |
1697 | bool read_constant) { |
1698 | const intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset); |
1699 | if (md_offset < 0) { |
1700 | return InferredTypeMetadata(kDynamicCid, |
1701 | InferredTypeMetadata::kFlagNullable); |
1702 | } |
1703 | |
1704 | AlternativeReadingScopeWithNewData alt(&helper_->reader_, |
1705 | &H.metadata_payloads(), md_offset); |
1706 | |
1707 | const NameIndex kernel_name = helper_->ReadCanonicalNameReference(); |
1708 | const uint8_t flags = helper_->ReadByte(); |
1709 | |
1710 | const Object* constant_value = &Object::null_object(); |
1711 | if ((flags & InferredTypeMetadata::kFlagConstant) != 0) { |
1712 | const intptr_t constant_offset = helper_->ReadUInt(); |
1713 | if (read_constant) { |
1714 | constant_value = &Object::ZoneHandle( |
1715 | H.zone(), constant_reader_->ReadConstant(constant_offset)); |
1716 | } |
1717 | } |
1718 | |
1719 | if (H.IsRoot(kernel_name)) { |
1720 | ASSERT((flags & InferredTypeMetadata::kFlagConstant) == 0); |
1721 | return InferredTypeMetadata(kDynamicCid, flags); |
1722 | } |
1723 | |
1724 | const Class& klass = |
1725 | Class::Handle(helper_->zone_, H.LookupClassByKernelClass(kernel_name)); |
1726 | ASSERT(!klass.IsNull()); |
1727 | |
1728 | intptr_t cid = klass.id(); |
1729 | if (cid == kClosureCid) { |
1730 | // VM uses more specific function types and doesn't expect instances of |
1731 | // _Closure class, so inferred _Closure class doesn't make sense for the VM. |
1732 | cid = kDynamicCid; |
1733 | } |
1734 | |
1735 | return InferredTypeMetadata(cid, flags, *constant_value); |
1736 | } |
1737 | |
1738 | void ProcedureAttributesMetadata::InitializeFromFlags(uint8_t flags) { |
1739 | const int kMethodOrSetterCalledDynamicallyBit = 1 << 0; |
1740 | const int kNonThisUsesBit = 1 << 1; |
1741 | const int kTearOffUsesBit = 1 << 2; |
1742 | const int kThisUsesBit = 1 << 3; |
1743 | const int kGetterCalledDynamicallyBit = 1 << 4; |
1744 | |
1745 | method_or_setter_called_dynamically = |
1746 | (flags & kMethodOrSetterCalledDynamicallyBit) != 0; |
1747 | getter_called_dynamically = (flags & kGetterCalledDynamicallyBit) != 0; |
1748 | has_this_uses = (flags & kThisUsesBit) != 0; |
1749 | has_non_this_uses = (flags & kNonThisUsesBit) != 0; |
1750 | has_tearoff_uses = (flags & kTearOffUsesBit) != 0; |
1751 | } |
1752 | |
1753 | ProcedureAttributesMetadataHelper::ProcedureAttributesMetadataHelper( |
1754 | KernelReaderHelper* helper) |
1755 | : MetadataHelper(helper, tag(), /* precompiler_only = */ true) {} |
1756 | |
1757 | bool ProcedureAttributesMetadataHelper::ReadMetadata( |
1758 | intptr_t node_offset, |
1759 | ProcedureAttributesMetadata* metadata) { |
1760 | intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset); |
1761 | if (md_offset < 0) { |
1762 | return false; |
1763 | } |
1764 | |
1765 | AlternativeReadingScopeWithNewData alt(&helper_->reader_, |
1766 | &H.metadata_payloads(), md_offset); |
1767 | |
1768 | const uint8_t flags = helper_->ReadByte(); |
1769 | metadata->InitializeFromFlags(flags); |
1770 | metadata->method_or_setter_selector_id = helper_->ReadUInt(); |
1771 | metadata->getter_selector_id = helper_->ReadUInt(); |
1772 | return true; |
1773 | } |
1774 | |
1775 | ProcedureAttributesMetadata |
1776 | ProcedureAttributesMetadataHelper::GetProcedureAttributes( |
1777 | intptr_t node_offset) { |
1778 | ProcedureAttributesMetadata metadata; |
1779 | ReadMetadata(node_offset, &metadata); |
1780 | return metadata; |
1781 | } |
1782 | |
1783 | ObfuscationProhibitionsMetadataHelper::ObfuscationProhibitionsMetadataHelper( |
1784 | KernelReaderHelper* helper) |
1785 | : MetadataHelper(helper, tag(), /* precompiler_only = */ true) {} |
1786 | |
1787 | void ObfuscationProhibitionsMetadataHelper::ReadMetadata(intptr_t node_offset) { |
1788 | intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset); |
1789 | if (md_offset < 0) { |
1790 | return; |
1791 | } |
1792 | |
1793 | AlternativeReadingScopeWithNewData alt(&helper_->reader_, |
1794 | &H.metadata_payloads(), md_offset); |
1795 | Obfuscator O(Thread::Current(), String::Handle()); |
1796 | |
1797 | intptr_t len = helper_->ReadUInt32(); |
1798 | for (int i = 0; i < len; ++i) { |
1799 | StringIndex name = helper_->ReadStringReference(); |
1800 | O.PreventRenaming(translation_helper_.DartSymbolPlain(name)); |
1801 | } |
1802 | return; |
1803 | } |
1804 | |
1805 | LoadingUnitsMetadataHelper::LoadingUnitsMetadataHelper( |
1806 | KernelReaderHelper* helper) |
1807 | : MetadataHelper(helper, tag(), /* precompiler_only = */ true) {} |
1808 | |
1809 | void LoadingUnitsMetadataHelper::ReadMetadata(intptr_t node_offset) { |
1810 | intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset); |
1811 | if (md_offset < 0) { |
1812 | return; |
1813 | } |
1814 | |
1815 | AlternativeReadingScopeWithNewData alt(&helper_->reader_, |
1816 | &H.metadata_payloads(), md_offset); |
1817 | |
1818 | Thread* T = Thread::Current(); |
1819 | Zone* Z = T->zone(); |
1820 | intptr_t unit_count = helper_->ReadUInt(); |
1821 | Array& loading_units = Array::Handle(Z, Array::New(unit_count + 1)); |
1822 | LoadingUnit& unit = LoadingUnit::Handle(Z); |
1823 | LoadingUnit& parent = LoadingUnit::Handle(Z); |
1824 | Library& lib = Library::Handle(Z); |
1825 | |
1826 | for (int i = 0; i < unit_count; i++) { |
1827 | intptr_t id = helper_->ReadUInt(); |
1828 | unit = LoadingUnit::New(); |
1829 | unit.set_id(id); |
1830 | |
1831 | intptr_t parent_id = helper_->ReadUInt(); |
1832 | RELEASE_ASSERT(parent_id < id); |
1833 | parent ^= loading_units.At(parent_id); |
1834 | RELEASE_ASSERT(parent.IsNull() == (parent_id == 0)); |
1835 | unit.set_parent(parent); |
1836 | |
1837 | intptr_t library_count = helper_->ReadUInt(); |
1838 | for (intptr_t j = 0; j < library_count; j++) { |
1839 | const String& uri = |
1840 | translation_helper_.DartSymbolPlain(helper_->ReadStringReference()); |
1841 | lib = Library::LookupLibrary(T, uri); |
1842 | if (lib.IsNull()) { |
1843 | FATAL1("Missing library: %s\n" , uri.ToCString()); |
1844 | } |
1845 | lib.set_loading_unit(unit); |
1846 | } |
1847 | |
1848 | loading_units.SetAt(id, unit); |
1849 | } |
1850 | |
1851 | ObjectStore* object_store = Isolate::Current()->object_store(); |
1852 | ASSERT(object_store->loading_units() == Array::null()); |
1853 | object_store->set_loading_units(loading_units); |
1854 | } |
1855 | |
1856 | CallSiteAttributesMetadataHelper::CallSiteAttributesMetadataHelper( |
1857 | KernelReaderHelper* helper, |
1858 | TypeTranslator* type_translator) |
1859 | : MetadataHelper(helper, tag(), /* precompiler_only = */ false), |
1860 | type_translator_(*type_translator) {} |
1861 | |
1862 | bool CallSiteAttributesMetadataHelper::ReadMetadata( |
1863 | intptr_t node_offset, |
1864 | CallSiteAttributesMetadata* metadata) { |
1865 | intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset); |
1866 | if (md_offset < 0) { |
1867 | return false; |
1868 | } |
1869 | |
1870 | AlternativeReadingScopeWithNewData alt(&helper_->reader_, |
1871 | &H.metadata_payloads(), md_offset); |
1872 | |
1873 | metadata->receiver_type = &type_translator_.BuildType(); |
1874 | return true; |
1875 | } |
1876 | |
1877 | CallSiteAttributesMetadata |
1878 | CallSiteAttributesMetadataHelper::GetCallSiteAttributes(intptr_t node_offset) { |
1879 | CallSiteAttributesMetadata metadata; |
1880 | ReadMetadata(node_offset, &metadata); |
1881 | return metadata; |
1882 | } |
1883 | |
1884 | TableSelectorMetadataHelper::TableSelectorMetadataHelper( |
1885 | KernelReaderHelper* helper) |
1886 | : MetadataHelper(helper, tag(), /* precompiler_only = */ true) {} |
1887 | |
1888 | TableSelectorMetadata* TableSelectorMetadataHelper::GetTableSelectorMetadata( |
1889 | Zone* zone) { |
1890 | const intptr_t node_offset = GetComponentMetadataPayloadOffset(); |
1891 | const intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset); |
1892 | if (md_offset < 0) { |
1893 | return nullptr; |
1894 | } |
1895 | |
1896 | AlternativeReadingScopeWithNewData alt(&helper_->reader_, |
1897 | &H.metadata_payloads(), md_offset); |
1898 | |
1899 | const intptr_t num_selectors = helper_->ReadUInt(); |
1900 | TableSelectorMetadata* metadata = |
1901 | new (zone) TableSelectorMetadata(num_selectors); |
1902 | for (intptr_t i = 0; i < num_selectors; i++) { |
1903 | ReadTableSelectorInfo(&metadata->selectors[i]); |
1904 | } |
1905 | return metadata; |
1906 | } |
1907 | |
1908 | void TableSelectorMetadataHelper::ReadTableSelectorInfo( |
1909 | TableSelectorInfo* info) { |
1910 | info->call_count = helper_->ReadUInt(); |
1911 | uint8_t flags = helper_->ReadByte(); |
1912 | info->called_on_null = (flags & kCalledOnNullBit) != 0; |
1913 | info->torn_off = (flags & kTornOffBit) != 0; |
1914 | } |
1915 | |
1916 | UnboxingInfoMetadataHelper::UnboxingInfoMetadataHelper( |
1917 | KernelReaderHelper* helper) |
1918 | : MetadataHelper(helper, tag(), /* precompiler_only = */ true) {} |
1919 | |
1920 | UnboxingInfoMetadata* UnboxingInfoMetadataHelper::GetUnboxingInfoMetadata( |
1921 | intptr_t node_offset) { |
1922 | const intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset); |
1923 | |
1924 | if (md_offset < 0) { |
1925 | return nullptr; |
1926 | } |
1927 | |
1928 | AlternativeReadingScopeWithNewData alt(&helper_->reader_, |
1929 | &H.metadata_payloads(), md_offset); |
1930 | |
1931 | const intptr_t num_args = helper_->ReadUInt(); |
1932 | const auto info = new (helper_->zone_) UnboxingInfoMetadata(); |
1933 | info->SetArgsCount(num_args); |
1934 | for (intptr_t i = 0; i < num_args; i++) { |
1935 | const auto arg_info = helper_->ReadByte(); |
1936 | assert(arg_info >= UnboxingInfoMetadata::kBoxed && |
1937 | arg_info < UnboxingInfoMetadata::kUnboxingCandidate); |
1938 | info->unboxed_args_info[i] = |
1939 | static_cast<UnboxingInfoMetadata::UnboxingInfoTag>(arg_info); |
1940 | } |
1941 | const auto return_info = helper_->ReadByte(); |
1942 | assert(return_info >= UnboxingInfoMetadata::kBoxed && |
1943 | return_info < UnboxingInfoMetadata::kUnboxingCandidate); |
1944 | info->return_info = |
1945 | static_cast<UnboxingInfoMetadata::UnboxingInfoTag>(return_info); |
1946 | return info; |
1947 | } |
1948 | |
1949 | intptr_t KernelReaderHelper::ReaderOffset() const { |
1950 | return reader_.offset(); |
1951 | } |
1952 | |
1953 | void KernelReaderHelper::SetOffset(intptr_t offset) { |
1954 | reader_.set_offset(offset); |
1955 | } |
1956 | |
1957 | void KernelReaderHelper::SkipBytes(intptr_t bytes) { |
1958 | reader_.set_offset(ReaderOffset() + bytes); |
1959 | } |
1960 | |
1961 | bool KernelReaderHelper::ReadBool() { |
1962 | return reader_.ReadBool(); |
1963 | } |
1964 | |
1965 | uint8_t KernelReaderHelper::ReadByte() { |
1966 | return reader_.ReadByte(); |
1967 | } |
1968 | |
1969 | uint32_t KernelReaderHelper::ReadUInt() { |
1970 | return reader_.ReadUInt(); |
1971 | } |
1972 | |
1973 | uint32_t KernelReaderHelper::ReadUInt32() { |
1974 | return reader_.ReadUInt32(); |
1975 | } |
1976 | |
1977 | uint32_t KernelReaderHelper::PeekUInt() { |
1978 | AlternativeReadingScope alt(&reader_); |
1979 | return reader_.ReadUInt(); |
1980 | } |
1981 | |
1982 | double KernelReaderHelper::ReadDouble() { |
1983 | return reader_.ReadDouble(); |
1984 | } |
1985 | |
1986 | uint32_t KernelReaderHelper::PeekListLength() { |
1987 | AlternativeReadingScope alt(&reader_); |
1988 | return reader_.ReadListLength(); |
1989 | } |
1990 | |
1991 | intptr_t KernelReaderHelper::ReadListLength() { |
1992 | return reader_.ReadListLength(); |
1993 | } |
1994 | |
1995 | StringIndex KernelReaderHelper::ReadStringReference() { |
1996 | return StringIndex(ReadUInt()); |
1997 | } |
1998 | |
1999 | NameIndex KernelReaderHelper::ReadCanonicalNameReference() { |
2000 | return reader_.ReadCanonicalNameReference(); |
2001 | } |
2002 | |
2003 | NameIndex KernelReaderHelper::ReadInterfaceMemberNameReference() { |
2004 | NameIndex name_index = reader_.ReadCanonicalNameReference(); |
2005 | NameIndex origin_name_index = reader_.ReadCanonicalNameReference(); |
2006 | if (!FLAG_precompiled_mode && origin_name_index != NameIndex::kInvalidName) { |
2007 | // Reference to a skipped member signature target, return the origin target. |
2008 | return origin_name_index; |
2009 | } |
2010 | return name_index; |
2011 | } |
2012 | |
2013 | StringIndex KernelReaderHelper::ReadNameAsStringIndex() { |
2014 | StringIndex name_index = ReadStringReference(); // read name index. |
2015 | if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') { |
2016 | ReadUInt(); // read library index. |
2017 | } |
2018 | return name_index; |
2019 | } |
2020 | |
2021 | const String& KernelReaderHelper::ReadNameAsMethodName() { |
2022 | StringIndex name_index = ReadStringReference(); // read name index. |
2023 | if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') { |
2024 | NameIndex library_reference = |
2025 | ReadCanonicalNameReference(); // read library index. |
2026 | return H.DartMethodName(library_reference, name_index); |
2027 | } else { |
2028 | return H.DartMethodName(NameIndex(), name_index); |
2029 | } |
2030 | } |
2031 | |
2032 | const String& KernelReaderHelper::ReadNameAsSetterName() { |
2033 | StringIndex name_index = ReadStringReference(); // read name index. |
2034 | if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') { |
2035 | NameIndex library_reference = |
2036 | ReadCanonicalNameReference(); // read library index. |
2037 | return H.DartSetterName(library_reference, name_index); |
2038 | } else { |
2039 | return H.DartSetterName(NameIndex(), name_index); |
2040 | } |
2041 | } |
2042 | |
2043 | const String& KernelReaderHelper::ReadNameAsGetterName() { |
2044 | StringIndex name_index = ReadStringReference(); // read name index. |
2045 | if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') { |
2046 | NameIndex library_reference = |
2047 | ReadCanonicalNameReference(); // read library index. |
2048 | return H.DartGetterName(library_reference, name_index); |
2049 | } else { |
2050 | return H.DartGetterName(NameIndex(), name_index); |
2051 | } |
2052 | } |
2053 | |
2054 | const String& KernelReaderHelper::ReadNameAsFieldName() { |
2055 | StringIndex name_index = ReadStringReference(); // read name index. |
2056 | if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') { |
2057 | NameIndex library_reference = |
2058 | ReadCanonicalNameReference(); // read library index. |
2059 | return H.DartFieldName(library_reference, name_index); |
2060 | } else { |
2061 | return H.DartFieldName(NameIndex(), name_index); |
2062 | } |
2063 | } |
2064 | |
2065 | void KernelReaderHelper::SkipFlags() { |
2066 | ReadFlags(); |
2067 | } |
2068 | |
2069 | void KernelReaderHelper::SkipStringReference() { |
2070 | ReadUInt(); |
2071 | } |
2072 | |
2073 | void KernelReaderHelper::SkipConstantReference() { |
2074 | ReadUInt(); |
2075 | } |
2076 | |
2077 | void KernelReaderHelper::SkipCanonicalNameReference() { |
2078 | ReadUInt(); |
2079 | } |
2080 | |
2081 | void KernelReaderHelper::SkipInterfaceMemberNameReference() { |
2082 | SkipCanonicalNameReference(); |
2083 | SkipCanonicalNameReference(); |
2084 | } |
2085 | |
2086 | void KernelReaderHelper::ReportUnexpectedTag(const char* variant, Tag tag) { |
2087 | FATAL3("Unexpected tag %d (%s) in ?, expected %s" , tag, Reader::TagName(tag), |
2088 | variant); |
2089 | } |
2090 | |
2091 | void KernelReaderHelper::ReadUntilFunctionNode() { |
2092 | const Tag tag = PeekTag(); |
2093 | if (tag == kProcedure) { |
2094 | ProcedureHelper procedure_helper(this); |
2095 | procedure_helper.ReadUntilExcluding(ProcedureHelper::kFunction); |
2096 | if (ReadTag() == kNothing) { // read function node tag. |
2097 | // Running a procedure without a function node doesn't make sense. |
2098 | UNREACHABLE(); |
2099 | } |
2100 | // Now at start of FunctionNode. |
2101 | } else if (tag == kConstructor) { |
2102 | ConstructorHelper constructor_helper(this); |
2103 | constructor_helper.ReadUntilExcluding(ConstructorHelper::kFunction); |
2104 | // Now at start of FunctionNode. |
2105 | // Notice that we also have a list of initializers after that! |
2106 | } else if (tag == kFunctionNode) { |
2107 | // Already at start of FunctionNode. |
2108 | } else { |
2109 | ReportUnexpectedTag("a procedure, a constructor or a function node" , tag); |
2110 | UNREACHABLE(); |
2111 | } |
2112 | } |
2113 | |
2114 | void KernelReaderHelper::SkipDartType() { |
2115 | Tag tag = ReadTag(); |
2116 | switch (tag) { |
2117 | case kInvalidType: |
2118 | case kDynamicType: |
2119 | case kVoidType: |
2120 | case kBottomType: |
2121 | // those contain nothing. |
2122 | return; |
2123 | case kNeverType: |
2124 | ReadNullability(); |
2125 | return; |
2126 | case kInterfaceType: |
2127 | SkipInterfaceType(false); |
2128 | return; |
2129 | case kSimpleInterfaceType: |
2130 | SkipInterfaceType(true); |
2131 | return; |
2132 | case kFunctionType: |
2133 | SkipFunctionType(false); |
2134 | return; |
2135 | case kSimpleFunctionType: |
2136 | SkipFunctionType(true); |
2137 | return; |
2138 | case kTypedefType: |
2139 | ReadNullability(); // read nullability. |
2140 | ReadUInt(); // read index for canonical name. |
2141 | SkipListOfDartTypes(); // read list of types. |
2142 | return; |
2143 | case kTypeParameterType: |
2144 | ReadNullability(); // read nullability. |
2145 | ReadUInt(); // read index for parameter. |
2146 | SkipOptionalDartType(); // read bound bound. |
2147 | return; |
2148 | default: |
2149 | ReportUnexpectedTag("type" , tag); |
2150 | UNREACHABLE(); |
2151 | } |
2152 | } |
2153 | |
2154 | void KernelReaderHelper::SkipOptionalDartType() { |
2155 | Tag tag = ReadTag(); // read tag. |
2156 | if (tag == kNothing) { |
2157 | return; |
2158 | } |
2159 | ASSERT(tag == kSomething); |
2160 | |
2161 | SkipDartType(); // read type. |
2162 | } |
2163 | |
2164 | void KernelReaderHelper::SkipInterfaceType(bool simple) { |
2165 | ReadNullability(); // read nullability. |
2166 | ReadUInt(); // read klass_name. |
2167 | if (!simple) { |
2168 | SkipListOfDartTypes(); // read list of types. |
2169 | } |
2170 | } |
2171 | |
2172 | void KernelReaderHelper::SkipFunctionType(bool simple) { |
2173 | ReadNullability(); // read nullability. |
2174 | |
2175 | if (!simple) { |
2176 | SkipTypeParametersList(); // read type_parameters. |
2177 | ReadUInt(); // read required parameter count. |
2178 | ReadUInt(); // read total parameter count. |
2179 | } |
2180 | |
2181 | SkipListOfDartTypes(); // read positional_parameters types. |
2182 | |
2183 | if (!simple) { |
2184 | const intptr_t named_count = |
2185 | ReadListLength(); // read named_parameters list length. |
2186 | for (intptr_t i = 0; i < named_count; ++i) { |
2187 | // read string reference (i.e. named_parameters[i].name). |
2188 | SkipStringReference(); |
2189 | SkipDartType(); // read named_parameters[i].type. |
2190 | SkipBytes(1); // read flags |
2191 | } |
2192 | } |
2193 | |
2194 | if (!simple) { |
2195 | SkipOptionalDartType(); // read typedef type. |
2196 | } |
2197 | |
2198 | SkipDartType(); // read return type. |
2199 | } |
2200 | |
2201 | void KernelReaderHelper::SkipStatementList() { |
2202 | intptr_t list_length = ReadListLength(); // read list length. |
2203 | for (intptr_t i = 0; i < list_length; ++i) { |
2204 | SkipStatement(); // read ith expression. |
2205 | } |
2206 | } |
2207 | |
2208 | void KernelReaderHelper::SkipListOfExpressions() { |
2209 | intptr_t list_length = ReadListLength(); // read list length. |
2210 | for (intptr_t i = 0; i < list_length; ++i) { |
2211 | SkipExpression(); // read ith expression. |
2212 | } |
2213 | } |
2214 | |
2215 | void KernelReaderHelper::SkipListOfDartTypes() { |
2216 | intptr_t list_length = ReadListLength(); // read list length. |
2217 | for (intptr_t i = 0; i < list_length; ++i) { |
2218 | SkipDartType(); // read ith type. |
2219 | } |
2220 | } |
2221 | |
2222 | void KernelReaderHelper::SkipListOfStrings() { |
2223 | intptr_t list_length = ReadListLength(); // read list length. |
2224 | for (intptr_t i = 0; i < list_length; ++i) { |
2225 | SkipStringReference(); // read ith string index. |
2226 | } |
2227 | } |
2228 | |
2229 | void KernelReaderHelper::SkipListOfVariableDeclarations() { |
2230 | intptr_t list_length = ReadListLength(); // read list length. |
2231 | for (intptr_t i = 0; i < list_length; ++i) { |
2232 | SkipVariableDeclaration(); // read ith variable declaration. |
2233 | } |
2234 | } |
2235 | |
2236 | void KernelReaderHelper::SkipTypeParametersList() { |
2237 | intptr_t list_length = ReadListLength(); // read list length. |
2238 | for (intptr_t i = 0; i < list_length; ++i) { |
2239 | TypeParameterHelper helper(this); |
2240 | helper.Finish(); |
2241 | } |
2242 | } |
2243 | |
2244 | void KernelReaderHelper::SkipInitializer() { |
2245 | Tag tag = ReadTag(); |
2246 | ReadByte(); // read isSynthetic flag. |
2247 | switch (tag) { |
2248 | case kInvalidInitializer: |
2249 | return; |
2250 | case kFieldInitializer: |
2251 | SkipCanonicalNameReference(); // read field_reference. |
2252 | SkipExpression(); // read value. |
2253 | return; |
2254 | case kSuperInitializer: |
2255 | ReadPosition(); // read position. |
2256 | SkipCanonicalNameReference(); // read target_reference. |
2257 | SkipArguments(); // read arguments. |
2258 | return; |
2259 | case kRedirectingInitializer: |
2260 | ReadPosition(); // read position. |
2261 | SkipCanonicalNameReference(); // read target_reference. |
2262 | SkipArguments(); // read arguments. |
2263 | return; |
2264 | case kLocalInitializer: |
2265 | SkipVariableDeclaration(); // read variable. |
2266 | return; |
2267 | case kAssertInitializer: |
2268 | SkipStatement(); |
2269 | return; |
2270 | default: |
2271 | ReportUnexpectedTag("initializer" , tag); |
2272 | UNREACHABLE(); |
2273 | } |
2274 | } |
2275 | |
2276 | void KernelReaderHelper::SkipExpression() { |
2277 | uint8_t payload = 0; |
2278 | Tag tag = ReadTag(&payload); |
2279 | switch (tag) { |
2280 | case kInvalidExpression: |
2281 | ReadPosition(); |
2282 | SkipStringReference(); |
2283 | return; |
2284 | case kVariableGet: |
2285 | ReadPosition(); // read position. |
2286 | ReadUInt(); // read kernel position. |
2287 | ReadUInt(); // read relative variable index. |
2288 | SkipOptionalDartType(); // read promoted type. |
2289 | return; |
2290 | case kSpecializedVariableGet: |
2291 | ReadPosition(); // read position. |
2292 | ReadUInt(); // read kernel position. |
2293 | return; |
2294 | case kVariableSet: |
2295 | ReadPosition(); // read position. |
2296 | ReadUInt(); // read kernel position. |
2297 | ReadUInt(); // read relative variable index. |
2298 | SkipExpression(); // read expression. |
2299 | return; |
2300 | case kSpecializedVariableSet: |
2301 | ReadPosition(); // read position. |
2302 | ReadUInt(); // read kernel position. |
2303 | SkipExpression(); // read expression. |
2304 | return; |
2305 | case kPropertyGet: |
2306 | ReadPosition(); // read position. |
2307 | SkipExpression(); // read receiver. |
2308 | SkipName(); // read name. |
2309 | SkipInterfaceMemberNameReference(); // read interface_target_reference. |
2310 | return; |
2311 | case kPropertySet: |
2312 | ReadPosition(); // read position. |
2313 | SkipExpression(); // read receiver. |
2314 | SkipName(); // read name. |
2315 | SkipExpression(); // read value. |
2316 | SkipInterfaceMemberNameReference(); // read interface_target_reference. |
2317 | return; |
2318 | case kSuperPropertyGet: |
2319 | ReadPosition(); // read position. |
2320 | SkipName(); // read name. |
2321 | SkipInterfaceMemberNameReference(); // read interface_target_reference. |
2322 | return; |
2323 | case kSuperPropertySet: |
2324 | ReadPosition(); // read position. |
2325 | SkipName(); // read name. |
2326 | SkipExpression(); // read value. |
2327 | SkipInterfaceMemberNameReference(); // read interface_target_reference. |
2328 | return; |
2329 | case kDirectPropertyGet: |
2330 | ReadPosition(); // read position. |
2331 | SkipExpression(); // read receiver. |
2332 | SkipInterfaceMemberNameReference(); // read target_reference. |
2333 | return; |
2334 | case kDirectPropertySet: |
2335 | ReadPosition(); // read position. |
2336 | SkipExpression(); // read receiver. |
2337 | SkipInterfaceMemberNameReference(); // read target_reference. |
2338 | SkipExpression(); // read value· |
2339 | return; |
2340 | case kStaticGet: |
2341 | ReadPosition(); // read position. |
2342 | SkipCanonicalNameReference(); // read target_reference. |
2343 | return; |
2344 | case kStaticSet: |
2345 | ReadPosition(); // read position. |
2346 | SkipCanonicalNameReference(); // read target_reference. |
2347 | SkipExpression(); // read expression. |
2348 | return; |
2349 | case kMethodInvocation: |
2350 | ReadPosition(); // read position. |
2351 | SkipExpression(); // read receiver. |
2352 | SkipName(); // read name. |
2353 | SkipArguments(); // read arguments. |
2354 | SkipInterfaceMemberNameReference(); // read interface_target_reference. |
2355 | return; |
2356 | case kSuperMethodInvocation: |
2357 | ReadPosition(); // read position. |
2358 | SkipName(); // read name. |
2359 | SkipArguments(); // read arguments. |
2360 | SkipInterfaceMemberNameReference(); // read interface_target_reference. |
2361 | return; |
2362 | case kDirectMethodInvocation: |
2363 | ReadPosition(); // read position. |
2364 | SkipExpression(); // read receiver. |
2365 | SkipInterfaceMemberNameReference(); // read target_reference. |
2366 | SkipArguments(); // read arguments. |
2367 | return; |
2368 | case kStaticInvocation: |
2369 | ReadPosition(); // read position. |
2370 | SkipCanonicalNameReference(); // read procedure_reference. |
2371 | SkipArguments(); // read arguments. |
2372 | return; |
2373 | case kConstructorInvocation: |
2374 | ReadPosition(); // read position. |
2375 | SkipCanonicalNameReference(); // read target_reference. |
2376 | SkipArguments(); // read arguments. |
2377 | return; |
2378 | case kNot: |
2379 | SkipExpression(); // read expression. |
2380 | return; |
2381 | case kNullCheck: |
2382 | ReadPosition(); // read position. |
2383 | SkipExpression(); // read expression. |
2384 | return; |
2385 | case kLogicalExpression: |
2386 | SkipExpression(); // read left. |
2387 | SkipBytes(1); // read operator. |
2388 | SkipExpression(); // read right. |
2389 | return; |
2390 | case kConditionalExpression: |
2391 | SkipExpression(); // read condition. |
2392 | SkipExpression(); // read then. |
2393 | SkipExpression(); // read otherwise. |
2394 | SkipOptionalDartType(); // read unused static type. |
2395 | return; |
2396 | case kStringConcatenation: |
2397 | ReadPosition(); // read position. |
2398 | SkipListOfExpressions(); // read list of expressions. |
2399 | return; |
2400 | case kIsExpression: |
2401 | ReadPosition(); // read position. |
2402 | if (translation_helper_.info().kernel_binary_version() >= 38) { |
2403 | SkipFlags(); // read flags. |
2404 | } |
2405 | SkipExpression(); // read operand. |
2406 | SkipDartType(); // read type. |
2407 | return; |
2408 | case kAsExpression: |
2409 | ReadPosition(); // read position. |
2410 | SkipFlags(); // read flags. |
2411 | SkipExpression(); // read operand. |
2412 | SkipDartType(); // read type. |
2413 | return; |
2414 | case kTypeLiteral: |
2415 | SkipDartType(); // read type. |
2416 | return; |
2417 | case kThisExpression: |
2418 | return; |
2419 | case kRethrow: |
2420 | ReadPosition(); // read position. |
2421 | return; |
2422 | case kThrow: |
2423 | ReadPosition(); // read position. |
2424 | SkipExpression(); // read expression. |
2425 | return; |
2426 | case kListLiteral: |
2427 | ReadPosition(); // read position. |
2428 | SkipDartType(); // read type. |
2429 | SkipListOfExpressions(); // read list of expressions. |
2430 | return; |
2431 | case kSetLiteral: |
2432 | // Set literals are currently desugared in the frontend and will not |
2433 | // reach the VM. See http://dartbug.com/35124 for discussion. |
2434 | UNREACHABLE(); |
2435 | return; |
2436 | case kMapLiteral: { |
2437 | ReadPosition(); // read position. |
2438 | SkipDartType(); // read key type. |
2439 | SkipDartType(); // read value type. |
2440 | intptr_t list_length = ReadListLength(); // read list length. |
2441 | for (intptr_t i = 0; i < list_length; ++i) { |
2442 | SkipExpression(); // read ith key. |
2443 | SkipExpression(); // read ith value. |
2444 | } |
2445 | return; |
2446 | } |
2447 | case kFunctionExpression: |
2448 | ReadPosition(); // read position. |
2449 | SkipFunctionNode(); // read function node. |
2450 | return; |
2451 | case kLet: |
2452 | SkipVariableDeclaration(); // read variable declaration. |
2453 | SkipExpression(); // read expression. |
2454 | return; |
2455 | case kBlockExpression: |
2456 | SkipStatementList(); |
2457 | SkipExpression(); // read expression. |
2458 | return; |
2459 | case kInstantiation: |
2460 | SkipExpression(); // read expression. |
2461 | SkipListOfDartTypes(); // read type arguments. |
2462 | return; |
2463 | case kBigIntLiteral: |
2464 | SkipStringReference(); // read string reference. |
2465 | return; |
2466 | case kStringLiteral: |
2467 | SkipStringReference(); // read string reference. |
2468 | return; |
2469 | case kSpecializedIntLiteral: |
2470 | return; |
2471 | case kNegativeIntLiteral: |
2472 | ReadUInt(); // read value. |
2473 | return; |
2474 | case kPositiveIntLiteral: |
2475 | ReadUInt(); // read value. |
2476 | return; |
2477 | case kDoubleLiteral: |
2478 | ReadDouble(); // read value. |
2479 | return; |
2480 | case kTrueLiteral: |
2481 | return; |
2482 | case kFalseLiteral: |
2483 | return; |
2484 | case kNullLiteral: |
2485 | return; |
2486 | case kConstantExpression: |
2487 | ReadPosition(); // read position. |
2488 | SkipDartType(); // read type. |
2489 | SkipConstantReference(); |
2490 | return; |
2491 | case kLoadLibrary: |
2492 | case kCheckLibraryIsLoaded: |
2493 | ReadUInt(); // skip library index |
2494 | return; |
2495 | case kConstStaticInvocation: |
2496 | case kConstConstructorInvocation: |
2497 | case kConstListLiteral: |
2498 | case kConstSetLiteral: |
2499 | case kConstMapLiteral: |
2500 | case kSymbolLiteral: |
2501 | // Const invocations and const literals are removed by the |
2502 | // constant evaluator. |
2503 | case kListConcatenation: |
2504 | case kSetConcatenation: |
2505 | case kMapConcatenation: |
2506 | case kInstanceCreation: |
2507 | case kFileUriExpression: |
2508 | // Collection concatenation, instance creation operations and |
2509 | // in-expression URI changes are internal to the front end and |
2510 | // removed by the constant evaluator. |
2511 | default: |
2512 | ReportUnexpectedTag("expression" , tag); |
2513 | UNREACHABLE(); |
2514 | } |
2515 | } |
2516 | |
2517 | void KernelReaderHelper::SkipStatement() { |
2518 | Tag tag = ReadTag(); // read tag. |
2519 | switch (tag) { |
2520 | case kExpressionStatement: |
2521 | SkipExpression(); // read expression. |
2522 | return; |
2523 | case kBlock: |
2524 | SkipStatementList(); |
2525 | return; |
2526 | case kEmptyStatement: |
2527 | return; |
2528 | case kAssertBlock: |
2529 | SkipStatementList(); |
2530 | return; |
2531 | case kAssertStatement: |
2532 | SkipExpression(); // Read condition. |
2533 | ReadPosition(); // read condition start offset. |
2534 | ReadPosition(); // read condition end offset. |
2535 | if (ReadTag() == kSomething) { |
2536 | SkipExpression(); // read (rest of) message. |
2537 | } |
2538 | return; |
2539 | case kLabeledStatement: |
2540 | SkipStatement(); // read body. |
2541 | return; |
2542 | case kBreakStatement: |
2543 | ReadPosition(); // read position. |
2544 | ReadUInt(); // read target_index. |
2545 | return; |
2546 | case kWhileStatement: |
2547 | ReadPosition(); // read position. |
2548 | SkipExpression(); // read condition. |
2549 | SkipStatement(); // read body. |
2550 | return; |
2551 | case kDoStatement: |
2552 | ReadPosition(); // read position. |
2553 | SkipStatement(); // read body. |
2554 | SkipExpression(); // read condition. |
2555 | return; |
2556 | case kForStatement: { |
2557 | ReadPosition(); // read position. |
2558 | SkipListOfVariableDeclarations(); // read variables. |
2559 | Tag tag = ReadTag(); // Read first part of condition. |
2560 | if (tag == kSomething) { |
2561 | SkipExpression(); // read rest of condition. |
2562 | } |
2563 | SkipListOfExpressions(); // read updates. |
2564 | SkipStatement(); // read body. |
2565 | return; |
2566 | } |
2567 | case kForInStatement: |
2568 | case kAsyncForInStatement: |
2569 | ReadPosition(); // read position. |
2570 | ReadPosition(); // read body position. |
2571 | SkipVariableDeclaration(); // read variable. |
2572 | SkipExpression(); // read iterable. |
2573 | SkipStatement(); // read body. |
2574 | return; |
2575 | case kSwitchStatement: { |
2576 | ReadPosition(); // read position. |
2577 | SkipExpression(); // read condition. |
2578 | int case_count = ReadListLength(); // read number of cases. |
2579 | for (intptr_t i = 0; i < case_count; ++i) { |
2580 | int expression_count = ReadListLength(); // read number of expressions. |
2581 | for (intptr_t j = 0; j < expression_count; ++j) { |
2582 | ReadPosition(); // read jth position. |
2583 | SkipExpression(); // read jth expression. |
2584 | } |
2585 | ReadBool(); // read is_default. |
2586 | SkipStatement(); // read body. |
2587 | } |
2588 | return; |
2589 | } |
2590 | case kContinueSwitchStatement: |
2591 | ReadPosition(); // read position. |
2592 | ReadUInt(); // read target_index. |
2593 | return; |
2594 | case kIfStatement: |
2595 | ReadPosition(); // read position. |
2596 | SkipExpression(); // read condition. |
2597 | SkipStatement(); // read then. |
2598 | SkipStatement(); // read otherwise. |
2599 | return; |
2600 | case kReturnStatement: { |
2601 | ReadPosition(); // read position |
2602 | Tag tag = ReadTag(); // read (first part of) expression. |
2603 | if (tag == kSomething) { |
2604 | SkipExpression(); // read (rest of) expression. |
2605 | } |
2606 | return; |
2607 | } |
2608 | case kTryCatch: { |
2609 | SkipStatement(); // read body. |
2610 | ReadByte(); // read flags |
2611 | intptr_t catch_count = ReadListLength(); // read number of catches. |
2612 | for (intptr_t i = 0; i < catch_count; ++i) { |
2613 | ReadPosition(); // read position. |
2614 | SkipDartType(); // read guard. |
2615 | tag = ReadTag(); // read first part of exception. |
2616 | if (tag == kSomething) { |
2617 | SkipVariableDeclaration(); // read exception. |
2618 | } |
2619 | tag = ReadTag(); // read first part of stack trace. |
2620 | if (tag == kSomething) { |
2621 | SkipVariableDeclaration(); // read stack trace. |
2622 | } |
2623 | SkipStatement(); // read body. |
2624 | } |
2625 | return; |
2626 | } |
2627 | case kTryFinally: |
2628 | SkipStatement(); // read body. |
2629 | SkipStatement(); // read finalizer. |
2630 | return; |
2631 | case kYieldStatement: { |
2632 | ReadPosition(); // read position. |
2633 | ReadByte(); // read flags. |
2634 | SkipExpression(); // read expression. |
2635 | return; |
2636 | } |
2637 | case kVariableDeclaration: |
2638 | SkipVariableDeclaration(); // read variable declaration. |
2639 | return; |
2640 | case kFunctionDeclaration: |
2641 | ReadPosition(); // read position. |
2642 | SkipVariableDeclaration(); // read variable. |
2643 | SkipFunctionNode(); // read function node. |
2644 | return; |
2645 | default: |
2646 | ReportUnexpectedTag("statement" , tag); |
2647 | UNREACHABLE(); |
2648 | } |
2649 | } |
2650 | |
2651 | void KernelReaderHelper::SkipFunctionNode() { |
2652 | FunctionNodeHelper function_node_helper(this); |
2653 | function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kEnd); |
2654 | } |
2655 | |
2656 | void KernelReaderHelper::SkipName() { |
2657 | StringIndex name_index = ReadStringReference(); // read name index. |
2658 | if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') { |
2659 | SkipCanonicalNameReference(); // read library index. |
2660 | } |
2661 | } |
2662 | |
2663 | void KernelReaderHelper::SkipArguments() { |
2664 | ReadUInt(); // read argument count. |
2665 | |
2666 | SkipListOfDartTypes(); // read list of types. |
2667 | SkipListOfExpressions(); // read positionals. |
2668 | |
2669 | // List of named. |
2670 | intptr_t list_length = ReadListLength(); // read list length. |
2671 | for (intptr_t i = 0; i < list_length; ++i) { |
2672 | SkipStringReference(); // read ith name index. |
2673 | SkipExpression(); // read ith expression. |
2674 | } |
2675 | } |
2676 | |
2677 | void KernelReaderHelper::SkipVariableDeclaration() { |
2678 | VariableDeclarationHelper helper(this); |
2679 | helper.ReadUntilExcluding(VariableDeclarationHelper::kEnd); |
2680 | } |
2681 | |
2682 | void KernelReaderHelper::SkipLibraryCombinator() { |
2683 | ReadBool(); // read is_show. |
2684 | intptr_t name_count = ReadUInt(); // read list length. |
2685 | for (intptr_t j = 0; j < name_count; ++j) { |
2686 | ReadUInt(); // read ith entry of name_indices. |
2687 | } |
2688 | } |
2689 | |
2690 | void KernelReaderHelper::SkipLibraryDependency() { |
2691 | ReadPosition(); // read file offset. |
2692 | ReadFlags(); |
2693 | SkipListOfExpressions(); // Annotations. |
2694 | ReadCanonicalNameReference(); |
2695 | ReadStringReference(); // Name. |
2696 | intptr_t combinator_count = ReadListLength(); |
2697 | for (intptr_t i = 0; i < combinator_count; ++i) { |
2698 | SkipLibraryCombinator(); |
2699 | } |
2700 | } |
2701 | |
2702 | void KernelReaderHelper::SkipLibraryPart() { |
2703 | SkipListOfExpressions(); // Read annotations. |
2704 | SkipStringReference(); // Read part URI index. |
2705 | } |
2706 | |
2707 | void KernelReaderHelper::SkipLibraryTypedef() { |
2708 | SkipCanonicalNameReference(); // read canonical name. |
2709 | ReadUInt(); // read source_uri_index. |
2710 | ReadPosition(); // read position. |
2711 | SkipStringReference(); // read name index. |
2712 | SkipListOfExpressions(); // read annotations. |
2713 | SkipTypeParametersList(); // read type parameters. |
2714 | SkipDartType(); // read type. |
2715 | SkipTypeParametersList(); // read type parameters of function type. |
2716 | SkipListOfVariableDeclarations(); // read positional parameters. |
2717 | SkipListOfVariableDeclarations(); // read named parameters. |
2718 | } |
2719 | |
2720 | TokenPosition KernelReaderHelper::ReadPosition() { |
2721 | TokenPosition position = reader_.ReadPosition(); |
2722 | RecordTokenPosition(position); |
2723 | return position; |
2724 | } |
2725 | |
2726 | intptr_t KernelReaderHelper::SourceTableFieldCountFromFirstLibraryOffset() { |
2727 | return SourceTableFieldCountFromFirstLibraryOffset41Plus; |
2728 | } |
2729 | |
2730 | intptr_t KernelReaderHelper::SourceTableSize() { |
2731 | AlternativeReadingScope alt(&reader_); |
2732 | intptr_t library_count = reader_.ReadFromIndexNoReset( |
2733 | reader_.size(), LibraryCountFieldCountFromEnd, 1, 0); |
2734 | |
2735 | const intptr_t count_from_first_library_offset = |
2736 | SourceTableFieldCountFromFirstLibraryOffset(); |
2737 | |
2738 | intptr_t source_table_offset = reader_.ReadFromIndexNoReset( |
2739 | reader_.size(), |
2740 | LibraryCountFieldCountFromEnd + 1 + library_count + 1 + |
2741 | count_from_first_library_offset, |
2742 | 1, 0); |
2743 | SetOffset(source_table_offset); // read source table offset. |
2744 | return reader_.ReadUInt32(); // read source table size. |
2745 | } |
2746 | |
2747 | intptr_t KernelReaderHelper::GetOffsetForSourceInfo(intptr_t index) { |
2748 | AlternativeReadingScope alt(&reader_); |
2749 | intptr_t library_count = reader_.ReadFromIndexNoReset( |
2750 | reader_.size(), LibraryCountFieldCountFromEnd, 1, 0); |
2751 | |
2752 | const intptr_t count_from_first_library_offset = |
2753 | SourceTableFieldCountFromFirstLibraryOffset(); |
2754 | |
2755 | intptr_t source_table_offset = reader_.ReadFromIndexNoReset( |
2756 | reader_.size(), |
2757 | LibraryCountFieldCountFromEnd + 1 + library_count + 1 + |
2758 | count_from_first_library_offset, |
2759 | 1, 0); |
2760 | intptr_t next_field_offset = reader_.ReadUInt32(); |
2761 | SetOffset(source_table_offset); |
2762 | intptr_t size = reader_.ReadUInt32(); // read source table size. |
2763 | |
2764 | return reader_.ReadFromIndexNoReset(next_field_offset, 0, size, index); |
2765 | } |
2766 | |
2767 | String& KernelReaderHelper::SourceTableUriFor(intptr_t index) { |
2768 | AlternativeReadingScope alt(&reader_); |
2769 | SetOffset(GetOffsetForSourceInfo(index)); |
2770 | intptr_t size = ReadUInt(); // read uri List<byte> size. |
2771 | return H.DartString(reader_.BufferAt(ReaderOffset()), size, Heap::kOld); |
2772 | } |
2773 | |
2774 | const String& KernelReaderHelper::GetSourceFor(intptr_t index) { |
2775 | AlternativeReadingScope alt(&reader_); |
2776 | SetOffset(GetOffsetForSourceInfo(index)); |
2777 | SkipBytes(ReadUInt()); // skip uri. |
2778 | intptr_t size = ReadUInt(); // read source List<byte> size. |
2779 | ASSERT(size >= 0); |
2780 | if (size == 0) { |
2781 | return Symbols::Empty(); |
2782 | } else { |
2783 | return H.DartString(reader_.BufferAt(ReaderOffset()), size, Heap::kOld); |
2784 | } |
2785 | } |
2786 | |
2787 | TypedDataPtr KernelReaderHelper::GetLineStartsFor(intptr_t index) { |
2788 | // Line starts are delta encoded. So get the max delta first so that we |
2789 | // can store them as tighly as possible. |
2790 | AlternativeReadingScope alt(&reader_); |
2791 | SetOffset(GetOffsetForSourceInfo(index)); |
2792 | SkipBytes(ReadUInt()); // skip uri. |
2793 | SkipBytes(ReadUInt()); // skip source. |
2794 | const intptr_t line_start_count = ReadUInt(); |
2795 | return reader_.ReadLineStartsData(line_start_count); |
2796 | } |
2797 | |
2798 | String& KernelReaderHelper::SourceTableImportUriFor(intptr_t index, |
2799 | uint32_t binaryVersion) { |
2800 | if (binaryVersion < 22) { |
2801 | return SourceTableUriFor(index); |
2802 | } |
2803 | |
2804 | AlternativeReadingScope alt(&reader_); |
2805 | SetOffset(GetOffsetForSourceInfo(index)); |
2806 | SkipBytes(ReadUInt()); // skip uri. |
2807 | SkipBytes(ReadUInt()); // skip source. |
2808 | const intptr_t line_start_count = ReadUInt(); // read number of line start |
2809 | // entries. |
2810 | for (intptr_t i = 0; i < line_start_count; ++i) { |
2811 | ReadUInt(); |
2812 | } |
2813 | |
2814 | intptr_t size = ReadUInt(); // read import uri List<byte> size. |
2815 | return H.DartString(reader_.BufferAt(ReaderOffset()), size, Heap::kOld); |
2816 | } |
2817 | |
2818 | intptr_t ActiveClass::MemberTypeParameterCount(Zone* zone) { |
2819 | ASSERT(member != NULL); |
2820 | if (member->IsFactory()) { |
2821 | TypeArguments& class_types = |
2822 | TypeArguments::Handle(zone, klass->type_parameters()); |
2823 | return class_types.Length(); |
2824 | } else if (member->IsMethodExtractor()) { |
2825 | Function& = |
2826 | Function::Handle(zone, member->extracted_method_closure()); |
2827 | TypeArguments& function_types = |
2828 | TypeArguments::Handle(zone, extracted.type_parameters()); |
2829 | return function_types.Length(); |
2830 | } else { |
2831 | TypeArguments& function_types = |
2832 | TypeArguments::Handle(zone, member->type_parameters()); |
2833 | return function_types.Length(); |
2834 | } |
2835 | } |
2836 | |
2837 | ActiveTypeParametersScope::(ActiveClass* active_class, |
2838 | const Function& innermost, |
2839 | Zone* Z) |
2840 | : active_class_(active_class), saved_(*active_class) { |
2841 | active_class_->enclosing = &innermost; |
2842 | |
2843 | intptr_t num_params = 0; |
2844 | |
2845 | Function& f = Function::Handle(Z); |
2846 | TypeArguments& f_params = TypeArguments::Handle(Z); |
2847 | for (f = innermost.raw(); f.parent_function() != Object::null(); |
2848 | f = f.parent_function()) { |
2849 | f_params = f.type_parameters(); |
2850 | num_params += f_params.Length(); |
2851 | } |
2852 | if (num_params == 0) return; |
2853 | |
2854 | TypeArguments& params = |
2855 | TypeArguments::Handle(Z, TypeArguments::New(num_params)); |
2856 | |
2857 | intptr_t index = num_params; |
2858 | for (f = innermost.raw(); f.parent_function() != Object::null(); |
2859 | f = f.parent_function()) { |
2860 | f_params = f.type_parameters(); |
2861 | for (intptr_t j = f_params.Length() - 1; j >= 0; --j) { |
2862 | params.SetTypeAt(--index, AbstractType::Handle(Z, f_params.TypeAt(j))); |
2863 | } |
2864 | } |
2865 | |
2866 | active_class_->local_type_parameters = ¶ms; |
2867 | } |
2868 | |
2869 | ActiveTypeParametersScope::( |
2870 | ActiveClass* active_class, |
2871 | const Function* function, |
2872 | const TypeArguments& new_params, |
2873 | Zone* Z) |
2874 | : active_class_(active_class), saved_(*active_class) { |
2875 | active_class_->enclosing = function; |
2876 | |
2877 | if (new_params.IsNull()) return; |
2878 | |
2879 | const TypeArguments* old_params = active_class->local_type_parameters; |
2880 | const intptr_t old_param_count = |
2881 | old_params == NULL ? 0 : old_params->Length(); |
2882 | const TypeArguments& extended_params = TypeArguments::Handle( |
2883 | Z, TypeArguments::New(old_param_count + new_params.Length())); |
2884 | |
2885 | intptr_t index = 0; |
2886 | for (intptr_t i = 0; i < old_param_count; ++i) { |
2887 | extended_params.SetTypeAt( |
2888 | index++, AbstractType::ZoneHandle(Z, old_params->TypeAt(i))); |
2889 | } |
2890 | for (intptr_t i = 0; i < new_params.Length(); ++i) { |
2891 | extended_params.SetTypeAt( |
2892 | index++, AbstractType::ZoneHandle(Z, new_params.TypeAt(i))); |
2893 | } |
2894 | |
2895 | active_class_->local_type_parameters = &extended_params; |
2896 | } |
2897 | |
2898 | TypeTranslator::TypeTranslator(KernelReaderHelper* helper, |
2899 | ConstantReader* constant_reader, |
2900 | ActiveClass* active_class, |
2901 | bool finalize, |
2902 | bool apply_legacy_erasure) |
2903 | : helper_(helper), |
2904 | constant_reader_(constant_reader), |
2905 | translation_helper_(helper->translation_helper_), |
2906 | active_class_(active_class), |
2907 | type_parameter_scope_(NULL), |
2908 | inferred_type_metadata_helper_(helper_, constant_reader_), |
2909 | unboxing_info_metadata_helper_(helper_), |
2910 | zone_(translation_helper_.zone()), |
2911 | result_(AbstractType::Handle(translation_helper_.zone())), |
2912 | finalize_(finalize), |
2913 | apply_legacy_erasure_(apply_legacy_erasure) {} |
2914 | |
2915 | AbstractType& TypeTranslator::BuildType() { |
2916 | BuildTypeInternal(); |
2917 | |
2918 | // We return a new `ZoneHandle` here on purpose: The intermediate language |
2919 | // instructions do not make a copy of the handle, so we do it. |
2920 | return AbstractType::ZoneHandle(Z, result_.raw()); |
2921 | } |
2922 | |
2923 | AbstractType& TypeTranslator::BuildTypeWithoutFinalization() { |
2924 | bool saved_finalize = finalize_; |
2925 | finalize_ = false; |
2926 | BuildTypeInternal(); |
2927 | finalize_ = saved_finalize; |
2928 | |
2929 | // We return a new `ZoneHandle` here on purpose: The intermediate language |
2930 | // instructions do not make a copy of the handle, so we do it. |
2931 | return AbstractType::ZoneHandle(Z, result_.raw()); |
2932 | } |
2933 | |
2934 | void TypeTranslator::BuildTypeInternal() { |
2935 | Tag tag = helper_->ReadTag(); |
2936 | switch (tag) { |
2937 | case kInvalidType: |
2938 | case kDynamicType: |
2939 | result_ = Object::dynamic_type().raw(); |
2940 | break; |
2941 | case kVoidType: |
2942 | result_ = Object::void_type().raw(); |
2943 | break; |
2944 | case kNeverType: { |
2945 | const Nullability nullability = helper_->ReadNullability(); |
2946 | if (apply_legacy_erasure_) { |
2947 | result_ = I->object_store()->null_type(); |
2948 | } else { |
2949 | result_ = Type::Handle(Z, I->object_store()->never_type()) |
2950 | .ToNullability(nullability, Heap::kOld); |
2951 | } |
2952 | break; |
2953 | } |
2954 | case kBottomType: |
2955 | // Map Bottom type to Null type until not emitted by CFE anymore. |
2956 | result_ = I->object_store()->null_type(); |
2957 | ASSERT(result_.IsNullable()); |
2958 | break; |
2959 | case kInterfaceType: |
2960 | BuildInterfaceType(false); |
2961 | break; |
2962 | case kSimpleInterfaceType: |
2963 | BuildInterfaceType(true); |
2964 | break; |
2965 | case kFunctionType: |
2966 | BuildFunctionType(false); |
2967 | break; |
2968 | case kSimpleFunctionType: |
2969 | BuildFunctionType(true); |
2970 | break; |
2971 | case kTypeParameterType: |
2972 | BuildTypeParameterType(); |
2973 | break; |
2974 | default: |
2975 | helper_->ReportUnexpectedTag("type" , tag); |
2976 | UNREACHABLE(); |
2977 | } |
2978 | } |
2979 | |
2980 | void TypeTranslator::BuildInterfaceType(bool simple) { |
2981 | // NOTE: That an interface type like `T<A, B>` is considered to be |
2982 | // malformed iff `T` is malformed. |
2983 | // => We therefore ignore errors in `A` or `B`. |
2984 | |
2985 | Nullability nullability = helper_->ReadNullability(); |
2986 | if (apply_legacy_erasure_) { |
2987 | nullability = Nullability::kLegacy; |
2988 | } |
2989 | |
2990 | NameIndex klass_name = |
2991 | helper_->ReadCanonicalNameReference(); // read klass_name. |
2992 | |
2993 | const Class& klass = Class::Handle(Z, H.LookupClassByKernelClass(klass_name)); |
2994 | ASSERT(!klass.IsNull()); |
2995 | if (klass.is_declared_in_bytecode()) { |
2996 | klass.EnsureDeclarationLoaded(); |
2997 | } |
2998 | if (simple) { |
2999 | if (finalize_ || klass.is_type_finalized()) { |
3000 | // Fast path for non-generic types: retrieve or populate the class's only |
3001 | // canonical type (as long as only one nullability variant is used), which |
3002 | // is its declaration type. |
3003 | result_ = klass.DeclarationType(); |
3004 | result_ = Type::Cast(result_).ToNullability(nullability, Heap::kOld); |
3005 | } else { |
3006 | // Note that the type argument vector is not yet extended. |
3007 | result_ = Type::New(klass, Object::null_type_arguments(), |
3008 | klass.token_pos(), nullability); |
3009 | } |
3010 | return; |
3011 | } |
3012 | |
3013 | intptr_t length = |
3014 | helper_->ReadListLength(); // read type_arguments list length. |
3015 | const TypeArguments& type_arguments = |
3016 | BuildTypeArguments(length); // read type arguments. |
3017 | result_ = |
3018 | Type::New(klass, type_arguments, TokenPosition::kNoSource, nullability); |
3019 | result_ = result_.NormalizeFutureOrType(Heap::kOld); |
3020 | if (finalize_) { |
3021 | ASSERT(active_class_->klass != NULL); |
3022 | result_ = ClassFinalizer::FinalizeType(*active_class_->klass, result_); |
3023 | } |
3024 | } |
3025 | |
3026 | void TypeTranslator::BuildFunctionType(bool simple) { |
3027 | Function& signature_function = Function::ZoneHandle( |
3028 | Z, Function::NewSignatureFunction(*active_class_->klass, |
3029 | active_class_->enclosing != NULL |
3030 | ? *active_class_->enclosing |
3031 | : Function::Handle(Z), |
3032 | TokenPosition::kNoSource)); |
3033 | |
3034 | Nullability nullability = helper_->ReadNullability(); |
3035 | if (apply_legacy_erasure_) { |
3036 | nullability = Nullability::kLegacy; |
3037 | } |
3038 | |
3039 | // Suspend finalization of types inside this one. They will be finalized after |
3040 | // the whole function type is constructed. |
3041 | // |
3042 | // TODO(31213): Test further when nested generic function types |
3043 | // are supported by fasta. |
3044 | bool finalize = finalize_; |
3045 | finalize_ = false; |
3046 | |
3047 | if (!simple) { |
3048 | LoadAndSetupTypeParameters(active_class_, signature_function, |
3049 | helper_->ReadListLength(), signature_function); |
3050 | } |
3051 | |
3052 | ActiveTypeParametersScope scope( |
3053 | active_class_, &signature_function, |
3054 | TypeArguments::Handle(Z, signature_function.type_parameters()), Z); |
3055 | |
3056 | intptr_t required_count; |
3057 | intptr_t all_count; |
3058 | intptr_t positional_count; |
3059 | if (!simple) { |
3060 | required_count = helper_->ReadUInt(); // read required parameter count. |
3061 | all_count = helper_->ReadUInt(); // read total parameter count. |
3062 | positional_count = |
3063 | helper_->ReadListLength(); // read positional_parameters list length. |
3064 | } else { |
3065 | positional_count = |
3066 | helper_->ReadListLength(); // read positional_parameters list length. |
3067 | required_count = positional_count; |
3068 | all_count = positional_count; |
3069 | } |
3070 | |
3071 | const intptr_t all_count_with_receiver = all_count + 1; |
3072 | const Array& parameter_types = |
3073 | Array::Handle(Z, Array::New(all_count_with_receiver, Heap::kOld)); |
3074 | signature_function.set_parameter_types(parameter_types); |
3075 | const Array& parameter_names = Array::Handle( |
3076 | Z, Array::New(simple ? all_count_with_receiver |
3077 | : Function::NameArrayLengthIncludingFlags( |
3078 | all_count_with_receiver), |
3079 | Heap::kOld)); |
3080 | signature_function.set_parameter_names(parameter_names); |
3081 | |
3082 | intptr_t pos = 0; |
3083 | parameter_types.SetAt(pos, AbstractType::dynamic_type()); |
3084 | parameter_names.SetAt(pos, H.DartSymbolPlain("_receiver_" )); |
3085 | ++pos; |
3086 | for (intptr_t i = 0; i < positional_count; ++i, ++pos) { |
3087 | BuildTypeInternal(); // read ith positional parameter. |
3088 | parameter_types.SetAt(pos, result_); |
3089 | parameter_names.SetAt(pos, H.DartSymbolPlain("noname" )); |
3090 | } |
3091 | |
3092 | // The additional first parameter is the receiver type (set to dynamic). |
3093 | signature_function.set_num_fixed_parameters(1 + required_count); |
3094 | signature_function.SetNumOptionalParameters( |
3095 | all_count - required_count, positional_count > required_count); |
3096 | |
3097 | if (!simple) { |
3098 | const intptr_t named_count = |
3099 | helper_->ReadListLength(); // read named_parameters list length. |
3100 | for (intptr_t i = 0; i < named_count; ++i, ++pos) { |
3101 | // read string reference (i.e. named_parameters[i].name). |
3102 | String& name = H.DartSymbolObfuscate(helper_->ReadStringReference()); |
3103 | BuildTypeInternal(); // read named_parameters[i].type. |
3104 | const uint8_t flags = helper_->ReadFlags(); // read flags |
3105 | parameter_types.SetAt(pos, result_); |
3106 | parameter_names.SetAt(pos, name); |
3107 | if (!apply_legacy_erasure_ && |
3108 | (flags & static_cast<uint8_t>(NamedTypeFlags::kIsRequired)) != 0) { |
3109 | signature_function.SetIsRequiredAt(pos); |
3110 | } |
3111 | } |
3112 | signature_function.TruncateUnusedParameterFlags(); |
3113 | } |
3114 | |
3115 | if (!simple) { |
3116 | helper_->SkipOptionalDartType(); // read typedef type. |
3117 | } |
3118 | |
3119 | BuildTypeInternal(); // read return type. |
3120 | signature_function.set_result_type(result_); |
3121 | |
3122 | finalize_ = finalize; |
3123 | |
3124 | Type& signature_type = |
3125 | Type::ZoneHandle(Z, signature_function.SignatureType(nullability)); |
3126 | |
3127 | if (finalize_) { |
3128 | signature_type ^= |
3129 | ClassFinalizer::FinalizeType(*active_class_->klass, signature_type); |
3130 | // Do not refer to signature_function anymore, since it may have been |
3131 | // replaced during canonicalization. |
3132 | signature_function = Function::null(); |
3133 | } |
3134 | |
3135 | result_ = signature_type.raw(); |
3136 | } |
3137 | |
3138 | void TypeTranslator::BuildTypeParameterType() { |
3139 | Nullability nullability = helper_->ReadNullability(); |
3140 | if (apply_legacy_erasure_) { |
3141 | nullability = Nullability::kLegacy; |
3142 | } |
3143 | |
3144 | intptr_t parameter_index = helper_->ReadUInt(); // read parameter index. |
3145 | helper_->SkipOptionalDartType(); // read bound. |
3146 | |
3147 | const TypeArguments& class_types = |
3148 | TypeArguments::Handle(Z, active_class_->klass->type_parameters()); |
3149 | if (parameter_index < class_types.Length()) { |
3150 | // The index of the type parameter in [parameters] is |
3151 | // the same index into the `klass->type_parameters()` array. |
3152 | const auto& type_param = |
3153 | TypeParameter::CheckedHandle(Z, class_types.TypeAt(parameter_index)); |
3154 | result_ = type_param.ToNullability(nullability, Heap::kOld); |
3155 | active_class_->RecordDerivedTypeParameter(Z, type_param, |
3156 | TypeParameter::Cast(result_)); |
3157 | return; |
3158 | } |
3159 | parameter_index -= class_types.Length(); |
3160 | |
3161 | if (active_class_->HasMember()) { |
3162 | if (active_class_->MemberIsFactoryProcedure()) { |
3163 | // |
3164 | // WARNING: This is a little hackish: |
3165 | // |
3166 | // We have a static factory constructor. The kernel IR gives the factory |
3167 | // constructor function its own type parameters (which are equal in name |
3168 | // and number to the ones of the enclosing class). I.e., |
3169 | // |
3170 | // class A<T> { |
3171 | // factory A.x() { return new B<T>(); } |
3172 | // } |
3173 | // |
3174 | // is basically translated to this: |
3175 | // |
3176 | // class A<T> { |
3177 | // static A.x<T'>() { return new B<T'>(); } |
3178 | // } |
3179 | // |
3180 | if (class_types.Length() > parameter_index) { |
3181 | const auto& type_param = TypeParameter::CheckedHandle( |
3182 | Z, class_types.TypeAt(parameter_index)); |
3183 | result_ = type_param.ToNullability(nullability, Heap::kOld); |
3184 | active_class_->RecordDerivedTypeParameter(Z, type_param, |
3185 | TypeParameter::Cast(result_)); |
3186 | return; |
3187 | } |
3188 | parameter_index -= class_types.Length(); |
3189 | } |
3190 | // Factory function should not be considered as procedure. |
3191 | intptr_t procedure_type_parameter_count = |
3192 | (active_class_->MemberIsProcedure() && |
3193 | !active_class_->MemberIsFactoryProcedure()) |
3194 | ? active_class_->MemberTypeParameterCount(Z) |
3195 | : 0; |
3196 | if (procedure_type_parameter_count > 0) { |
3197 | if (procedure_type_parameter_count > parameter_index) { |
3198 | const auto& type_param = TypeParameter::CheckedHandle( |
3199 | Z, |
3200 | TypeArguments::Handle(Z, active_class_->member->type_parameters()) |
3201 | .TypeAt(parameter_index)); |
3202 | result_ = type_param.ToNullability(nullability, Heap::kOld); |
3203 | active_class_->RecordDerivedTypeParameter(Z, type_param, |
3204 | TypeParameter::Cast(result_)); |
3205 | if (finalize_) { |
3206 | result_ = |
3207 | ClassFinalizer::FinalizeType(*active_class_->klass, result_); |
3208 | } |
3209 | return; |
3210 | } |
3211 | parameter_index -= procedure_type_parameter_count; |
3212 | } |
3213 | } |
3214 | |
3215 | if (active_class_->local_type_parameters != NULL) { |
3216 | if (parameter_index < active_class_->local_type_parameters->Length()) { |
3217 | const auto& type_param = TypeParameter::CheckedHandle( |
3218 | Z, active_class_->local_type_parameters->TypeAt(parameter_index)); |
3219 | result_ = type_param.ToNullability(nullability, Heap::kOld); |
3220 | active_class_->RecordDerivedTypeParameter(Z, type_param, |
3221 | TypeParameter::Cast(result_)); |
3222 | if (finalize_) { |
3223 | result_ = ClassFinalizer::FinalizeType(*active_class_->klass, result_); |
3224 | } |
3225 | return; |
3226 | } |
3227 | parameter_index -= active_class_->local_type_parameters->Length(); |
3228 | } |
3229 | |
3230 | if (type_parameter_scope_ != NULL && |
3231 | parameter_index < type_parameter_scope_->outer_parameter_count() + |
3232 | type_parameter_scope_->parameter_count()) { |
3233 | result_ = Type::DynamicType(); |
3234 | return; |
3235 | } |
3236 | |
3237 | H.ReportError( |
3238 | helper_->script(), TokenPosition::kNoSource, |
3239 | "Unbound type parameter found in %s. Please report this at dartbug.com." , |
3240 | active_class_->ToCString()); |
3241 | } |
3242 | |
3243 | const TypeArguments& TypeTranslator::BuildTypeArguments(intptr_t length) { |
3244 | bool only_dynamic = true; |
3245 | intptr_t offset = helper_->ReaderOffset(); |
3246 | for (intptr_t i = 0; i < length; ++i) { |
3247 | if (helper_->ReadTag() != kDynamicType) { // Read the ith types tag. |
3248 | only_dynamic = false; |
3249 | helper_->SetOffset(offset); |
3250 | break; |
3251 | } |
3252 | } |
3253 | TypeArguments& type_arguments = TypeArguments::ZoneHandle(Z); |
3254 | if (!only_dynamic) { |
3255 | type_arguments = TypeArguments::New(length); |
3256 | for (intptr_t i = 0; i < length; ++i) { |
3257 | BuildTypeInternal(); // read ith type. |
3258 | type_arguments.SetTypeAt(i, result_); |
3259 | } |
3260 | |
3261 | if (finalize_) { |
3262 | type_arguments = type_arguments.Canonicalize(); |
3263 | } |
3264 | } |
3265 | return type_arguments; |
3266 | } |
3267 | |
3268 | const TypeArguments& TypeTranslator::BuildInstantiatedTypeArguments( |
3269 | const Class& receiver_class, |
3270 | intptr_t length) { |
3271 | const TypeArguments& type_arguments = BuildTypeArguments(length); |
3272 | |
3273 | // If type_arguments is null all arguments are dynamic. |
3274 | // If, however, this class doesn't specify all the type arguments directly we |
3275 | // still need to finalize the type below in order to get any non-dynamic types |
3276 | // from any super. See http://www.dartbug.com/29537. |
3277 | if (type_arguments.IsNull() && receiver_class.NumTypeArguments() == length) { |
3278 | return type_arguments; |
3279 | } |
3280 | |
3281 | // We make a temporary [Type] object and use `ClassFinalizer::FinalizeType` to |
3282 | // finalize the argument types. |
3283 | // (This can for example make the [type_arguments] vector larger) |
3284 | Type& type = Type::Handle( |
3285 | Z, Type::New(receiver_class, type_arguments, TokenPosition::kNoSource)); |
3286 | if (finalize_) { |
3287 | type ^= ClassFinalizer::FinalizeType(*active_class_->klass, type); |
3288 | } |
3289 | |
3290 | const TypeArguments& instantiated_type_arguments = |
3291 | TypeArguments::ZoneHandle(Z, type.arguments()); |
3292 | return instantiated_type_arguments; |
3293 | } |
3294 | |
3295 | void TypeTranslator::LoadAndSetupTypeParameters( |
3296 | ActiveClass* active_class, |
3297 | const Object& set_on, |
3298 | intptr_t type_parameter_count, |
3299 | const Function& parameterized_function) { |
3300 | ASSERT(type_parameter_count >= 0); |
3301 | if (type_parameter_count == 0) { |
3302 | return; |
3303 | } |
3304 | ASSERT(set_on.IsClass() || set_on.IsFunction()); |
3305 | bool set_on_class = set_on.IsClass(); |
3306 | ASSERT(set_on_class == parameterized_function.IsNull()); |
3307 | |
3308 | // First setup the type parameters, so if any of the following code uses it |
3309 | // (in a recursive way) we're fine. |
3310 | TypeArguments& type_parameters = TypeArguments::Handle(Z); |
3311 | TypeParameter& parameter = TypeParameter::Handle(Z); |
3312 | const Type& null_bound = Type::Handle(Z); |
3313 | |
3314 | const NNBDMode nnbd_mode = set_on.IsClass() |
3315 | ? Class::Cast(set_on).nnbd_mode() |
3316 | : Function::Cast(set_on).nnbd_mode(); |
3317 | const Nullability nullability = (nnbd_mode == NNBDMode::kOptedInLib) |
3318 | ? Nullability::kNonNullable |
3319 | : Nullability::kLegacy; |
3320 | |
3321 | // Step a) Create array of [TypeParameter] objects (without bound). |
3322 | type_parameters = TypeArguments::New(type_parameter_count); |
3323 | const Library& lib = Library::Handle(Z, active_class->klass->library()); |
3324 | { |
3325 | AlternativeReadingScope alt(&helper_->reader_); |
3326 | for (intptr_t i = 0; i < type_parameter_count; i++) { |
3327 | TypeParameterHelper helper(helper_); |
3328 | helper.Finish(); |
3329 | parameter = TypeParameter::New( |
3330 | set_on_class ? *active_class->klass : Class::Handle(Z), |
3331 | parameterized_function, i, |
3332 | H.DartIdentifier(lib, helper.name_index_), // read ith name index. |
3333 | null_bound, helper.IsGenericCovariantImpl(), nullability, |
3334 | TokenPosition::kNoSource); |
3335 | parameter.SetCanonical(); |
3336 | parameter.SetDeclaration(true); |
3337 | type_parameters.SetTypeAt(i, parameter); |
3338 | } |
3339 | } |
3340 | |
3341 | if (set_on.IsClass()) { |
3342 | Class::Cast(set_on).set_type_parameters(type_parameters); |
3343 | } else { |
3344 | Function::Cast(set_on).set_type_parameters(type_parameters); |
3345 | } |
3346 | |
3347 | const Function* enclosing = NULL; |
3348 | if (!parameterized_function.IsNull()) { |
3349 | enclosing = ¶meterized_function; |
3350 | } |
3351 | ActiveTypeParametersScope scope(active_class, enclosing, type_parameters, Z); |
3352 | |
3353 | // Step b) Fill in the bounds of all [TypeParameter]s. |
3354 | for (intptr_t i = 0; i < type_parameter_count; i++) { |
3355 | TypeParameterHelper helper(helper_); |
3356 | helper.ReadUntilExcludingAndSetJustRead(TypeParameterHelper::kBound); |
3357 | |
3358 | // TODO(github.com/dart-lang/kernel/issues/42): This should be handled |
3359 | // by the frontend. |
3360 | parameter ^= type_parameters.TypeAt(i); |
3361 | const Tag tag = helper_->PeekTag(); // peek ith bound type. |
3362 | if (tag == kDynamicType) { |
3363 | helper_->SkipDartType(); // read ith bound. |
3364 | parameter.set_bound( |
3365 | Type::Handle(Z, nnbd_mode == NNBDMode::kOptedInLib |
3366 | ? I->object_store()->nullable_object_type() |
3367 | : I->object_store()->legacy_object_type())); |
3368 | } else { |
3369 | AbstractType& bound = BuildTypeWithoutFinalization(); // read ith bound. |
3370 | parameter.set_bound(bound); |
3371 | } |
3372 | |
3373 | helper.Finish(); |
3374 | } |
3375 | |
3376 | // Fix bounds in all derived type parameters (with different nullabilities). |
3377 | if (active_class->derived_type_parameters != nullptr) { |
3378 | auto& derived = TypeParameter::Handle(Z); |
3379 | auto& bound = AbstractType::Handle(Z); |
3380 | for (intptr_t i = 0, n = active_class->derived_type_parameters->Length(); |
3381 | i < n; ++i) { |
3382 | derived ^= active_class->derived_type_parameters->At(i); |
3383 | if (derived.bound() == AbstractType::null() && |
3384 | (derived.parameterized_class() == set_on.raw() || |
3385 | derived.parameterized_function() == set_on.raw())) { |
3386 | ASSERT(!derived.IsFinalized()); |
3387 | parameter ^= type_parameters.TypeAt(derived.index()); |
3388 | bound = parameter.bound(); |
3389 | derived.set_bound(bound); |
3390 | } |
3391 | } |
3392 | } |
3393 | } |
3394 | |
3395 | const Type& TypeTranslator::ReceiverType(const Class& klass) { |
3396 | ASSERT(!klass.IsNull()); |
3397 | ASSERT(!klass.IsTypedefClass()); |
3398 | // Note that if klass is _Closure, the returned type will be _Closure, |
3399 | // and not the signature type. |
3400 | Type& type = Type::ZoneHandle(Z); |
3401 | if (finalize_ || klass.is_type_finalized()) { |
3402 | type = klass.DeclarationType(); |
3403 | } else { |
3404 | type = Type::New(klass, TypeArguments::Handle(Z, klass.type_parameters()), |
3405 | klass.token_pos(), Nullability::kNonNullable); |
3406 | } |
3407 | return type; |
3408 | } |
3409 | |
3410 | static void SetupUnboxingInfoOfParameter(const Function& function, |
3411 | intptr_t param_index, |
3412 | const UnboxingInfoMetadata* metadata) { |
3413 | const intptr_t param_pos = |
3414 | param_index + (function.HasThisParameter() ? 1 : 0); |
3415 | |
3416 | if (param_pos < function.maximum_unboxed_parameter_count()) { |
3417 | switch (metadata->unboxed_args_info[param_index]) { |
3418 | case UnboxingInfoMetadata::kUnboxedIntCandidate: |
3419 | if (FlowGraphCompiler::SupportsUnboxedInt64()) { |
3420 | function.set_unboxed_integer_parameter_at(param_pos); |
3421 | } |
3422 | break; |
3423 | case UnboxingInfoMetadata::kUnboxedDoubleCandidate: |
3424 | if (FlowGraphCompiler::SupportsUnboxedDoubles()) { |
3425 | function.set_unboxed_double_parameter_at(param_pos); |
3426 | } |
3427 | break; |
3428 | case UnboxingInfoMetadata::kUnboxingCandidate: |
3429 | UNREACHABLE(); |
3430 | break; |
3431 | case UnboxingInfoMetadata::kBoxed: |
3432 | break; |
3433 | default: |
3434 | UNREACHABLE(); |
3435 | break; |
3436 | } |
3437 | } |
3438 | } |
3439 | |
3440 | static void SetupUnboxingInfoOfReturnValue( |
3441 | const Function& function, |
3442 | const UnboxingInfoMetadata* metadata) { |
3443 | switch (metadata->return_info) { |
3444 | case UnboxingInfoMetadata::kUnboxedIntCandidate: |
3445 | if (FlowGraphCompiler::SupportsUnboxedInt64()) { |
3446 | function.set_unboxed_integer_return(); |
3447 | } |
3448 | break; |
3449 | case UnboxingInfoMetadata::kUnboxedDoubleCandidate: |
3450 | if (FlowGraphCompiler::SupportsUnboxedDoubles()) { |
3451 | function.set_unboxed_double_return(); |
3452 | } |
3453 | break; |
3454 | case UnboxingInfoMetadata::kUnboxingCandidate: |
3455 | UNREACHABLE(); |
3456 | break; |
3457 | case UnboxingInfoMetadata::kBoxed: |
3458 | break; |
3459 | default: |
3460 | UNREACHABLE(); |
3461 | break; |
3462 | } |
3463 | } |
3464 | |
3465 | void TypeTranslator::SetupUnboxingInfoMetadata(const Function& function, |
3466 | intptr_t library_kernel_offset) { |
3467 | const intptr_t kernel_offset = |
3468 | function.kernel_offset() + library_kernel_offset; |
3469 | const auto unboxing_info = |
3470 | unboxing_info_metadata_helper_.GetUnboxingInfoMetadata(kernel_offset); |
3471 | |
3472 | // TODO(dartbug.com/32292): accept unboxed parameters and return value |
3473 | // when FLAG_use_table_dispatch == false. |
3474 | if (FLAG_precompiled_mode && unboxing_info != nullptr && |
3475 | FLAG_use_table_dispatch && FLAG_use_bare_instructions) { |
3476 | for (intptr_t i = 0; i < unboxing_info->unboxed_args_info.length(); i++) { |
3477 | SetupUnboxingInfoOfParameter(function, i, unboxing_info); |
3478 | } |
3479 | SetupUnboxingInfoOfReturnValue(function, unboxing_info); |
3480 | } |
3481 | } |
3482 | |
3483 | void TypeTranslator::SetupUnboxingInfoMetadataForFieldAccessors( |
3484 | const Function& field_accessor, |
3485 | intptr_t library_kernel_offset) { |
3486 | const intptr_t kernel_offset = |
3487 | field_accessor.kernel_offset() + library_kernel_offset; |
3488 | const auto unboxing_info = |
3489 | unboxing_info_metadata_helper_.GetUnboxingInfoMetadata(kernel_offset); |
3490 | |
3491 | // TODO(dartbug.com/32292): accept unboxed parameters and return value |
3492 | // when FLAG_use_table_dispatch == false. |
3493 | if (FLAG_precompiled_mode && unboxing_info != nullptr && |
3494 | FLAG_use_table_dispatch && FLAG_use_bare_instructions) { |
3495 | if (field_accessor.IsImplicitSetterFunction()) { |
3496 | for (intptr_t i = 0; i < unboxing_info->unboxed_args_info.length(); i++) { |
3497 | SetupUnboxingInfoOfParameter(field_accessor, i, unboxing_info); |
3498 | } |
3499 | } else { |
3500 | ASSERT(field_accessor.IsImplicitGetterFunction() || |
3501 | field_accessor.IsImplicitStaticGetterFunction()); |
3502 | SetupUnboxingInfoOfReturnValue(field_accessor, unboxing_info); |
3503 | } |
3504 | } |
3505 | } |
3506 | |
3507 | void TypeTranslator::SetupFunctionParameters( |
3508 | const Class& klass, |
3509 | const Function& function, |
3510 | bool is_method, |
3511 | bool is_closure, |
3512 | FunctionNodeHelper* function_node_helper) { |
3513 | ASSERT(!(is_method && is_closure)); |
3514 | bool is_factory = function.IsFactory(); |
3515 | intptr_t = (is_method || is_closure || is_factory) ? 1 : 0; |
3516 | |
3517 | if (!is_factory) { |
3518 | LoadAndSetupTypeParameters(active_class_, function, |
3519 | helper_->ReadListLength(), function); |
3520 | function_node_helper->SetJustRead(FunctionNodeHelper::kTypeParameters); |
3521 | } |
3522 | |
3523 | ActiveTypeParametersScope scope(active_class_, function, Z); |
3524 | |
3525 | function_node_helper->ReadUntilExcluding( |
3526 | FunctionNodeHelper::kPositionalParameters); |
3527 | |
3528 | intptr_t required_parameter_count = |
3529 | function_node_helper->required_parameter_count_; |
3530 | intptr_t total_parameter_count = function_node_helper->total_parameter_count_; |
3531 | |
3532 | intptr_t positional_parameter_count = |
3533 | helper_->ReadListLength(); // read list length. |
3534 | |
3535 | intptr_t named_parameter_count = |
3536 | total_parameter_count - positional_parameter_count; |
3537 | |
3538 | function.set_num_fixed_parameters(extra_parameters + |
3539 | required_parameter_count); |
3540 | if (named_parameter_count > 0) { |
3541 | function.SetNumOptionalParameters(named_parameter_count, false); |
3542 | } else { |
3543 | function.SetNumOptionalParameters( |
3544 | positional_parameter_count - required_parameter_count, true); |
3545 | } |
3546 | intptr_t parameter_count = extra_parameters + total_parameter_count; |
3547 | |
3548 | function.set_parameter_types( |
3549 | Array::Handle(Z, Array::New(parameter_count, Heap::kOld))); |
3550 | const Array& parameter_names = Array::Handle( |
3551 | Z, Array::New(Function::NameArrayLengthIncludingFlags(parameter_count), |
3552 | Heap::kOld)); |
3553 | function.set_parameter_names(parameter_names); |
3554 | intptr_t pos = 0; |
3555 | if (is_method) { |
3556 | ASSERT(!klass.IsNull()); |
3557 | function.SetParameterTypeAt(pos, H.GetDeclarationType(klass)); |
3558 | function.SetParameterNameAt(pos, Symbols::This()); |
3559 | pos++; |
3560 | } else if (is_closure) { |
3561 | function.SetParameterTypeAt(pos, AbstractType::dynamic_type()); |
3562 | function.SetParameterNameAt(pos, Symbols::ClosureParameter()); |
3563 | pos++; |
3564 | } else if (is_factory) { |
3565 | function.SetParameterTypeAt(pos, AbstractType::dynamic_type()); |
3566 | function.SetParameterNameAt(pos, Symbols::TypeArgumentsParameter()); |
3567 | pos++; |
3568 | } |
3569 | |
3570 | const Library& lib = Library::Handle(Z, active_class_->klass->library()); |
3571 | for (intptr_t i = 0; i < positional_parameter_count; ++i, ++pos) { |
3572 | // Read ith variable declaration. |
3573 | VariableDeclarationHelper helper(helper_); |
3574 | helper.ReadUntilExcluding(VariableDeclarationHelper::kType); |
3575 | // The required flag should only be set on named parameters. |
3576 | ASSERT(!helper.IsRequired()); |
3577 | const AbstractType& type = BuildTypeWithoutFinalization(); // read type. |
3578 | Tag tag = helper_->ReadTag(); // read (first part of) initializer. |
3579 | if (tag == kSomething) { |
3580 | helper_->SkipExpression(); // read (actual) initializer. |
3581 | } |
3582 | |
3583 | function.SetParameterTypeAt(pos, type); |
3584 | function.SetParameterNameAt(pos, H.DartIdentifier(lib, helper.name_index_)); |
3585 | } |
3586 | |
3587 | intptr_t named_parameter_count_check = |
3588 | helper_->ReadListLength(); // read list length. |
3589 | ASSERT(named_parameter_count_check == named_parameter_count); |
3590 | for (intptr_t i = 0; i < named_parameter_count; ++i, ++pos) { |
3591 | // Read ith variable declaration. |
3592 | VariableDeclarationHelper helper(helper_); |
3593 | helper.ReadUntilExcluding(VariableDeclarationHelper::kType); |
3594 | const AbstractType& type = BuildTypeWithoutFinalization(); // read type. |
3595 | Tag tag = helper_->ReadTag(); // read (first part of) initializer. |
3596 | if (tag == kSomething) { |
3597 | helper_->SkipExpression(); // read (actual) initializer. |
3598 | } |
3599 | |
3600 | function.SetParameterTypeAt(pos, type); |
3601 | function.SetParameterNameAt(pos, H.DartIdentifier(lib, helper.name_index_)); |
3602 | if (helper.IsRequired()) { |
3603 | function.SetIsRequiredAt(pos); |
3604 | } |
3605 | } |
3606 | function.TruncateUnusedParameterFlags(); |
3607 | |
3608 | function_node_helper->SetJustRead(FunctionNodeHelper::kNamedParameters); |
3609 | |
3610 | // The result type for generative constructors has already been set. |
3611 | if (!function.IsGenerativeConstructor()) { |
3612 | const AbstractType& return_type = |
3613 | BuildTypeWithoutFinalization(); // read return type. |
3614 | function.set_result_type(return_type); |
3615 | function_node_helper->SetJustRead(FunctionNodeHelper::kReturnType); |
3616 | } |
3617 | } |
3618 | |
3619 | } // namespace kernel |
3620 | } // namespace dart |
3621 | |