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
22namespace dart {
23namespace kernel {
24
25TranslationHelper::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
40TranslationHelper::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
55void 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
64void 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
77void 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
89GrowableObjectArrayPtr 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
99void 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
107GrowableObjectArrayPtr 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
116void TranslationHelper::SetStringOffsets(const TypedData& string_offsets) {
117 ASSERT(string_offsets_.IsNull());
118 string_offsets_ = string_offsets.raw();
119}
120
121void TranslationHelper::SetStringData(const ExternalTypedData& string_data) {
122 ASSERT(string_data_.IsNull());
123 string_data_ = string_data.raw();
124}
125
126void TranslationHelper::SetCanonicalNames(const TypedData& canonical_names) {
127 ASSERT(canonical_names_.IsNull());
128 canonical_names_ = canonical_names.raw();
129}
130
131void 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
138void TranslationHelper::SetMetadataMappings(
139 const ExternalTypedData& metadata_mappings) {
140 ASSERT(metadata_mappings_.IsNull());
141 metadata_mappings_ = metadata_mappings.raw();
142}
143
144void TranslationHelper::SetConstants(const Array& constants) {
145 ASSERT(constants_.IsNull() ||
146 (constants.IsNull() || constants.Length() == 0));
147 constants_ = constants.raw();
148}
149
150void TranslationHelper::SetConstantsTable(
151 const ExternalTypedData& constants_table) {
152 ASSERT(constants_table_.IsNull());
153 constants_table_ = constants_table.raw();
154}
155
156void TranslationHelper::SetKernelProgramInfo(const KernelProgramInfo& info) {
157 info_ = info.raw();
158}
159
160intptr_t TranslationHelper::StringOffset(StringIndex index) const {
161 return string_offsets_.GetUint32(index << 2);
162}
163
164intptr_t TranslationHelper::StringSize(StringIndex index) const {
165 return StringOffset(StringIndex(index + 1)) - StringOffset(index);
166}
167
168uint8_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
174uint8_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
187bool 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
196NameIndex 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
204StringIndex TranslationHelper::CanonicalNameString(NameIndex name) {
205 return StringIndex(canonical_names_.GetUint32((8 * name) + 4));
206}
207
208bool 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
214bool 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
220bool TranslationHelper::IsRoot(NameIndex name) {
221 return name == -1;
222}
223
224bool 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
229bool 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
236bool TranslationHelper::IsMember(NameIndex name) {
237 return IsConstructor(name) || IsField(name) || IsProcedure(name);
238}
239
240bool 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
254bool 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
269bool TranslationHelper::IsProcedure(NameIndex name) {
270 return IsMethod(name) || IsGetter(name) || IsSetter(name) || IsFactory(name);
271}
272
273bool 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
287bool 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
301bool 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
315bool 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
330NameIndex 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
340InstancePtr 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
351const String& TranslationHelper::DartString(const char* content,
352 Heap::Space space) {
353 return String::ZoneHandle(Z, String::New(content, space));
354}
355
356String& 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
367String& 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
373const String& TranslationHelper::DartSymbolPlain(const char* content) const {
374 return String::ZoneHandle(Z, Symbols::New(thread_, content));
375}
376
377String& 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
389const 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
399String& 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
415String& TranslationHelper::DartIdentifier(const Library& lib,
416 StringIndex string_index) {
417 String& name = DartString(string_index);
418 ManglePrivateName(lib, &name);
419 return name;
420}
421
422const 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
428const String& TranslationHelper::DartConstructorName(NameIndex constructor) {
429 ASSERT(IsConstructor(constructor));
430 return DartFactoryName(constructor);
431}
432
433const 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
446const String& TranslationHelper::DartSetterName(NameIndex setter) {
447 return DartSetterName(CanonicalNameParent(setter),
448 CanonicalNameString(setter));
449}
450
451const 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
478const String& TranslationHelper::DartGetterName(NameIndex getter) {
479 return DartGetterName(CanonicalNameParent(getter),
480 CanonicalNameString(getter));
481}
482
483const 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
491const String& TranslationHelper::DartFieldName(NameIndex field) {
492 return DartFieldName(CanonicalNameParent(field), CanonicalNameString(field));
493}
494
495const String& TranslationHelper::DartFieldName(NameIndex parent,
496 StringIndex field) {
497 String& name = DartString(field);
498 return ManglePrivateName(parent, &name);
499}
500
501const String& TranslationHelper::DartMethodName(NameIndex method) {
502 return DartMethodName(CanonicalNameParent(method),
503 CanonicalNameString(method));
504}
505
506const String& TranslationHelper::DartMethodName(NameIndex parent,
507 StringIndex method) {
508 String& name = DartString(method);
509 return ManglePrivateName(parent, &name);
510}
511
512const 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.
524static 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
536LibraryPtr 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
561ClassPtr 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
588FieldPtr 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
609FunctionPtr 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
636FunctionPtr 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
645FunctionPtr 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
655FunctionPtr 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
671FunctionPtr 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
689FunctionPtr 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
704Type& 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
719void 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
747void 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
758void 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
770void 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
783void 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
795String& 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
819String& 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
841void 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
905void 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
934void 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
976FieldHelper::FieldHelper(KernelReaderHelper* helper, intptr_t offset)
977 : helper_(helper), next_read_(kStart) {
978 helper_->SetOffset(offset);
979}
980
981void 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
1041void 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
1117void 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
1184void 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
1302void 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
1357void 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
1408void 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
1455MetadataHelper::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
1468void 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
1478void 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
1520intptr_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
1560intptr_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
1606intptr_t MetadataHelper::GetComponentMetadataPayloadOffset() {
1607 const intptr_t kComponentNodeOffset = 0;
1608 return GetNextMetadataPayloadOffset(kComponentNodeOffset -
1609 helper_->data_program_offset_);
1610}
1611
1612DirectCallMetadataHelper::DirectCallMetadataHelper(KernelReaderHelper* helper)
1613 : MetadataHelper(helper, tag(), /* precompiler_only = */ true) {}
1614
1615bool 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
1631DirectCallMetadata 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
1658DirectCallMetadata 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
1674DirectCallMetadata 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
1689InferredTypeMetadataHelper::InferredTypeMetadataHelper(
1690 KernelReaderHelper* helper,
1691 ConstantReader* constant_reader)
1692 : MetadataHelper(helper, tag(), /* precompiler_only = */ true),
1693 constant_reader_(constant_reader) {}
1694
1695InferredTypeMetadata 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
1738void 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
1753ProcedureAttributesMetadataHelper::ProcedureAttributesMetadataHelper(
1754 KernelReaderHelper* helper)
1755 : MetadataHelper(helper, tag(), /* precompiler_only = */ true) {}
1756
1757bool 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
1775ProcedureAttributesMetadata
1776ProcedureAttributesMetadataHelper::GetProcedureAttributes(
1777 intptr_t node_offset) {
1778 ProcedureAttributesMetadata metadata;
1779 ReadMetadata(node_offset, &metadata);
1780 return metadata;
1781}
1782
1783ObfuscationProhibitionsMetadataHelper::ObfuscationProhibitionsMetadataHelper(
1784 KernelReaderHelper* helper)
1785 : MetadataHelper(helper, tag(), /* precompiler_only = */ true) {}
1786
1787void 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
1805LoadingUnitsMetadataHelper::LoadingUnitsMetadataHelper(
1806 KernelReaderHelper* helper)
1807 : MetadataHelper(helper, tag(), /* precompiler_only = */ true) {}
1808
1809void 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
1856CallSiteAttributesMetadataHelper::CallSiteAttributesMetadataHelper(
1857 KernelReaderHelper* helper,
1858 TypeTranslator* type_translator)
1859 : MetadataHelper(helper, tag(), /* precompiler_only = */ false),
1860 type_translator_(*type_translator) {}
1861
1862bool 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
1877CallSiteAttributesMetadata
1878CallSiteAttributesMetadataHelper::GetCallSiteAttributes(intptr_t node_offset) {
1879 CallSiteAttributesMetadata metadata;
1880 ReadMetadata(node_offset, &metadata);
1881 return metadata;
1882}
1883
1884TableSelectorMetadataHelper::TableSelectorMetadataHelper(
1885 KernelReaderHelper* helper)
1886 : MetadataHelper(helper, tag(), /* precompiler_only = */ true) {}
1887
1888TableSelectorMetadata* 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
1908void 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
1916UnboxingInfoMetadataHelper::UnboxingInfoMetadataHelper(
1917 KernelReaderHelper* helper)
1918 : MetadataHelper(helper, tag(), /* precompiler_only = */ true) {}
1919
1920UnboxingInfoMetadata* 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
1949intptr_t KernelReaderHelper::ReaderOffset() const {
1950 return reader_.offset();
1951}
1952
1953void KernelReaderHelper::SetOffset(intptr_t offset) {
1954 reader_.set_offset(offset);
1955}
1956
1957void KernelReaderHelper::SkipBytes(intptr_t bytes) {
1958 reader_.set_offset(ReaderOffset() + bytes);
1959}
1960
1961bool KernelReaderHelper::ReadBool() {
1962 return reader_.ReadBool();
1963}
1964
1965uint8_t KernelReaderHelper::ReadByte() {
1966 return reader_.ReadByte();
1967}
1968
1969uint32_t KernelReaderHelper::ReadUInt() {
1970 return reader_.ReadUInt();
1971}
1972
1973uint32_t KernelReaderHelper::ReadUInt32() {
1974 return reader_.ReadUInt32();
1975}
1976
1977uint32_t KernelReaderHelper::PeekUInt() {
1978 AlternativeReadingScope alt(&reader_);
1979 return reader_.ReadUInt();
1980}
1981
1982double KernelReaderHelper::ReadDouble() {
1983 return reader_.ReadDouble();
1984}
1985
1986uint32_t KernelReaderHelper::PeekListLength() {
1987 AlternativeReadingScope alt(&reader_);
1988 return reader_.ReadListLength();
1989}
1990
1991intptr_t KernelReaderHelper::ReadListLength() {
1992 return reader_.ReadListLength();
1993}
1994
1995StringIndex KernelReaderHelper::ReadStringReference() {
1996 return StringIndex(ReadUInt());
1997}
1998
1999NameIndex KernelReaderHelper::ReadCanonicalNameReference() {
2000 return reader_.ReadCanonicalNameReference();
2001}
2002
2003NameIndex 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
2013StringIndex 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
2021const 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
2032const 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
2043const 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
2054const 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
2065void KernelReaderHelper::SkipFlags() {
2066 ReadFlags();
2067}
2068
2069void KernelReaderHelper::SkipStringReference() {
2070 ReadUInt();
2071}
2072
2073void KernelReaderHelper::SkipConstantReference() {
2074 ReadUInt();
2075}
2076
2077void KernelReaderHelper::SkipCanonicalNameReference() {
2078 ReadUInt();
2079}
2080
2081void KernelReaderHelper::SkipInterfaceMemberNameReference() {
2082 SkipCanonicalNameReference();
2083 SkipCanonicalNameReference();
2084}
2085
2086void KernelReaderHelper::ReportUnexpectedTag(const char* variant, Tag tag) {
2087 FATAL3("Unexpected tag %d (%s) in ?, expected %s", tag, Reader::TagName(tag),
2088 variant);
2089}
2090
2091void 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
2114void 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
2154void 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
2164void 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
2172void 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
2201void 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
2208void 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
2215void 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
2222void 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
2229void 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
2236void 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
2244void 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
2276void 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
2517void 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
2651void KernelReaderHelper::SkipFunctionNode() {
2652 FunctionNodeHelper function_node_helper(this);
2653 function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kEnd);
2654}
2655
2656void 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
2663void 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
2677void KernelReaderHelper::SkipVariableDeclaration() {
2678 VariableDeclarationHelper helper(this);
2679 helper.ReadUntilExcluding(VariableDeclarationHelper::kEnd);
2680}
2681
2682void 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
2690void 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
2702void KernelReaderHelper::SkipLibraryPart() {
2703 SkipListOfExpressions(); // Read annotations.
2704 SkipStringReference(); // Read part URI index.
2705}
2706
2707void 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
2720TokenPosition KernelReaderHelper::ReadPosition() {
2721 TokenPosition position = reader_.ReadPosition();
2722 RecordTokenPosition(position);
2723 return position;
2724}
2725
2726intptr_t KernelReaderHelper::SourceTableFieldCountFromFirstLibraryOffset() {
2727 return SourceTableFieldCountFromFirstLibraryOffset41Plus;
2728}
2729
2730intptr_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
2747intptr_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
2767String& 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
2774const 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
2787TypedDataPtr 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
2798String& 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
2818intptr_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& extracted =
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
2837ActiveTypeParametersScope::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 = &params;
2867}
2868
2869ActiveTypeParametersScope::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
2898TypeTranslator::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
2915AbstractType& 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
2923AbstractType& 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
2934void 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
2980void 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
3026void 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
3138void 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
3243const 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
3268const 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
3295void 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 = &parameterized_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
3395const 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
3410static 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
3440static 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
3465void 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
3483void 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
3507void 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 extra_parameters = (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