1// Copyright (c) 2016, 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#if !defined(DART_PRECOMPILED_RUNTIME)
5
6#include "vm/kernel_loader.h"
7
8#include <string.h>
9
10#include <memory>
11
12#include "vm/compiler/backend/flow_graph_compiler.h"
13#include "vm/compiler/frontend/constant_reader.h"
14#include "vm/compiler/frontend/kernel_translation_helper.h"
15#include "vm/dart_api_impl.h"
16#include "vm/flags.h"
17#include "vm/heap/heap.h"
18#include "vm/kernel_binary.h"
19#include "vm/longjump.h"
20#include "vm/object_store.h"
21#include "vm/parser.h"
22#include "vm/reusable_handles.h"
23#include "vm/service_isolate.h"
24#include "vm/symbols.h"
25#include "vm/thread.h"
26
27namespace dart {
28namespace kernel {
29
30#define Z (zone_)
31#define I (isolate_)
32#define T (type_translator_)
33#define H (translation_helper_)
34
35static const char* const kVMServiceIOLibraryUri = "dart:vmservice_io";
36
37class SimpleExpressionConverter {
38 public:
39 SimpleExpressionConverter(TranslationHelper* translation_helper,
40 KernelReaderHelper* reader_helper)
41 : translation_helper_(*translation_helper),
42 zone_(translation_helper_.zone()),
43 simple_value_(NULL),
44 helper_(reader_helper) {}
45
46 bool IsSimple(intptr_t kernel_offset) {
47 AlternativeReadingScope alt(&helper_->reader_, kernel_offset);
48 uint8_t payload = 0;
49 Tag tag = helper_->ReadTag(&payload); // read tag.
50 switch (tag) {
51 case kBigIntLiteral: {
52 const String& literal_str =
53 H.DartString(helper_->ReadStringReference(),
54 Heap::kOld); // read index into string table.
55 simple_value_ = &Integer::ZoneHandle(Z, Integer::New(literal_str));
56 if (simple_value_->IsNull()) {
57 H.ReportError("Integer literal %s is out of range",
58 literal_str.ToCString());
59 UNREACHABLE();
60 }
61 *simple_value_ = H.Canonicalize(*simple_value_);
62 return true;
63 }
64 case kStringLiteral:
65 simple_value_ = &H.DartSymbolPlain(
66 helper_->ReadStringReference()); // read index into string table.
67 return true;
68 case kSpecializedIntLiteral:
69 simple_value_ =
70 &Integer::ZoneHandle(Z, Integer::New(static_cast<int32_t>(payload) -
71 SpecializedIntLiteralBias,
72 Heap::kOld));
73 *simple_value_ = H.Canonicalize(*simple_value_);
74 return true;
75 case kNegativeIntLiteral:
76 simple_value_ = &Integer::ZoneHandle(
77 Z, Integer::New(-static_cast<int64_t>(helper_->ReadUInt()),
78 Heap::kOld)); // read value.
79 *simple_value_ = H.Canonicalize(*simple_value_);
80 return true;
81 case kPositiveIntLiteral:
82 simple_value_ = &Integer::ZoneHandle(
83 Z, Integer::New(static_cast<int64_t>(helper_->ReadUInt()),
84 Heap::kOld)); // read value.
85 *simple_value_ = H.Canonicalize(*simple_value_);
86 return true;
87 case kDoubleLiteral:
88 simple_value_ = &Double::ZoneHandle(
89 Z, Double::New(helper_->ReadDouble(), Heap::kOld)); // read value.
90 *simple_value_ = H.Canonicalize(*simple_value_);
91 return true;
92 case kTrueLiteral:
93 simple_value_ = &Bool::Handle(Z, Bool::Get(true).raw());
94 return true;
95 case kFalseLiteral:
96 simple_value_ = &Bool::Handle(Z, Bool::Get(false).raw());
97 return true;
98 case kNullLiteral:
99 simple_value_ = &Instance::ZoneHandle(Z, Instance::null());
100 return true;
101 default:
102 return false;
103 }
104 }
105
106 const Instance& SimpleValue() { return *simple_value_; }
107 Zone* zone() const { return zone_; }
108
109 private:
110 TranslationHelper& translation_helper_;
111 Zone* zone_;
112 Instance* simple_value_;
113 KernelReaderHelper* helper_;
114
115 DISALLOW_COPY_AND_ASSIGN(SimpleExpressionConverter);
116};
117
118ArrayPtr KernelLoader::MakeFieldsArray() {
119 const intptr_t len = fields_.length();
120 const Array& res = Array::Handle(zone_, Array::New(len, Heap::kOld));
121 for (intptr_t i = 0; i < len; i++) {
122 res.SetAt(i, *fields_[i]);
123 }
124 return res.raw();
125}
126
127ArrayPtr KernelLoader::MakeFunctionsArray() {
128 const intptr_t len = functions_.length();
129 const Array& res = Array::Handle(zone_, Array::New(len, Heap::kOld));
130 for (intptr_t i = 0; i < len; i++) {
131 res.SetAt(i, *functions_[i]);
132 }
133 return res.raw();
134}
135
136LibraryPtr BuildingTranslationHelper::LookupLibraryByKernelLibrary(
137 NameIndex library) {
138 return loader_->LookupLibrary(library);
139}
140
141ClassPtr BuildingTranslationHelper::LookupClassByKernelClass(NameIndex klass) {
142#if defined(DEBUG)
143 LibraryLookupHandleScope library_lookup_handle_scope(library_lookup_handle_);
144#endif // defined(DEBUG)
145 library_lookup_handle_ = loader_->LookupLibraryFromClass(klass);
146 return loader_->LookupClass(library_lookup_handle_, klass);
147}
148
149LibraryIndex::LibraryIndex(const ExternalTypedData& kernel_data,
150 uint32_t binary_version)
151 : reader_(kernel_data), binary_version_(binary_version) {
152 intptr_t data_size = reader_.size();
153
154 procedure_count_ = reader_.ReadUInt32At(data_size - 4);
155 procedure_index_offset_ = data_size - 4 - (procedure_count_ + 1) * 4;
156
157 class_count_ = reader_.ReadUInt32At(procedure_index_offset_ - 4);
158 class_index_offset_ = procedure_index_offset_ - 4 - (class_count_ + 1) * 4;
159
160 source_references_offset_ = -1;
161 source_references_offset_ = reader_.ReadUInt32At(class_index_offset_ - 4);
162}
163
164ClassIndex::ClassIndex(const uint8_t* buffer,
165 intptr_t buffer_size,
166 intptr_t class_offset,
167 intptr_t class_size)
168 : reader_(buffer, buffer_size) {
169 Init(class_offset, class_size);
170}
171
172ClassIndex::ClassIndex(const ExternalTypedData& library_kernel_data,
173 intptr_t class_offset,
174 intptr_t class_size)
175 : reader_(library_kernel_data) {
176 Init(class_offset, class_size);
177}
178
179void ClassIndex::Init(intptr_t class_offset, intptr_t class_size) {
180 procedure_count_ = reader_.ReadUInt32At(class_offset + class_size - 4);
181 procedure_index_offset_ =
182 class_offset + class_size - 4 - (procedure_count_ + 1) * 4;
183}
184
185using UriToSourceTable = DirectChainedHashMap<UriToSourceTableTrait>;
186
187KernelLoader::KernelLoader(Program* program,
188 UriToSourceTable* uri_to_source_table)
189 : program_(program),
190 thread_(Thread::Current()),
191 zone_(thread_->zone()),
192 isolate_(thread_->isolate()),
193 patch_classes_(Array::ZoneHandle(zone_)),
194 active_class_(),
195 library_kernel_offset_(-1), // Set to the correct value in LoadLibrary
196 kernel_binary_version_(program->binary_version()),
197 correction_offset_(-1), // Set to the correct value in LoadLibrary
198 loading_native_wrappers_library_(false),
199 library_kernel_data_(ExternalTypedData::ZoneHandle(zone_)),
200 kernel_program_info_(KernelProgramInfo::ZoneHandle(zone_)),
201 translation_helper_(this, thread_, Heap::kOld),
202 helper_(zone_,
203 &translation_helper_,
204 program_->kernel_data(),
205 program_->kernel_data_size(),
206 0),
207 constant_reader_(&helper_, &active_class_),
208 type_translator_(&helper_,
209 &constant_reader_,
210 &active_class_,
211 /* finalize= */ false),
212 inferred_type_metadata_helper_(&helper_, &constant_reader_),
213 bytecode_metadata_helper_(&helper_, &active_class_),
214 external_name_class_(Class::Handle(Z)),
215 external_name_field_(Field::Handle(Z)),
216 potential_natives_(GrowableObjectArray::Handle(Z)),
217 potential_pragma_functions_(GrowableObjectArray::Handle(Z)),
218 pragma_class_(Class::Handle(Z)),
219 name_index_handle_(Smi::Handle(Z)),
220 expression_evaluation_library_(Library::Handle(Z)) {
221 if (!program->is_single_program()) {
222 FATAL(
223 "Trying to load a concatenated dill file at a time where that is "
224 "not allowed");
225 }
226 InitializeFields(uri_to_source_table);
227}
228
229void KernelLoader::ReadObfuscationProhibitions() {
230 ObfuscationProhibitionsMetadataHelper helper(&helper_);
231 helper.ReadProhibitions();
232}
233
234void KernelLoader::ReadLoadingUnits() {
235 LoadingUnitsMetadataHelper helper(&helper_);
236 helper.ReadLoadingUnits();
237}
238
239Object& KernelLoader::LoadEntireProgram(Program* program,
240 bool process_pending_classes) {
241 Thread* thread = Thread::Current();
242 TIMELINE_DURATION(thread, Isolate, "LoadKernel");
243
244 if (program->is_single_program()) {
245 KernelLoader loader(program, /*uri_to_source_table=*/nullptr);
246 return Object::Handle(loader.LoadProgram(process_pending_classes));
247 }
248
249 kernel::Reader reader(program->kernel_data(), program->kernel_data_size());
250 GrowableArray<intptr_t> subprogram_file_starts;
251 index_programs(&reader, &subprogram_file_starts);
252
253 Zone* zone = thread->zone();
254 Library& library = Library::Handle(zone);
255 intptr_t subprogram_count = subprogram_file_starts.length() - 1;
256
257 // First index all source tables.
258 UriToSourceTable uri_to_source_table;
259 UriToSourceTableEntry wrapper;
260 for (intptr_t i = subprogram_count - 1; i >= 0; --i) {
261 intptr_t subprogram_start = subprogram_file_starts.At(i);
262 intptr_t subprogram_end = subprogram_file_starts.At(i + 1);
263 Thread* thread_ = Thread::Current();
264 Zone* zone_ = thread_->zone();
265 TranslationHelper translation_helper(thread);
266 KernelReaderHelper helper_(zone_, &translation_helper,
267 program->kernel_data() + subprogram_start,
268 subprogram_end - subprogram_start, 0);
269 const intptr_t source_table_size = helper_.SourceTableSize();
270 for (intptr_t index = 0; index < source_table_size; ++index) {
271 const String& uri_string = helper_.SourceTableUriFor(index);
272 wrapper.uri = &uri_string;
273 TypedData& line_starts =
274 TypedData::Handle(Z, helper_.GetLineStartsFor(index));
275 if (line_starts.Length() == 0) continue;
276 const String& script_source = helper_.GetSourceFor(index);
277 wrapper.uri = &uri_string;
278 UriToSourceTableEntry* pair = uri_to_source_table.LookupValue(&wrapper);
279 if (pair != NULL) {
280 // At least two entries with content. Unless the content is the same
281 // that's not valid.
282 const bool src_differ = pair->sources->CompareTo(script_source) != 0;
283 const bool line_starts_differ =
284 !pair->line_starts->CanonicalizeEquals(line_starts);
285 if (src_differ || line_starts_differ) {
286 FATAL3(
287 "Invalid kernel binary: Contains at least two source entries "
288 "that do not agree. URI '%s', difference: %s. Subprogram count: "
289 "%" Pd ".",
290 uri_string.ToCString(),
291 src_differ && line_starts_differ
292 ? "src and line starts"
293 : (src_differ ? "src" : "line starts"),
294 subprogram_count);
295 }
296 } else {
297 UriToSourceTableEntry* tmp = new UriToSourceTableEntry();
298 tmp->uri = &uri_string;
299 tmp->sources = &script_source;
300 tmp->line_starts = &line_starts;
301 uri_to_source_table.Insert(tmp);
302 }
303 }
304 }
305
306 // Create "fake programs" for each sub-program.
307 for (intptr_t i = subprogram_count - 1; i >= 0; --i) {
308 intptr_t subprogram_start = subprogram_file_starts.At(i);
309 intptr_t subprogram_end = subprogram_file_starts.At(i + 1);
310 reader.set_raw_buffer(program->kernel_data() + subprogram_start);
311 reader.set_size(subprogram_end - subprogram_start);
312 reader.set_offset(0);
313 const char* error = nullptr;
314 std::unique_ptr<Program> subprogram = Program::ReadFrom(&reader, &error);
315 if (subprogram == nullptr) {
316 FATAL1("Failed to load kernel file: %s", error);
317 }
318 ASSERT(subprogram->is_single_program());
319 KernelLoader loader(subprogram.get(), &uri_to_source_table);
320 Object& load_result = Object::Handle(loader.LoadProgram(false));
321 if (load_result.IsError()) return load_result;
322
323 if (load_result.IsLibrary()) {
324 library ^= load_result.raw();
325 }
326 }
327
328 if (process_pending_classes && !ClassFinalizer::ProcessPendingClasses()) {
329 // Class finalization failed -> sticky error would be set.
330 return Error::Handle(thread->StealStickyError());
331 }
332
333 return library;
334}
335
336void KernelLoader::index_programs(
337 kernel::Reader* reader,
338 GrowableArray<intptr_t>* subprogram_file_starts) {
339 // Dill files can be concatenated (e.g. cat a.dill b.dill > c.dill), so we
340 // need to first index the (possibly combined) file.
341 // First entry becomes last entry.
342 // Last entry is for ease of calculating size of last subprogram.
343 subprogram_file_starts->Add(reader->size());
344 reader->set_offset(reader->size() - 4);
345 while (reader->offset() > 0) {
346 intptr_t size = reader->ReadUInt32();
347 intptr_t start = reader->offset() - size;
348 if (start < 0) {
349 FATAL("Invalid kernel binary: Indicated size is invalid.");
350 }
351 subprogram_file_starts->Add(start);
352 reader->set_offset(start - 4);
353 }
354 subprogram_file_starts->Reverse();
355}
356
357StringPtr KernelLoader::FindSourceForScript(const uint8_t* kernel_buffer,
358 intptr_t kernel_buffer_length,
359 const String& uri) {
360 Thread* thread = Thread::Current();
361 Zone* zone = thread->zone();
362 TranslationHelper translation_helper(thread);
363 KernelReaderHelper reader(zone, &translation_helper, kernel_buffer,
364 kernel_buffer_length, 0);
365 intptr_t source_table_size = reader.SourceTableSize();
366 for (intptr_t i = 0; i < source_table_size; ++i) {
367 const String& source_uri = reader.SourceTableUriFor(i);
368 if (source_uri.EndsWith(uri)) {
369 return reader.GetSourceFor(i).raw();
370 }
371 }
372 return String::null();
373}
374
375void KernelLoader::InitializeFields(UriToSourceTable* uri_to_source_table) {
376 const intptr_t source_table_size = helper_.SourceTableSize();
377 const Array& scripts =
378 Array::Handle(Z, Array::New(source_table_size, Heap::kOld));
379
380 // Copy the Kernel string offsets out of the binary and into the VM's heap.
381 ASSERT(program_->string_table_offset() >= 0);
382 Reader reader(program_->kernel_data(), program_->kernel_data_size());
383 reader.set_offset(program_->string_table_offset());
384 intptr_t count = reader.ReadUInt() + 1;
385 TypedData& offsets = TypedData::Handle(
386 Z, TypedData::New(kTypedDataUint32ArrayCid, count, Heap::kOld));
387 offsets.SetUint32(0, 0);
388 intptr_t end_offset = 0;
389 for (intptr_t i = 1; i < count; ++i) {
390 end_offset = reader.ReadUInt();
391 offsets.SetUint32(i << 2, end_offset);
392 }
393
394 // Create view of the string data.
395 const ExternalTypedData& data = ExternalTypedData::Handle(
396 Z,
397 reader.ExternalDataFromTo(reader.offset(), reader.offset() + end_offset));
398
399 // Create a view of the constants table. The trailing ComponentIndex is
400 // negligible in size.
401 const ExternalTypedData& constants_table = ExternalTypedData::Handle(
402 Z, reader.ExternalDataFromTo(program_->constant_table_offset(),
403 program_->kernel_data_size()));
404
405 // Copy the canonical names into the VM's heap. Encode them as unsigned, so
406 // the parent indexes are adjusted when extracted.
407 reader.set_offset(program_->name_table_offset());
408 count = reader.ReadUInt() * 2;
409 TypedData& names = TypedData::Handle(
410 Z, TypedData::New(kTypedDataUint32ArrayCid, count, Heap::kOld));
411 for (intptr_t i = 0; i < count; ++i) {
412 names.SetUint32(i << 2, reader.ReadUInt());
413 }
414
415 // Create view of metadata payloads.
416 const ExternalTypedData& metadata_payloads = ExternalTypedData::Handle(
417 Z, reader.ExternalDataFromTo(program_->metadata_payloads_offset(),
418 program_->metadata_mappings_offset()));
419 ASSERT(Utils::IsAligned(metadata_payloads.DataAddr(0), kWordSize));
420
421 // Create view of metadata mappings.
422 const ExternalTypedData& metadata_mappings = ExternalTypedData::Handle(
423 Z, reader.ExternalDataFromTo(program_->metadata_mappings_offset(),
424 program_->string_table_offset()));
425
426#if defined(DEBUG)
427 MetadataHelper::VerifyMetadataMappings(metadata_mappings);
428#endif
429
430 const Array& libraries_cache =
431 Array::Handle(Z, HashTables::New<UnorderedHashMap<SmiTraits>>(
432 program_->library_count(), Heap::kOld));
433
434 const intptr_t kClassesPerLibraryGuess = 5;
435 const Array& classes_cache = Array::Handle(
436 Z, HashTables::New<UnorderedHashMap<SmiTraits>>(
437 kClassesPerLibraryGuess * program_->library_count(), Heap::kOld));
438
439 kernel_program_info_ = KernelProgramInfo::New(
440 offsets, data, names, metadata_payloads, metadata_mappings,
441 constants_table, scripts, libraries_cache, classes_cache,
442 program_->typed_data() == nullptr ? Object::null_object()
443 : *program_->typed_data(),
444 program_->binary_version());
445
446 H.InitFromKernelProgramInfo(kernel_program_info_);
447
448 Script& script = Script::Handle(Z);
449 for (intptr_t index = 0; index < source_table_size; ++index) {
450 script = LoadScriptAt(index, uri_to_source_table);
451 scripts.SetAt(index, script);
452 }
453
454 bytecode_metadata_helper_.ReadBytecodeComponent();
455}
456
457KernelLoader::KernelLoader(const Script& script,
458 const ExternalTypedData& kernel_data,
459 intptr_t data_program_offset,
460 uint32_t kernel_binary_version)
461 : program_(NULL),
462 thread_(Thread::Current()),
463 zone_(thread_->zone()),
464 isolate_(thread_->isolate()),
465 patch_classes_(Array::ZoneHandle(zone_)),
466 library_kernel_offset_(data_program_offset),
467 kernel_binary_version_(kernel_binary_version),
468 correction_offset_(0),
469 loading_native_wrappers_library_(false),
470 library_kernel_data_(ExternalTypedData::ZoneHandle(zone_)),
471 kernel_program_info_(
472 KernelProgramInfo::ZoneHandle(zone_, script.kernel_program_info())),
473 translation_helper_(this, thread_, Heap::kOld),
474 helper_(zone_, &translation_helper_, script, kernel_data, 0),
475 constant_reader_(&helper_, &active_class_),
476 type_translator_(&helper_,
477 &constant_reader_,
478 &active_class_,
479 /* finalize= */ false),
480 inferred_type_metadata_helper_(&helper_, &constant_reader_),
481 bytecode_metadata_helper_(&helper_, &active_class_),
482 external_name_class_(Class::Handle(Z)),
483 external_name_field_(Field::Handle(Z)),
484 potential_natives_(GrowableObjectArray::Handle(Z)),
485 potential_pragma_functions_(GrowableObjectArray::Handle(Z)),
486 pragma_class_(Class::Handle(Z)),
487 name_index_handle_(Smi::Handle(Z)),
488 expression_evaluation_library_(Library::Handle(Z)) {
489 ASSERT(T.active_class_ == &active_class_);
490 T.finalize_ = false;
491 library_kernel_data_ = kernel_data.raw();
492 H.InitFromKernelProgramInfo(kernel_program_info_);
493}
494
495void KernelLoader::EvaluateDelayedPragmas() {
496 potential_pragma_functions_ =
497 kernel_program_info_.potential_pragma_functions();
498 if (potential_pragma_functions_.IsNull()) return;
499
500 Thread* thread = Thread::Current();
501 NoOOBMessageScope no_msg_scope(thread);
502 NoReloadScope no_reload_scope(thread->isolate(), thread);
503
504 Function& function = Function::Handle();
505 Library& library = Library::Handle();
506 Class& klass = Class::Handle();
507 for (int i = 0; i < potential_pragma_functions_.Length(); ++i) {
508 function ^= potential_pragma_functions_.At(i);
509 klass = function.Owner();
510 library = klass.library();
511 library.GetMetadata(function);
512 }
513
514 potential_pragma_functions_ = GrowableObjectArray::null();
515 kernel_program_info_.set_potential_pragma_functions(
516 GrowableObjectArray::Handle(Z));
517}
518
519void KernelLoader::AnnotateNativeProcedures() {
520 potential_natives_ = kernel_program_info_.potential_natives();
521 const intptr_t length =
522 !potential_natives_.IsNull() ? potential_natives_.Length() : 0;
523 if (length == 0) return;
524
525 // Prepare lazy constant reading.
526 ConstantReader constant_reader(&helper_, &active_class_);
527
528 // Obtain `dart:_internal::ExternalName.name`.
529 EnsureExternalClassIsLookedUp();
530 Instance& constant = Instance::Handle(Z);
531 String& native_name = String::Handle(Z);
532
533 // Start scanning all candidates in [potential_natives] for the annotation
534 // constant. If the annotation is found, flag the [Function] as native and
535 // attach the native name to it.
536 Function& function = Function::Handle(Z);
537 for (intptr_t i = 0; i < length; ++i) {
538 function ^= potential_natives_.At(i);
539 helper_.SetOffset(function.KernelDataProgramOffset() +
540 function.kernel_offset());
541 {
542 ProcedureHelper procedure_helper(&helper_);
543 procedure_helper.ReadUntilExcluding(ProcedureHelper::kAnnotations);
544 }
545
546 const intptr_t annotation_count = helper_.ReadListLength();
547 for (intptr_t j = 0; j < annotation_count; ++j) {
548 const intptr_t tag = helper_.PeekTag();
549 if (tag == kConstantExpression) {
550 helper_.ReadByte(); // Skip the tag.
551 helper_.ReadPosition(); // Skip fileOffset.
552 helper_.SkipDartType(); // Skip type.
553
554 // We have a candidate. Let's look if it's an instance of the
555 // ExternalName class.
556 const intptr_t constant_table_offset = helper_.ReadUInt();
557 if (constant_reader.IsInstanceConstant(constant_table_offset,
558 external_name_class_)) {
559 constant = constant_reader.ReadConstant(constant_table_offset);
560 ASSERT(constant.clazz() == external_name_class_.raw());
561 // We found the annotation, let's flag the function as native and
562 // set the native name!
563 native_name ^= constant.GetField(external_name_field_);
564 function.set_is_native(true);
565 function.set_native_name(native_name);
566 function.set_is_external(false);
567 break;
568 }
569 } else {
570 helper_.SkipExpression();
571 }
572 }
573 }
574
575 // Clear out the list of [Function] objects which might need their native
576 // name to be set after reading the constant table from the kernel blob.
577 potential_natives_ = GrowableObjectArray::null();
578 kernel_program_info_.set_potential_natives(potential_natives_);
579}
580
581StringPtr KernelLoader::DetectExternalNameCtor() {
582 helper_.ReadTag();
583 helper_.ReadPosition();
584 NameIndex annotation_class = H.EnclosingName(
585 helper_.ReadCanonicalNameReference()); // read target reference,
586
587 if (!IsClassName(annotation_class, Symbols::DartInternal(),
588 Symbols::ExternalName())) {
589 helper_.SkipArguments();
590 return String::null();
591 }
592
593 // Read arguments:
594 intptr_t total_arguments = helper_.ReadUInt(); // read argument count.
595 helper_.SkipListOfDartTypes(); // read list of types.
596 intptr_t positional_arguments = helper_.ReadListLength();
597 ASSERT(total_arguments == 1 && positional_arguments == 1);
598
599 Tag tag = helper_.ReadTag();
600 ASSERT(tag == kStringLiteral);
601 String& result = H.DartSymbolPlain(
602 helper_.ReadStringReference()); // read index into string table.
603
604 // List of named.
605 intptr_t list_length = helper_.ReadListLength(); // read list length.
606 ASSERT(list_length == 0);
607
608 return result.raw();
609}
610
611bool KernelLoader::IsClassName(NameIndex name,
612 const String& library,
613 const String& klass) {
614 ASSERT(H.IsClass(name));
615 StringIndex class_name_index = H.CanonicalNameString(name);
616
617 if (!H.StringEquals(class_name_index, klass.ToCString())) {
618 return false;
619 }
620 ASSERT(H.IsLibrary(H.CanonicalNameParent(name)));
621 StringIndex library_name_index =
622 H.CanonicalNameString(H.CanonicalNameParent(name));
623 return H.StringEquals(library_name_index, library.ToCString());
624}
625
626bool KernelLoader::DetectPragmaCtor() {
627 helper_.ReadTag();
628 helper_.ReadPosition();
629 NameIndex annotation_class = H.EnclosingName(
630 helper_.ReadCanonicalNameReference()); // read target reference
631 helper_.SkipArguments();
632 return IsClassName(annotation_class, Symbols::DartCore(), Symbols::Pragma());
633}
634
635void KernelLoader::LoadNativeExtensionLibraries() {
636 const auto& potential_extension_libraries =
637 GrowableObjectArray::Handle(Z, H.GetPotentialExtensionLibraries());
638 if (potential_extension_libraries.IsNull()) {
639 return;
640 }
641
642 // Prepare lazy constant reading.
643 ConstantReader constant_reader(&helper_, &active_class_);
644
645 // Obtain `dart:_internal::ExternalName.name`.
646 EnsureExternalClassIsLookedUp();
647
648 Instance& constant = Instance::Handle(Z);
649 String& uri_path = String::Handle(Z);
650 Library& library = Library::Handle(Z);
651
652 const intptr_t length = potential_extension_libraries.Length();
653 for (intptr_t i = 0; i < length; ++i) {
654 library ^= potential_extension_libraries.At(i);
655
656 if (library.is_declared_in_bytecode()) {
657 const auto& imports = Array::Handle(Z, library.imports());
658 auto& ns = Namespace::Handle(Z);
659 auto& importee = Library::Handle(Z);
660 for (intptr_t j = 0; j < imports.Length(); ++j) {
661 ns ^= imports.At(j);
662 if (ns.IsNull()) continue;
663 importee = ns.library();
664 uri_path = importee.url();
665 if (uri_path.StartsWith(Symbols::DartExtensionScheme())) {
666 LoadNativeExtension(library, uri_path);
667 }
668 }
669 } else {
670 helper_.SetOffset(library.kernel_offset());
671
672 LibraryHelper library_helper(&helper_, kernel_binary_version_);
673 library_helper.ReadUntilExcluding(LibraryHelper::kAnnotations);
674
675 const intptr_t annotation_count = helper_.ReadListLength();
676 for (intptr_t j = 0; j < annotation_count; ++j) {
677 uri_path = String::null();
678
679 const intptr_t tag = helper_.PeekTag();
680 if (tag == kConstantExpression) {
681 helper_.ReadByte(); // Skip the tag.
682 helper_.ReadPosition(); // Skip fileOffset.
683 helper_.SkipDartType(); // Skip type.
684
685 // We have a candidate. Let's look if it's an instance of the
686 // ExternalName class.
687 const intptr_t constant_table_offset = helper_.ReadUInt();
688 if (constant_reader.IsInstanceConstant(constant_table_offset,
689 external_name_class_)) {
690 constant = constant_reader.ReadConstant(constant_table_offset);
691 ASSERT(constant.clazz() == external_name_class_.raw());
692 uri_path ^= constant.GetField(external_name_field_);
693 }
694 } else if (tag == kConstructorInvocation ||
695 tag == kConstConstructorInvocation) {
696 uri_path = DetectExternalNameCtor();
697 } else {
698 helper_.SkipExpression();
699 }
700
701 if (uri_path.IsNull()) continue;
702
703 LoadNativeExtension(library, uri_path);
704
705 // Create a dummy library and add it as an import to the current
706 // library. This allows later to discover and reload this native
707 // extension, e.g. when running from an app-jit snapshot.
708 // See Loader::ReloadNativeExtensions(...) which relies on
709 // Dart_GetImportsOfScheme('dart-ext').
710 const auto& native_library = Library::Handle(Library::New(uri_path));
711 library.AddImport(Namespace::Handle(Namespace::New(
712 native_library, Array::null_array(), Array::null_array())));
713 }
714 }
715 }
716}
717
718void KernelLoader::LoadNativeExtension(const Library& library,
719 const String& uri_path) {
720#if !defined(DART_PRECOMPILER)
721 if (!I->HasTagHandler()) {
722 H.ReportError("no library handler registered.");
723 }
724
725 I->BlockClassFinalization();
726 const auto& result = Object::Handle(
727 Z, I->CallTagHandler(Dart_kImportExtensionTag, library, uri_path));
728 I->UnblockClassFinalization();
729
730 if (result.IsError()) {
731 H.ReportError(Error::Cast(result), "library handler failed");
732 }
733#endif
734}
735
736ObjectPtr KernelLoader::LoadProgram(bool process_pending_classes) {
737 ASSERT(kernel_program_info_.constants() == Array::null());
738
739 if (!program_->is_single_program()) {
740 FATAL(
741 "Trying to load a concatenated dill file at a time where that is "
742 "not allowed");
743 }
744
745 LongJumpScope jump;
746 if (setjmp(*jump.Set()) == 0) {
747 if (!bytecode_metadata_helper_.ReadLibraries()) {
748 // Note that `problemsAsJson` on Component is implicitly skipped.
749 const intptr_t length = program_->library_count();
750 for (intptr_t i = 0; i < length; i++) {
751 LoadLibrary(i);
752 }
753 }
754
755 // Finalize still pending classes if requested.
756 if (process_pending_classes) {
757 if (!ClassFinalizer::ProcessPendingClasses()) {
758 // Class finalization failed -> sticky error would be set.
759 return H.thread()->StealStickyError();
760 }
761 }
762
763 // Sets the constants array to an empty hash and leaves the constant
764 // table's raw bytes in place for lazy reading. We can fix up all
765 // "pending" processing now, and must ensure we don't create new
766 // ones from this point on.
767 ASSERT(kernel_program_info_.constants_table() != ExternalTypedData::null());
768 const Array& array =
769 Array::Handle(Z, HashTables::New<KernelConstantsMap>(16, Heap::kOld));
770 kernel_program_info_.set_constants(array);
771 H.SetConstants(array); // for caching
772 AnnotateNativeProcedures();
773 LoadNativeExtensionLibraries();
774 EvaluateDelayedPragmas();
775
776 NameIndex main = program_->main_method();
777 if (main != -1) {
778 NameIndex main_library = H.EnclosingName(main);
779 return LookupLibrary(main_library);
780 }
781
782 return bytecode_metadata_helper_.GetMainLibrary();
783 }
784
785 // Either class finalization failed or we caught a compile error.
786 // In both cases sticky error would be set.
787 return Thread::Current()->StealStickyError();
788}
789
790void KernelLoader::LoadLibrary(const Library& library) {
791 ASSERT(!library.Loaded());
792
793 bytecode_metadata_helper_.ReadLibrary(library);
794 if (library.Loaded()) {
795 return;
796 }
797 const auto& uri = String::Handle(Z, library.url());
798 const intptr_t num_libraries = program_->library_count();
799 for (intptr_t i = 0; i < num_libraries; ++i) {
800 const String& library_uri = LibraryUri(i);
801 if (library_uri.Equals(uri)) {
802 LoadLibrary(i);
803 return;
804 }
805 }
806}
807
808ObjectPtr KernelLoader::LoadExpressionEvaluationFunction(
809 const String& library_url,
810 const String& klass) {
811 // Find the original context, i.e. library/class, in which the evaluation will
812 // happen.
813 const Library& real_library =
814 Library::Handle(Z, Library::LookupLibrary(thread_, library_url));
815 ASSERT(!real_library.IsNull());
816 const Class& real_class = Class::Handle(
817 Z, klass.IsNull() ? real_library.toplevel_class()
818 : real_library.LookupClassAllowPrivate(klass));
819 ASSERT(!real_class.IsNull());
820
821 const intptr_t num_cids = I->class_table()->NumCids();
822 const intptr_t num_libs =
823 GrowableObjectArray::Handle(I->object_store()->libraries()).Length();
824
825 // Load the "evaluate:source" expression evaluation library.
826 ASSERT(expression_evaluation_library_.IsNull());
827 ASSERT(H.GetExpressionEvaluationFunction().IsNull());
828 H.SetExpressionEvaluationRealClass(real_class);
829 const Object& result = Object::Handle(Z, LoadProgram(true));
830 if (result.IsError()) {
831 return result.raw();
832 }
833 const Function& function = H.GetExpressionEvaluationFunction();
834 ASSERT(!function.IsNull());
835 ASSERT(GrowableObjectArray::Handle(I->object_store()->libraries()).Length() ==
836 num_libs);
837 ASSERT(I->class_table()->NumCids() == num_cids);
838
839 // Make the expression evaluation function have the right script,
840 // kernel data and parent.
841 const auto& eval_script = Script::Handle(Z, function.script());
842 auto& kernel_data = ExternalTypedData::Handle(Z);
843 intptr_t kernel_offset = -1;
844 if (!function.is_declared_in_bytecode()) {
845 ASSERT(!expression_evaluation_library_.IsNull());
846 kernel_data = expression_evaluation_library_.kernel_data();
847 kernel_offset = expression_evaluation_library_.kernel_offset();
848 }
849 function.SetKernelDataAndScript(eval_script, kernel_data, kernel_offset);
850
851 function.set_owner(real_class);
852
853 return function.raw();
854}
855
856void KernelLoader::FindModifiedLibraries(Program* program,
857 Isolate* isolate,
858 BitVector* modified_libs,
859 bool force_reload,
860 bool* is_empty_program,
861 intptr_t* p_num_classes,
862 intptr_t* p_num_procedures) {
863 LongJumpScope jump;
864 Zone* zone = Thread::Current()->zone();
865 if (setjmp(*jump.Set()) == 0) {
866 if (force_reload) {
867 // If a reload is being forced we mark all libraries as having
868 // been modified.
869 const GrowableObjectArray& libs =
870 GrowableObjectArray::Handle(isolate->object_store()->libraries());
871 intptr_t num_libs = libs.Length();
872 Library& lib = dart::Library::Handle(zone);
873 for (intptr_t i = 0; i < num_libs; i++) {
874 lib ^= libs.At(i);
875 if (!lib.is_dart_scheme()) {
876 modified_libs->Add(lib.index());
877 }
878 }
879 return;
880 }
881
882 if (p_num_classes != nullptr) {
883 *p_num_classes = 0;
884 }
885 if (p_num_procedures != nullptr) {
886 *p_num_procedures = 0;
887 }
888
889 // Now go through all the libraries that are present in the incremental
890 // kernel files, these will constitute the modified libraries.
891 *is_empty_program = true;
892 if (program->is_single_program()) {
893 KernelLoader loader(program, /*uri_to_source_table=*/nullptr);
894 loader.walk_incremental_kernel(modified_libs, is_empty_program,
895 p_num_classes, p_num_procedures);
896 }
897 kernel::Reader reader(program->kernel_data(), program->kernel_data_size());
898 GrowableArray<intptr_t> subprogram_file_starts;
899 index_programs(&reader, &subprogram_file_starts);
900
901 // Create "fake programs" for each sub-program.
902 intptr_t subprogram_count = subprogram_file_starts.length() - 1;
903 for (intptr_t i = 0; i < subprogram_count; ++i) {
904 intptr_t subprogram_start = subprogram_file_starts.At(i);
905 intptr_t subprogram_end = subprogram_file_starts.At(i + 1);
906 reader.set_raw_buffer(program->kernel_data() + subprogram_start);
907 reader.set_size(subprogram_end - subprogram_start);
908 reader.set_offset(0);
909 const char* error = nullptr;
910 std::unique_ptr<Program> subprogram = Program::ReadFrom(&reader, &error);
911 if (subprogram == nullptr) {
912 FATAL1("Failed to load kernel file: %s", error);
913 }
914 ASSERT(subprogram->is_single_program());
915 KernelLoader loader(subprogram.get(), /*uri_to_source_table=*/nullptr);
916 loader.walk_incremental_kernel(modified_libs, is_empty_program,
917 p_num_classes, p_num_procedures);
918 }
919 }
920}
921
922void KernelLoader::walk_incremental_kernel(BitVector* modified_libs,
923 bool* is_empty_program,
924 intptr_t* p_num_classes,
925 intptr_t* p_num_procedures) {
926 if (bytecode_metadata_helper_.FindModifiedLibrariesForHotReload(
927 modified_libs, is_empty_program, p_num_classes, p_num_procedures)) {
928 return;
929 }
930 intptr_t length = program_->library_count();
931 *is_empty_program = *is_empty_program && (length == 0);
932 bool collect_library_stats =
933 p_num_classes != nullptr || p_num_procedures != nullptr;
934 intptr_t num_classes = 0;
935 intptr_t num_procedures = 0;
936 Library& lib = Library::Handle(Z);
937 for (intptr_t i = 0; i < length; i++) {
938 intptr_t kernel_offset = library_offset(i);
939 helper_.SetOffset(kernel_offset);
940 LibraryHelper library_helper(&helper_, kernel_binary_version_);
941 library_helper.ReadUntilIncluding(LibraryHelper::kCanonicalName);
942 lib = LookupLibraryOrNull(library_helper.canonical_name_);
943 if (!lib.IsNull() && !lib.is_dart_scheme()) {
944 // This is a library that already exists so mark it as being modified.
945 modified_libs->Add(lib.index());
946 }
947 if (collect_library_stats) {
948 intptr_t library_end = library_offset(i + 1);
949 library_kernel_data_ =
950 helper_.reader_.ExternalDataFromTo(kernel_offset, library_end);
951 LibraryIndex library_index(library_kernel_data_, kernel_binary_version_);
952 num_classes += library_index.class_count();
953 num_procedures += library_index.procedure_count();
954 }
955 }
956 if (p_num_classes != nullptr) {
957 *p_num_classes += num_classes;
958 }
959 if (p_num_procedures != nullptr) {
960 *p_num_procedures += num_procedures;
961 }
962}
963
964void KernelLoader::ReadInferredType(const Field& field,
965 intptr_t kernel_offset) {
966 const InferredTypeMetadata type =
967 inferred_type_metadata_helper_.GetInferredType(kernel_offset,
968 /*read_constant=*/false);
969 if (type.IsTrivial()) {
970 return;
971 }
972 field.set_guarded_cid(type.cid);
973 field.set_is_nullable(type.IsNullable());
974 field.set_guarded_list_length(Field::kNoFixedLength);
975 if (FLAG_precompiled_mode) {
976 field.set_is_unboxing_candidate(
977 !field.is_late() && !field.is_static() &&
978 ((field.guarded_cid() == kDoubleCid &&
979 FlowGraphCompiler::SupportsUnboxedDoubles()) ||
980 (field.guarded_cid() == kFloat32x4Cid &&
981 FlowGraphCompiler::SupportsUnboxedSimd128()) ||
982 (field.guarded_cid() == kFloat64x2Cid &&
983 FlowGraphCompiler::SupportsUnboxedSimd128()) ||
984 type.IsInt()) &&
985 !field.is_nullable());
986 field.set_is_non_nullable_integer(!field.is_nullable() && type.IsInt());
987 }
988}
989
990void KernelLoader::CheckForInitializer(const Field& field) {
991 if (helper_.PeekTag() == kSomething) {
992 field.set_has_initializer(true);
993 SimpleExpressionConverter converter(&H, &helper_);
994 const bool has_simple_initializer =
995 converter.IsSimple(helper_.ReaderOffset() + 1);
996 if (!has_simple_initializer || !converter.SimpleValue().IsNull()) {
997 field.set_has_nontrivial_initializer(true);
998 return;
999 }
1000 }
1001 field.set_has_initializer(false);
1002 field.set_has_nontrivial_initializer(false);
1003}
1004
1005LibraryPtr KernelLoader::LoadLibrary(intptr_t index) {
1006 if (!program_->is_single_program()) {
1007 FATAL(
1008 "Trying to load a concatenated dill file at a time where that is "
1009 "not allowed");
1010 }
1011
1012 // Read library index.
1013 library_kernel_offset_ = library_offset(index);
1014 correction_offset_ = library_kernel_offset_;
1015 intptr_t library_end = library_offset(index + 1);
1016 intptr_t library_size = library_end - library_kernel_offset_;
1017
1018 // NOTE: Since |helper_| is used to load the overall kernel program,
1019 // it's reader's offset is an offset into the overall kernel program.
1020 // Hence, when setting the kernel offsets of field and functions, one
1021 // has to subtract the library's kernel offset from the reader's
1022 // offset.
1023 helper_.SetOffset(library_kernel_offset_);
1024
1025 LibraryHelper library_helper(&helper_, kernel_binary_version_);
1026 library_helper.ReadUntilIncluding(LibraryHelper::kCanonicalName);
1027 if (!FLAG_precompiled_mode && !I->should_load_vmservice()) {
1028 StringIndex lib_name_index =
1029 H.CanonicalNameString(library_helper.canonical_name_);
1030 if (H.StringEquals(lib_name_index, kVMServiceIOLibraryUri)) {
1031 // We are not the service isolate and we are not generating an AOT
1032 // snapshot so we skip loading 'dart:vmservice_io'.
1033 skip_vmservice_library_ = library_helper.canonical_name_;
1034 ASSERT(H.IsLibrary(skip_vmservice_library_));
1035 return Library::null();
1036 }
1037 }
1038
1039 Library& library =
1040 Library::Handle(Z, LookupLibrary(library_helper.canonical_name_));
1041
1042 // The Kernel library is external implies that it is already loaded.
1043 ASSERT(!library_helper.IsExternal() || library.Loaded());
1044 if (library.Loaded()) return library.raw();
1045
1046 library.set_is_nnbd(library_helper.IsNonNullableByDefault());
1047 const NNBDCompiledMode mode =
1048 library_helper.GetNonNullableByDefaultCompiledMode();
1049 if (!I->null_safety() && mode == NNBDCompiledMode::kStrong) {
1050 H.ReportError(
1051 "Library '%s' was compiled with sound null safety (in strong mode) and "
1052 "it "
1053 "requires --sound-null-safety option at runtime",
1054 String::Handle(library.url()).ToCString());
1055 }
1056 if (I->null_safety() && (mode == NNBDCompiledMode::kWeak ||
1057 mode == NNBDCompiledMode::kDisabled)) {
1058 H.ReportError(
1059 "Library '%s' was compiled without sound null safety (in weak mode) "
1060 "and it "
1061 "cannot be used with --sound-null-safety at runtime",
1062 String::Handle(library.url()).ToCString());
1063 }
1064 library.set_nnbd_compiled_mode(mode);
1065
1066 library_kernel_data_ = helper_.reader_.ExternalDataFromTo(
1067 library_kernel_offset_, library_kernel_offset_ + library_size);
1068 library.set_kernel_data(library_kernel_data_);
1069 library.set_kernel_offset(library_kernel_offset_);
1070
1071 LibraryIndex library_index(library_kernel_data_, kernel_binary_version_);
1072 intptr_t class_count = library_index.class_count();
1073
1074 library_helper.ReadUntilIncluding(LibraryHelper::kName);
1075 library.SetName(H.DartSymbolObfuscate(library_helper.name_index_));
1076
1077 // The bootstrapper will take care of creating the native wrapper classes, but
1078 // we will add the synthetic constructors to them here.
1079 if (library.name() ==
1080 Symbols::Symbol(Symbols::kDartNativeWrappersLibNameId).raw()) {
1081 ASSERT(library.LoadInProgress());
1082 loading_native_wrappers_library_ = true;
1083 } else {
1084 loading_native_wrappers_library_ = false;
1085 library.SetLoadInProgress();
1086 }
1087
1088 library_helper.ReadUntilIncluding(LibraryHelper::kSourceUriIndex);
1089 const Script& script =
1090 Script::Handle(Z, ScriptAt(library_helper.source_uri_index_));
1091
1092 library_helper.ReadUntilExcluding(LibraryHelper::kAnnotations);
1093 intptr_t annotations_kernel_offset =
1094 helper_.ReaderOffset() - correction_offset_;
1095 intptr_t annotation_count = helper_.ReadListLength(); // read list length.
1096 if (annotation_count > 0) {
1097 // This must wait until we can evaluate constants.
1098 // So put on the "pending" list.
1099 H.AddPotentialExtensionLibrary(library);
1100 }
1101 for (intptr_t i = 0; i < annotation_count; ++i) {
1102 helper_.SkipExpression(); // read ith annotation.
1103 }
1104 library_helper.SetJustRead(LibraryHelper::kAnnotations);
1105
1106 // Setup toplevel class (which contains library fields/procedures).
1107
1108 // We do not register expression evaluation classes with the VM:
1109 // The expression evaluation functions should be GC-able as soon as
1110 // they are not reachable anymore and we never look them up by name.
1111 const bool register_class =
1112 library.raw() != expression_evaluation_library_.raw();
1113
1114 Class& toplevel_class =
1115 Class::Handle(Z, Class::New(library, Symbols::TopLevel(), script,
1116 TokenPosition::kNoSource, register_class));
1117 toplevel_class.set_is_abstract();
1118 toplevel_class.set_is_declaration_loaded();
1119 toplevel_class.set_is_type_finalized();
1120 library.set_toplevel_class(toplevel_class);
1121
1122 library_helper.ReadUntilExcluding(LibraryHelper::kDependencies);
1123 LoadLibraryImportsAndExports(&library, toplevel_class);
1124 library_helper.SetJustRead(LibraryHelper::kDependencies);
1125
1126 // Everything up til the classes are skipped implicitly, and library_helper
1127 // is no longer used.
1128
1129 const GrowableObjectArray& classes =
1130 GrowableObjectArray::Handle(Z, I->object_store()->pending_classes());
1131
1132 // Load all classes.
1133 intptr_t next_class_offset = library_index.ClassOffset(0);
1134 Class& klass = Class::Handle(Z);
1135 for (intptr_t i = 0; i < class_count; ++i) {
1136 helper_.SetOffset(next_class_offset);
1137 next_class_offset = library_index.ClassOffset(i + 1);
1138 LoadClass(library, toplevel_class, next_class_offset, &klass);
1139 if (register_class) {
1140 classes.Add(klass, Heap::kOld);
1141 }
1142 }
1143
1144 if (loading_native_wrappers_library_ || !register_class) {
1145 FinishTopLevelClassLoading(toplevel_class, library, library_index);
1146 }
1147
1148 if (FLAG_enable_mirrors && annotation_count > 0) {
1149 ASSERT(annotations_kernel_offset > 0);
1150 library.AddLibraryMetadata(toplevel_class, TokenPosition::kNoSource,
1151 annotations_kernel_offset, 0);
1152 }
1153
1154 if (register_class) {
1155 helper_.SetOffset(library_index.SourceReferencesOffset());
1156 intptr_t count = helper_.ReadUInt();
1157 const GrowableObjectArray& used_scripts =
1158 GrowableObjectArray::Handle(library.used_scripts());
1159 Script& script = Script::Handle(Z);
1160 for (intptr_t i = 0; i < count; i++) {
1161 intptr_t uri_index = helper_.ReadUInt();
1162 script = ScriptAt(uri_index);
1163 used_scripts.Add(script);
1164 }
1165 }
1166 if (!library.Loaded()) library.SetLoaded();
1167
1168 return library.raw();
1169}
1170
1171void KernelLoader::FinishTopLevelClassLoading(
1172 const Class& toplevel_class,
1173 const Library& library,
1174 const LibraryIndex& library_index) {
1175 if (toplevel_class.is_loaded()) {
1176 return;
1177 }
1178 TIMELINE_DURATION(Thread::Current(), Isolate, "FinishTopLevelClassLoading");
1179
1180 ActiveClassScope active_class_scope(&active_class_, &toplevel_class);
1181
1182 // Offsets within library index are whole program offsets and not
1183 // relative to the library.
1184 const intptr_t correction = correction_offset_ - library_kernel_offset_;
1185 helper_.SetOffset(library_index.ClassOffset(library_index.class_count()) +
1186 correction);
1187
1188 if (kernel_binary_version_ >= 30) {
1189 const intptr_t extension_count = helper_.ReadListLength();
1190 for (intptr_t i = 0; i < extension_count; ++i) {
1191 helper_.ReadTag(); // read tag.
1192 helper_.SkipCanonicalNameReference(); // skip canonical name.
1193 helper_.SkipStringReference(); // skip name.
1194 helper_.ReadUInt(); // read source uri index.
1195 helper_.ReadPosition(); // read file offset.
1196 helper_.SkipTypeParametersList(); // skip type parameter list.
1197 helper_.SkipDartType(); // skip on-type.
1198
1199 const intptr_t extension_member_count = helper_.ReadListLength();
1200 for (intptr_t j = 0; j < extension_member_count; ++j) {
1201 helper_.SkipName(); // skip name.
1202 helper_.ReadByte(); // read kind.
1203 helper_.ReadByte(); // read flags.
1204 helper_.SkipCanonicalNameReference(); // skip member reference
1205 }
1206 }
1207 }
1208
1209 fields_.Clear();
1210 functions_.Clear();
1211
1212 // Load toplevel fields.
1213 const intptr_t field_count = helper_.ReadListLength(); // read list length.
1214 for (intptr_t i = 0; i < field_count; ++i) {
1215 intptr_t field_offset = helper_.ReaderOffset() - correction_offset_;
1216 ActiveMemberScope active_member_scope(&active_class_, NULL);
1217 FieldHelper field_helper(&helper_);
1218 field_helper.ReadUntilExcluding(FieldHelper::kName);
1219
1220 const String& name = helper_.ReadNameAsFieldName();
1221 field_helper.SetJustRead(FieldHelper::kName);
1222
1223 field_helper.ReadUntilExcluding(FieldHelper::kAnnotations);
1224 intptr_t annotation_count = helper_.ReadListLength();
1225 bool has_pragma_annotation;
1226 {
1227 String& native_name_unused = String::Handle();
1228 bool is_potential_native_unused;
1229 ReadVMAnnotations(library, annotation_count, &native_name_unused,
1230 &is_potential_native_unused, &has_pragma_annotation);
1231 }
1232 field_helper.SetJustRead(FieldHelper::kAnnotations);
1233
1234 field_helper.ReadUntilExcluding(FieldHelper::kType);
1235 const Object& script_class =
1236 ClassForScriptAt(toplevel_class, field_helper.source_uri_index_);
1237 // In the VM all const fields are implicitly final whereas in Kernel they
1238 // are not final because they are not explicitly declared that way.
1239 const bool is_final = field_helper.IsConst() || field_helper.IsFinal();
1240 // Only instance fields could be covariant.
1241 ASSERT(!field_helper.IsCovariant() &&
1242 !field_helper.IsGenericCovariantImpl());
1243 const bool is_late = field_helper.IsLate();
1244 const bool is_extension_member = field_helper.IsExtensionMember();
1245 const Field& field = Field::Handle(
1246 Z, Field::NewTopLevel(name, is_final, field_helper.IsConst(), is_late,
1247 script_class, field_helper.position_,
1248 field_helper.end_position_));
1249 field.set_kernel_offset(field_offset);
1250 field.set_has_pragma(has_pragma_annotation);
1251 field.set_is_extension_member(is_extension_member);
1252 const AbstractType& type = T.BuildType(); // read type.
1253 field.SetFieldType(type);
1254 ReadInferredType(field, field_offset + library_kernel_offset_);
1255 CheckForInitializer(field);
1256 // In NNBD libraries, static fields with initializers are
1257 // implicitly late.
1258 if (field.has_initializer() && library.is_nnbd()) {
1259 field.set_is_late(true);
1260 }
1261 field_helper.SetJustRead(FieldHelper::kType);
1262 field_helper.ReadUntilExcluding(FieldHelper::kInitializer);
1263 intptr_t field_initializer_offset = helper_.ReaderOffset();
1264 field_helper.ReadUntilExcluding(FieldHelper::kEnd);
1265 {
1266 // GenerateFieldAccessors reads (some of) the initializer.
1267 AlternativeReadingScope alt(&helper_.reader_, field_initializer_offset);
1268 GenerateFieldAccessors(toplevel_class, field, &field_helper);
1269 }
1270 if ((FLAG_enable_mirrors || has_pragma_annotation) &&
1271 annotation_count > 0) {
1272 library.AddFieldMetadata(field, TokenPosition::kNoSource, field_offset,
1273 0);
1274 }
1275 fields_.Add(&field);
1276 }
1277
1278 ASSERT(!toplevel_class.is_loaded());
1279
1280 // Load toplevel procedures.
1281 intptr_t next_procedure_offset =
1282 library_index.ProcedureOffset(0) + correction;
1283 const intptr_t procedure_count = library_index.procedure_count();
1284 for (intptr_t i = 0; i < procedure_count; ++i) {
1285 helper_.SetOffset(next_procedure_offset);
1286 next_procedure_offset = library_index.ProcedureOffset(i + 1) + correction;
1287 LoadProcedure(library, toplevel_class, false, next_procedure_offset);
1288 // LoadProcedure calls Library::GetMetadata which invokes Dart code
1289 // which may recursively trigger class finalization and
1290 // FinishTopLevelClassLoading.
1291 // In such case, return immediately and avoid overwriting already finalized
1292 // functions with freshly loaded and not yet finalized.
1293 if (toplevel_class.is_loaded()) {
1294 return;
1295 }
1296 }
1297
1298 toplevel_class.SetFields(Array::Handle(MakeFieldsArray()));
1299 toplevel_class.SetFunctions(Array::Handle(MakeFunctionsArray()));
1300
1301 String& name = String::Handle(Z);
1302 for (intptr_t i = 0, n = fields_.length(); i < n; ++i) {
1303 const Field* field = fields_.At(i);
1304 name = field->name();
1305 library.AddObject(*field, name);
1306 }
1307 for (intptr_t i = 0, n = functions_.length(); i < n; ++i) {
1308 const Function* function = functions_.At(i);
1309 name = function->name();
1310 library.AddObject(*function, name);
1311 }
1312
1313 ASSERT(!toplevel_class.is_loaded());
1314 toplevel_class.set_is_loaded(true);
1315}
1316
1317void KernelLoader::LoadLibraryImportsAndExports(Library* library,
1318 const Class& toplevel_class) {
1319 GrowableObjectArray& show_list = GrowableObjectArray::Handle(Z);
1320 GrowableObjectArray& hide_list = GrowableObjectArray::Handle(Z);
1321 Array& show_names = Array::Handle(Z);
1322 Array& hide_names = Array::Handle(Z);
1323 Namespace& ns = Namespace::Handle(Z);
1324 LibraryPrefix& library_prefix = LibraryPrefix::Handle(Z);
1325
1326 const intptr_t deps_count = helper_.ReadListLength();
1327 const Array& deps = Array::Handle(Array::New(deps_count));
1328 for (intptr_t dep = 0; dep < deps_count; ++dep) {
1329 LibraryDependencyHelper dependency_helper(&helper_);
1330
1331 dependency_helper.ReadUntilExcluding(LibraryDependencyHelper::kAnnotations);
1332 intptr_t annotations_kernel_offset =
1333 helper_.ReaderOffset() - correction_offset_;
1334
1335 dependency_helper.ReadUntilExcluding(LibraryDependencyHelper::kCombinators);
1336
1337 // Ignore the dependency if the target library is invalid.
1338 // The error will be caught during compilation.
1339 if (dependency_helper.target_library_canonical_name_ < 0) {
1340 const intptr_t combinator_count = helper_.ReadListLength();
1341 for (intptr_t c = 0; c < combinator_count; ++c) {
1342 helper_.SkipLibraryCombinator();
1343 }
1344 continue;
1345 }
1346
1347 // Prepare show and hide lists.
1348 show_list = GrowableObjectArray::New(Heap::kOld);
1349 hide_list = GrowableObjectArray::New(Heap::kOld);
1350 const intptr_t combinator_count = helper_.ReadListLength();
1351 for (intptr_t c = 0; c < combinator_count; ++c) {
1352 uint8_t flags = helper_.ReadFlags();
1353 intptr_t name_count = helper_.ReadListLength();
1354 for (intptr_t n = 0; n < name_count; ++n) {
1355 String& show_hide_name =
1356 H.DartSymbolObfuscate(helper_.ReadStringReference());
1357 if ((flags & LibraryDependencyHelper::Show) != 0) {
1358 show_list.Add(show_hide_name, Heap::kOld);
1359 } else {
1360 hide_list.Add(show_hide_name, Heap::kOld);
1361 }
1362 }
1363 }
1364
1365 if (show_list.Length() > 0) {
1366 show_names = Array::MakeFixedLength(show_list);
1367 } else {
1368 show_names = Array::null();
1369 }
1370
1371 if (hide_list.Length() > 0) {
1372 hide_names = Array::MakeFixedLength(hide_list);
1373 } else {
1374 hide_names = Array::null();
1375 }
1376
1377 Library& target_library = Library::Handle(
1378 Z, LookupLibrary(dependency_helper.target_library_canonical_name_));
1379 if (!FLAG_enable_mirrors &&
1380 target_library.url() == Symbols::DartMirrors().raw()) {
1381 H.ReportError(
1382 "import of dart:mirrors is not supported in the current Dart "
1383 "runtime");
1384 }
1385 if (!Api::IsFfiEnabled() &&
1386 target_library.url() == Symbols::DartFfi().raw()) {
1387 H.ReportError(
1388 "import of dart:ffi is not supported in the current Dart runtime");
1389 }
1390 String& prefix = H.DartSymbolPlain(dependency_helper.name_index_);
1391 ns = Namespace::New(target_library, show_names, hide_names);
1392 if ((dependency_helper.flags_ & LibraryDependencyHelper::Export) != 0) {
1393 library->AddExport(ns);
1394 } else {
1395 if (prefix.IsNull() || prefix.Length() == 0) {
1396 library->AddImport(ns);
1397 } else {
1398 library_prefix = library->LookupLocalLibraryPrefix(prefix);
1399 if (!library_prefix.IsNull()) {
1400 library_prefix.AddImport(ns);
1401 } else {
1402 library_prefix = LibraryPrefix::New(
1403 prefix, ns,
1404 (dependency_helper.flags_ & LibraryDependencyHelper::Deferred) !=
1405 0,
1406 *library);
1407 library->AddObject(library_prefix, prefix);
1408 }
1409 }
1410 }
1411
1412 if (FLAG_enable_mirrors && dependency_helper.annotation_count_ > 0) {
1413 ASSERT(annotations_kernel_offset > 0);
1414 ns.AddMetadata(toplevel_class, TokenPosition::kNoSource,
1415 annotations_kernel_offset);
1416 }
1417
1418 if (prefix.IsNull()) {
1419 deps.SetAt(dep, ns);
1420 } else {
1421 deps.SetAt(dep, library_prefix);
1422 }
1423 }
1424
1425 library->set_dependencies(deps);
1426}
1427
1428void KernelLoader::LoadPreliminaryClass(ClassHelper* class_helper,
1429 intptr_t type_parameter_count) {
1430 const Class* klass = active_class_.klass;
1431
1432 // Enable access to type_parameters().
1433 klass->set_is_declaration_loaded();
1434
1435 // Note: This assumes that ClassHelper is exactly at the position where
1436 // the length of the type parameters have been read, and that the order in
1437 // the binary is as follows: [...], kTypeParameters, kSuperClass, kMixinType,
1438 // kImplementedClasses, [...].
1439
1440 // Set type parameters.
1441 T.LoadAndSetupTypeParameters(&active_class_, *klass, type_parameter_count,
1442 Function::Handle(Z));
1443
1444 // Set super type. Some classes (e.g., Object) do not have one.
1445 Tag type_tag = helper_.ReadTag(); // read super class type (part 1).
1446 if (type_tag == kSomething) {
1447 AbstractType& super_type =
1448 T.BuildTypeWithoutFinalization(); // read super class type (part 2).
1449 klass->set_super_type(super_type);
1450 }
1451
1452 class_helper->SetJustRead(ClassHelper::kSuperClass);
1453 class_helper->ReadUntilIncluding(ClassHelper::kMixinType);
1454
1455 // Build implemented interface types
1456 intptr_t interface_count = helper_.ReadListLength();
1457 const Array& interfaces =
1458 Array::Handle(Z, Array::New(interface_count, Heap::kOld));
1459 for (intptr_t i = 0; i < interface_count; i++) {
1460 const AbstractType& type =
1461 T.BuildTypeWithoutFinalization(); // read ith type.
1462 interfaces.SetAt(i, type);
1463 }
1464 class_helper->SetJustRead(ClassHelper::kImplementedClasses);
1465 klass->set_interfaces(interfaces);
1466
1467 if (class_helper->is_abstract()) klass->set_is_abstract();
1468
1469 if (class_helper->is_transformed_mixin_application()) {
1470 klass->set_is_transformed_mixin_application();
1471 }
1472 if (class_helper->has_const_constructor()) {
1473 klass->set_is_const();
1474 }
1475}
1476
1477void KernelLoader::LoadClass(const Library& library,
1478 const Class& toplevel_class,
1479 intptr_t class_end,
1480 Class* out_class) {
1481 intptr_t class_offset = helper_.ReaderOffset();
1482 ClassIndex class_index(program_->kernel_data(), program_->kernel_data_size(),
1483 class_offset, class_end - class_offset);
1484
1485 ClassHelper class_helper(&helper_);
1486 class_helper.ReadUntilIncluding(ClassHelper::kCanonicalName);
1487 *out_class = LookupClass(library, class_helper.canonical_name_);
1488 out_class->set_kernel_offset(class_offset - correction_offset_);
1489
1490 // The class needs to have a script because all the functions in the class
1491 // will inherit it. The predicate Function::IsOptimizable uses the absence of
1492 // a script to detect test functions that should not be optimized.
1493 if (out_class->script() == Script::null()) {
1494 class_helper.ReadUntilIncluding(ClassHelper::kSourceUriIndex);
1495 const Script& script =
1496 Script::Handle(Z, ScriptAt(class_helper.source_uri_index_));
1497 out_class->set_script(script);
1498 }
1499 if (out_class->token_pos() == TokenPosition::kNoSource) {
1500 class_helper.ReadUntilIncluding(ClassHelper::kEndPosition);
1501 out_class->set_token_pos(class_helper.start_position_);
1502 out_class->set_end_token_pos(class_helper.end_position_);
1503 }
1504
1505 class_helper.ReadUntilIncluding(ClassHelper::kFlags);
1506 if (class_helper.is_enum_class()) {
1507 out_class->set_is_enum_class();
1508 }
1509
1510 class_helper.ReadUntilExcluding(ClassHelper::kAnnotations);
1511 intptr_t annotation_count = helper_.ReadListLength();
1512 bool has_pragma_annotation = false;
1513 {
1514 String& native_name_unused = String::Handle(Z);
1515 bool is_potential_native_unused = false;
1516 ReadVMAnnotations(library, annotation_count, &native_name_unused,
1517 &is_potential_native_unused, &has_pragma_annotation);
1518 }
1519 if (has_pragma_annotation) {
1520 out_class->set_has_pragma(true);
1521 }
1522 class_helper.SetJustRead(ClassHelper::kAnnotations);
1523 class_helper.ReadUntilExcluding(ClassHelper::kTypeParameters);
1524 intptr_t type_parameter_counts =
1525 helper_.ReadListLength(); // read type_parameters list length.
1526
1527 ActiveClassScope active_class_scope(&active_class_, out_class);
1528 if (!out_class->is_declaration_loaded()) {
1529 LoadPreliminaryClass(&class_helper, type_parameter_counts);
1530 } else {
1531 ASSERT(type_parameter_counts == 0);
1532 class_helper.SetJustRead(ClassHelper::kTypeParameters);
1533 }
1534
1535 if ((FLAG_enable_mirrors || has_pragma_annotation) && annotation_count > 0) {
1536 library.AddClassMetadata(*out_class, toplevel_class,
1537 TokenPosition::kNoSource,
1538 class_offset - correction_offset_, 0);
1539 }
1540
1541 // We do not register expression evaluation classes with the VM:
1542 // The expression evaluation functions should be GC-able as soon as
1543 // they are not reachable anymore and we never look them up by name.
1544 const bool register_class =
1545 library.raw() != expression_evaluation_library_.raw();
1546
1547 if (loading_native_wrappers_library_ || !register_class) {
1548 FinishClassLoading(*out_class, library, toplevel_class, class_offset,
1549 class_index, &class_helper);
1550 }
1551
1552 helper_.SetOffset(class_end);
1553}
1554
1555void KernelLoader::FinishClassLoading(const Class& klass,
1556 const Library& library,
1557 const Class& toplevel_class,
1558 intptr_t class_offset,
1559 const ClassIndex& class_index,
1560 ClassHelper* class_helper) {
1561 if (klass.is_loaded()) {
1562 return;
1563 }
1564
1565 TIMELINE_DURATION(Thread::Current(), Isolate, "FinishClassLoading");
1566
1567 ActiveClassScope active_class_scope(&active_class_, &klass);
1568
1569 // If this is a dart:internal.ClassID class ignore field declarations
1570 // contained in the Kernel file and instead inject our own const
1571 // fields.
1572 const bool discard_fields = klass.InjectCIDFields();
1573
1574 fields_.Clear();
1575 functions_.Clear();
1576 if (!discard_fields) {
1577 class_helper->ReadUntilExcluding(ClassHelper::kFields);
1578 int field_count = helper_.ReadListLength(); // read list length.
1579 for (intptr_t i = 0; i < field_count; ++i) {
1580 intptr_t field_offset = helper_.ReaderOffset() - correction_offset_;
1581 ActiveMemberScope active_member(&active_class_, NULL);
1582 FieldHelper field_helper(&helper_);
1583
1584 field_helper.ReadUntilIncluding(FieldHelper::kSourceUriIndex);
1585 const Object& script_class =
1586 ClassForScriptAt(klass, field_helper.source_uri_index_);
1587
1588 field_helper.ReadUntilExcluding(FieldHelper::kName);
1589 const String& name = helper_.ReadNameAsFieldName();
1590 field_helper.SetJustRead(FieldHelper::kName);
1591
1592 field_helper.ReadUntilExcluding(FieldHelper::kAnnotations);
1593 intptr_t annotation_count = helper_.ReadListLength();
1594 bool has_pragma_annotation;
1595 {
1596 String& native_name_unused = String::Handle();
1597 bool is_potential_native_unused;
1598 ReadVMAnnotations(library, annotation_count, &native_name_unused,
1599 &is_potential_native_unused, &has_pragma_annotation);
1600 }
1601 field_helper.SetJustRead(FieldHelper::kAnnotations);
1602
1603 field_helper.ReadUntilExcluding(FieldHelper::kType);
1604 const AbstractType& type =
1605 T.BuildTypeWithoutFinalization(); // read type.
1606 field_helper.SetJustRead(FieldHelper::kType);
1607
1608 const bool is_reflectable =
1609 field_helper.position_.IsReal() &&
1610 !(library.is_dart_scheme() && library.IsPrivate(name));
1611 // In the VM all const fields are implicitly final whereas in Kernel they
1612 // are not final because they are not explicitly declared that way.
1613 const bool is_final = field_helper.IsConst() || field_helper.IsFinal();
1614 const bool is_late = field_helper.IsLate();
1615 const bool is_extension_member = field_helper.IsExtensionMember();
1616 Field& field = Field::Handle(
1617 Z, Field::New(name, field_helper.IsStatic(), is_final,
1618 field_helper.IsConst(), is_reflectable, is_late,
1619 script_class, type, field_helper.position_,
1620 field_helper.end_position_));
1621 field.set_kernel_offset(field_offset);
1622 field.set_has_pragma(has_pragma_annotation);
1623 field.set_is_covariant(field_helper.IsCovariant());
1624 field.set_is_generic_covariant_impl(
1625 field_helper.IsGenericCovariantImpl());
1626 field.set_is_extension_member(is_extension_member);
1627 ReadInferredType(field, field_offset + library_kernel_offset_);
1628 CheckForInitializer(field);
1629 // In NNBD libraries, static fields with initializers are
1630 // implicitly late.
1631 if (field_helper.IsStatic() && field.has_initializer() &&
1632 library.is_nnbd()) {
1633 field.set_is_late(true);
1634 }
1635 field_helper.ReadUntilExcluding(FieldHelper::kInitializer);
1636 intptr_t field_initializer_offset = helper_.ReaderOffset();
1637 field_helper.ReadUntilExcluding(FieldHelper::kEnd);
1638 {
1639 // GenerateFieldAccessors reads (some of) the initializer.
1640 AlternativeReadingScope alt(&helper_.reader_, field_initializer_offset);
1641 GenerateFieldAccessors(klass, field, &field_helper);
1642 }
1643 if ((FLAG_enable_mirrors || has_pragma_annotation) &&
1644 annotation_count > 0) {
1645 library.AddFieldMetadata(field, TokenPosition::kNoSource, field_offset,
1646 0);
1647 }
1648 fields_.Add(&field);
1649 }
1650 class_helper->SetJustRead(ClassHelper::kFields);
1651
1652 if (klass.is_enum_class()) {
1653 // Add static field 'const _deleted_enum_sentinel'.
1654 // This field does not need to be of type E.
1655 Field& deleted_enum_sentinel = Field::ZoneHandle(Z);
1656 deleted_enum_sentinel =
1657 Field::New(Symbols::_DeletedEnumSentinel(),
1658 /* is_static = */ true,
1659 /* is_final = */ true,
1660 /* is_const = */ true,
1661 /* is_reflectable = */ false,
1662 /* is_late = */ false, klass, Object::dynamic_type(),
1663 TokenPosition::kNoSource, TokenPosition::kNoSource);
1664 fields_.Add(&deleted_enum_sentinel);
1665 }
1666
1667 // Due to ReadVMAnnotations(), the klass may have been loaded at this point
1668 // (loading the class while evaluating annotations).
1669 if (klass.is_loaded()) {
1670 return;
1671 }
1672
1673 klass.SetFields(Array::Handle(Z, MakeFieldsArray()));
1674 }
1675
1676 class_helper->ReadUntilExcluding(ClassHelper::kConstructors);
1677 int constructor_count = helper_.ReadListLength(); // read list length.
1678 for (intptr_t i = 0; i < constructor_count; ++i) {
1679 intptr_t constructor_offset = helper_.ReaderOffset() - correction_offset_;
1680 ActiveMemberScope active_member_scope(&active_class_, NULL);
1681 ConstructorHelper constructor_helper(&helper_);
1682 constructor_helper.ReadUntilExcluding(ConstructorHelper::kAnnotations);
1683 intptr_t annotation_count = helper_.ReadListLength();
1684 bool has_pragma_annotation;
1685 {
1686 String& native_name_unused = String::Handle();
1687 bool is_potential_native_unused;
1688 ReadVMAnnotations(library, annotation_count, &native_name_unused,
1689 &is_potential_native_unused, &has_pragma_annotation);
1690 }
1691 constructor_helper.SetJustRead(ConstructorHelper::kAnnotations);
1692 constructor_helper.ReadUntilExcluding(ConstructorHelper::kFunction);
1693
1694 const String& name =
1695 H.DartConstructorName(constructor_helper.canonical_name_);
1696
1697 // We can have synthetic constructors, which will not have a source uri
1698 // attached to them (which means the index into the source uri table is 0,
1699 // see `package:kernel/binary/ast_to_binary::writeUriReference`.
1700 const Object* owner = &klass;
1701 const intptr_t source_uri_index = constructor_helper.source_uri_index_;
1702 if (source_uri_index != 0) {
1703 owner = &ClassForScriptAt(klass, source_uri_index);
1704 }
1705
1706 Function& function = Function::ZoneHandle(
1707 Z, Function::New(name, FunctionLayout::kConstructor,
1708 false, // is_static
1709 constructor_helper.IsConst(),
1710 false, // is_abstract
1711 constructor_helper.IsExternal(),
1712 false, // is_native
1713 *owner, constructor_helper.start_position_));
1714 function.set_end_token_pos(constructor_helper.end_position_);
1715 functions_.Add(&function);
1716 function.set_kernel_offset(constructor_offset);
1717 function.set_result_type(T.ReceiverType(klass));
1718 function.set_has_pragma(has_pragma_annotation);
1719
1720 FunctionNodeHelper function_node_helper(&helper_);
1721 function_node_helper.ReadUntilExcluding(
1722 FunctionNodeHelper::kTypeParameters);
1723 T.SetupFunctionParameters(klass, function,
1724 true, // is_method
1725 false, // is_closure
1726 &function_node_helper);
1727 T.SetupUnboxingInfoMetadata(function, library_kernel_offset_);
1728
1729 if (library.is_dart_scheme() &&
1730 H.IsPrivate(constructor_helper.canonical_name_)) {
1731 function.set_is_reflectable(false);
1732 }
1733
1734 if (constructor_helper.IsSynthetic()) {
1735 function.set_is_debuggable(false);
1736 }
1737
1738 function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kEnd);
1739 constructor_helper.SetJustRead(ConstructorHelper::kFunction);
1740 constructor_helper.ReadUntilExcluding(ConstructorHelper::kEnd);
1741
1742 if ((FLAG_enable_mirrors || has_pragma_annotation) &&
1743 annotation_count > 0) {
1744 library.AddFunctionMetadata(function, TokenPosition::kNoSource,
1745 constructor_offset, 0);
1746 }
1747 }
1748
1749 // Due to ReadVMAnnotations(), the klass may have been loaded at this point
1750 // (loading the class while evaluating annotations).
1751 if (klass.is_loaded()) {
1752 return;
1753 }
1754
1755 // Everything up til the procedures are skipped implicitly, and class_helper
1756 // is no longer used.
1757
1758 intptr_t procedure_count = class_index.procedure_count();
1759 // Procedure offsets within a class index are whole program offsets and not
1760 // relative to the library of the class. Hence, we need a correction to get
1761 // the currect procedure offset within the current data.
1762 intptr_t correction = correction_offset_ - library_kernel_offset_;
1763 intptr_t next_procedure_offset = class_index.ProcedureOffset(0) + correction;
1764 for (intptr_t i = 0; i < procedure_count; ++i) {
1765 helper_.SetOffset(next_procedure_offset);
1766 next_procedure_offset = class_index.ProcedureOffset(i + 1) + correction;
1767 LoadProcedure(library, klass, true, next_procedure_offset);
1768 // LoadProcedure calls Library::GetMetadata which invokes Dart code
1769 // which may recursively trigger class finalization and FinishClassLoading.
1770 // In such case, return immediately and avoid overwriting already finalized
1771 // functions with freshly loaded and not yet finalized.
1772 if (klass.is_loaded()) {
1773 return;
1774 }
1775 }
1776
1777 klass.SetFunctions(Array::Handle(MakeFunctionsArray()));
1778
1779 ASSERT(!klass.is_loaded());
1780 klass.set_is_loaded(true);
1781}
1782
1783void KernelLoader::FinishLoading(const Class& klass) {
1784 ASSERT(!klass.is_declared_in_bytecode());
1785 ASSERT(klass.IsTopLevel() || (klass.kernel_offset() > 0));
1786
1787 Zone* zone = Thread::Current()->zone();
1788 const Script& script = Script::Handle(zone, klass.script());
1789 const Library& library = Library::Handle(zone, klass.library());
1790 const Class& toplevel_class = Class::Handle(zone, library.toplevel_class());
1791 const ExternalTypedData& library_kernel_data =
1792 ExternalTypedData::Handle(zone, library.kernel_data());
1793 ASSERT(!library_kernel_data.IsNull());
1794 const intptr_t library_kernel_offset = library.kernel_offset();
1795 ASSERT(library_kernel_offset > 0);
1796
1797 const KernelProgramInfo& info =
1798 KernelProgramInfo::Handle(zone, script.kernel_program_info());
1799
1800 KernelLoader kernel_loader(script, library_kernel_data, library_kernel_offset,
1801 info.kernel_binary_version());
1802 LibraryIndex library_index(library_kernel_data, info.kernel_binary_version());
1803
1804 if (klass.IsTopLevel()) {
1805 ASSERT(klass.raw() == toplevel_class.raw());
1806 kernel_loader.FinishTopLevelClassLoading(klass, library, library_index);
1807 return;
1808 }
1809
1810 const intptr_t class_offset = klass.kernel_offset();
1811 ClassIndex class_index(
1812 library_kernel_data, class_offset,
1813 // Class offsets in library index are whole program offsets.
1814 // Hence, we need to add |library_kernel_offset| to
1815 // |class_offset| to lookup the entry for the class in the library
1816 // index.
1817 library_index.SizeOfClassAtOffset(class_offset + library_kernel_offset));
1818
1819 kernel_loader.helper_.SetOffset(class_offset);
1820 ClassHelper class_helper(&kernel_loader.helper_);
1821
1822 kernel_loader.FinishClassLoading(klass, library, toplevel_class, class_offset,
1823 class_index, &class_helper);
1824}
1825
1826// Read annotations on a procedure to identify potential VM-specific directives.
1827//
1828// Output parameters:
1829//
1830// `native_name`: non-null if `@ExternalName(...)` was identified.
1831//
1832// `is_potential_native`: non-null if there may be an `@ExternalName(...)`
1833// annotation and we need to re-try after reading the constants table.
1834//
1835// `has_pragma_annotation`: non-null if @pragma(...) was found (no information
1836// is given on the kind of pragma directive).
1837//
1838void KernelLoader::ReadVMAnnotations(const Library& library,
1839 intptr_t annotation_count,
1840 String* native_name,
1841 bool* is_potential_native,
1842 bool* has_pragma_annotation) {
1843 *is_potential_native = false;
1844 *has_pragma_annotation = false;
1845 Instance& constant = Instance::Handle(Z);
1846 String& detected_name = String::Handle(Z);
1847 for (intptr_t i = 0; i < annotation_count; ++i) {
1848 const intptr_t tag = helper_.PeekTag();
1849 if (tag == kConstructorInvocation || tag == kConstConstructorInvocation) {
1850 const intptr_t start = helper_.ReaderOffset();
1851 detected_name = DetectExternalNameCtor();
1852 if (!detected_name.IsNull()) {
1853 *native_name = detected_name.raw();
1854 continue;
1855 }
1856
1857 helper_.SetOffset(start);
1858 if (DetectPragmaCtor()) {
1859 *has_pragma_annotation = true;
1860 }
1861 } else if (tag == kConstantExpression) {
1862 const Array& constant_table_array =
1863 Array::Handle(kernel_program_info_.constants());
1864 if (constant_table_array.IsNull()) {
1865 // We can only read in the constant table once all classes have been
1866 // finalized (otherwise we can't create instances of the classes!).
1867 //
1868 // We therefore delay the scanning for `ExternalName {name: ... }`
1869 // constants in the annotation list to later.
1870 *is_potential_native = true;
1871
1872 ASSERT(kernel_program_info_.constants_table() !=
1873 ExternalTypedData::null());
1874
1875 // For pragma annotations, we seek into the constants table and peek
1876 // into the Kernel representation of the constant.
1877 //
1878 // TODO(sjindel): Refactor `ExternalName` handling to do this as well
1879 // and avoid the "potential natives" list.
1880
1881 helper_.ReadByte(); // Skip the tag.
1882 helper_.ReadPosition(); // Skip fileOffset.
1883 helper_.SkipDartType(); // Skip type.
1884 const intptr_t offset_in_constant_table = helper_.ReadUInt();
1885
1886 AlternativeReadingScopeWithNewData scope(
1887 &helper_.reader_,
1888 &ExternalTypedData::Handle(Z,
1889 kernel_program_info_.constants_table()),
1890 0);
1891
1892 // Seek into the position within the constant table where we can inspect
1893 // this constant's Kernel representation.
1894 helper_.ReadUInt(); // skip constant table size
1895 helper_.SkipBytes(offset_in_constant_table);
1896 uint8_t tag = helper_.ReadTag();
1897 if (tag == kInstanceConstant) {
1898 *has_pragma_annotation =
1899 *has_pragma_annotation ||
1900 IsClassName(helper_.ReadCanonicalNameReference(),
1901 Symbols::DartCore(), Symbols::Pragma());
1902 }
1903 } else {
1904 // Prepare lazy constant reading.
1905 const dart::Class& toplevel_class =
1906 Class::Handle(Z, library.toplevel_class());
1907 ActiveClassScope active_class_scope(&active_class_, &toplevel_class);
1908 ConstantReader constant_reader(&helper_, &active_class_);
1909
1910 helper_.ReadByte(); // Skip the tag.
1911
1912 // Obtain `dart:_internal::ExternalName.name`.
1913 EnsureExternalClassIsLookedUp();
1914
1915 // Obtain `dart:_internal::pragma`.
1916 EnsurePragmaClassIsLookedUp();
1917
1918 if (tag == kConstantExpression) {
1919 helper_.ReadPosition(); // Skip fileOffset.
1920 helper_.SkipDartType(); // Skip type.
1921 }
1922 const intptr_t constant_table_offset = helper_.ReadUInt();
1923 // We have a candidate. Let's look if it's an instance of the
1924 // ExternalName or Pragma class.
1925 if (constant_reader.IsInstanceConstant(constant_table_offset,
1926 external_name_class_)) {
1927 constant = constant_reader.ReadConstant(constant_table_offset);
1928 ASSERT(constant.clazz() == external_name_class_.raw());
1929 *native_name ^= constant.GetField(external_name_field_);
1930 } else if (constant_reader.IsInstanceConstant(constant_table_offset,
1931 pragma_class_)) {
1932 *has_pragma_annotation = true;
1933 }
1934 }
1935 } else {
1936 helper_.SkipExpression();
1937 continue;
1938 }
1939 }
1940}
1941
1942void KernelLoader::LoadProcedure(const Library& library,
1943 const Class& owner,
1944 bool in_class,
1945 intptr_t procedure_end) {
1946 intptr_t procedure_offset = helper_.ReaderOffset() - correction_offset_;
1947 ProcedureHelper procedure_helper(&helper_);
1948
1949 procedure_helper.ReadUntilExcluding(ProcedureHelper::kAnnotations);
1950 // CFE adds 'member signature' abstract functions to a legacy class deriving
1951 // or implementing an opted-in interface. The signature of these functions is
1952 // legacy erased and used as the target of interface calls. They are used for
1953 // static reasoning about the program by CFE, but not really needed by the VM.
1954 // In certain situations (e.g. issue 162073826), a large number of these
1955 // additional functions can cause strain on the VM. They are therefore skipped
1956 // in jit mode and their associated origin function is used instead as
1957 // interface call target.
1958 if (procedure_helper.IsRedirectingFactoryConstructor() ||
1959 (!FLAG_precompiled_mode && procedure_helper.IsMemberSignature())) {
1960 helper_.SetOffset(procedure_end);
1961 return;
1962 }
1963 const String& name = H.DartProcedureName(procedure_helper.canonical_name_);
1964 bool is_method = in_class && !procedure_helper.IsStatic();
1965 bool is_abstract = procedure_helper.IsAbstract();
1966 bool is_external = procedure_helper.IsExternal();
1967 bool is_extension_member = procedure_helper.IsExtensionMember();
1968 String& native_name = String::Handle(Z);
1969 bool is_potential_native;
1970 bool has_pragma_annotation;
1971 const intptr_t annotation_count = helper_.ReadListLength();
1972 ReadVMAnnotations(library, annotation_count, &native_name,
1973 &is_potential_native, &has_pragma_annotation);
1974 // If this is a potential native, we'll unset is_external in
1975 // AnnotateNativeProcedures instead.
1976 is_external = is_external && native_name.IsNull();
1977 procedure_helper.SetJustRead(ProcedureHelper::kAnnotations);
1978 const Object& script_class =
1979 ClassForScriptAt(owner, procedure_helper.source_uri_index_);
1980 FunctionLayout::Kind kind = GetFunctionType(procedure_helper.kind_);
1981
1982 // We do not register expression evaluation libraries with the VM:
1983 // The expression evaluation functions should be GC-able as soon as
1984 // they are not reachable anymore and we never look them up by name.
1985 const bool register_function = !name.Equals(Symbols::DebugProcedureName());
1986
1987 Function& function = Function::ZoneHandle(
1988 Z, Function::New(name, kind,
1989 !is_method, // is_static
1990 false, // is_const
1991 is_abstract, is_external,
1992 !native_name.IsNull(), // is_native
1993 script_class, procedure_helper.start_position_));
1994 function.set_has_pragma(has_pragma_annotation);
1995 function.set_end_token_pos(procedure_helper.end_position_);
1996 function.set_is_synthetic(procedure_helper.IsNoSuchMethodForwarder() ||
1997 procedure_helper.IsMemberSignature());
1998 if (register_function) {
1999 functions_.Add(&function);
2000 } else {
2001 H.SetExpressionEvaluationFunction(function);
2002 }
2003 function.set_kernel_offset(procedure_offset);
2004 function.set_is_extension_member(is_extension_member);
2005 if ((library.is_dart_scheme() &&
2006 H.IsPrivate(procedure_helper.canonical_name_)) ||
2007 (function.is_static() && (library.raw() == Library::InternalLibrary()))) {
2008 function.set_is_reflectable(false);
2009 }
2010 if (procedure_helper.IsMemberSignature()) {
2011 function.set_is_reflectable(false);
2012 }
2013
2014 ActiveMemberScope active_member(&active_class_, &function);
2015
2016 procedure_helper.ReadUntilExcluding(ProcedureHelper::kFunction);
2017
2018 Tag function_node_tag = helper_.ReadTag();
2019 ASSERT(function_node_tag == kSomething);
2020 FunctionNodeHelper function_node_helper(&helper_);
2021 function_node_helper.ReadUntilIncluding(FunctionNodeHelper::kDartAsyncMarker);
2022
2023 const bool is_async_await_completer_owner =
2024 Symbols::_AsyncAwaitCompleter().Equals(
2025 String::Handle(Z, owner.ScrubbedName()));
2026
2027 // _AsyncAwaitCompleter.future should be made non-debuggable, otherwise
2028 // stepping out of async methods will keep hitting breakpoint resulting in
2029 // infinite loop.
2030 const bool is_async_await_completer_future =
2031 is_async_await_completer_owner &&
2032 Symbols::CompleterGetFuture().Equals(name);
2033 function.set_is_debuggable(function_node_helper.dart_async_marker_ ==
2034 FunctionNodeHelper::kSync &&
2035 !is_async_await_completer_future);
2036
2037 // _AsyncAwaitCompleter.start should be made non-visible in stack traces,
2038 // since it is an implementation detail of our await/async desugaring.
2039 if (is_async_await_completer_owner &&
2040 Symbols::_AsyncAwaitStart().Equals(name)) {
2041 function.set_is_visible(!FLAG_causal_async_stacks &&
2042 !FLAG_lazy_async_stacks);
2043 }
2044
2045 switch (function_node_helper.dart_async_marker_) {
2046 case FunctionNodeHelper::kSyncStar:
2047 function.set_modifier(FunctionLayout::kSyncGen);
2048 function.set_is_visible(!FLAG_causal_async_stacks &&
2049 !FLAG_lazy_async_stacks);
2050 break;
2051 case FunctionNodeHelper::kAsync:
2052 function.set_modifier(FunctionLayout::kAsync);
2053 function.set_is_inlinable(!FLAG_causal_async_stacks &&
2054 !FLAG_lazy_async_stacks);
2055 function.set_is_visible(!FLAG_causal_async_stacks &&
2056 !FLAG_lazy_async_stacks);
2057 break;
2058 case FunctionNodeHelper::kAsyncStar:
2059 function.set_modifier(FunctionLayout::kAsyncGen);
2060 function.set_is_inlinable(!FLAG_causal_async_stacks &&
2061 !FLAG_lazy_async_stacks);
2062 function.set_is_visible(!FLAG_causal_async_stacks &&
2063 !FLAG_lazy_async_stacks);
2064 break;
2065 default:
2066 // no special modifier
2067 break;
2068 }
2069 ASSERT(function_node_helper.async_marker_ == FunctionNodeHelper::kSync);
2070
2071 if (!native_name.IsNull()) {
2072 function.set_native_name(native_name);
2073 }
2074 if (is_potential_native) {
2075 // Cannot be processed right now, so put on "pending" list.
2076 EnsurePotentialNatives();
2077 potential_natives_.Add(function);
2078 }
2079
2080 function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kTypeParameters);
2081 T.SetupFunctionParameters(owner, function, is_method,
2082 false, // is_closure
2083 &function_node_helper);
2084 T.SetupUnboxingInfoMetadata(function, library_kernel_offset_);
2085
2086 // Everything else is skipped implicitly, and procedure_helper and
2087 // function_node_helper are no longer used.
2088 helper_.SetOffset(procedure_end);
2089
2090 if (annotation_count > 0) {
2091 library.AddFunctionMetadata(function, TokenPosition::kNoSource,
2092 procedure_offset, 0);
2093 }
2094
2095 if (has_pragma_annotation) {
2096 if (kernel_program_info_.constants() == Array::null()) {
2097 // Any potential pragma function before point at which
2098 // constant table could be loaded goes to "pending".
2099 EnsurePotentialPragmaFunctions();
2100 potential_pragma_functions_.Add(function);
2101 } else {
2102 Thread* thread = Thread::Current();
2103 NoOOBMessageScope no_msg_scope(thread);
2104 NoReloadScope no_reload_scope(thread->isolate(), thread);
2105 library.GetMetadata(function);
2106 }
2107 }
2108}
2109
2110const Object& KernelLoader::ClassForScriptAt(const Class& klass,
2111 intptr_t source_uri_index) {
2112 const Script& correct_script = Script::Handle(Z, ScriptAt(source_uri_index));
2113 if (klass.script() != correct_script.raw()) {
2114 // Lazily create the [patch_classes_] array in case we need it.
2115 if (patch_classes_.IsNull()) {
2116 const Array& scripts = Array::Handle(Z, kernel_program_info_.scripts());
2117 ASSERT(!scripts.IsNull());
2118 patch_classes_ = Array::New(scripts.Length(), Heap::kOld);
2119 }
2120
2121 // Use cache for patch classes. This works best for in-order usages.
2122 PatchClass& patch_class = PatchClass::ZoneHandle(Z);
2123 patch_class ^= patch_classes_.At(source_uri_index);
2124 if (patch_class.IsNull() || patch_class.origin_class() != klass.raw()) {
2125 ASSERT(!library_kernel_data_.IsNull());
2126 patch_class = PatchClass::New(klass, correct_script);
2127 patch_class.set_library_kernel_data(library_kernel_data_);
2128 patch_class.set_library_kernel_offset(library_kernel_offset_);
2129 patch_classes_.SetAt(source_uri_index, patch_class);
2130 }
2131 return patch_class;
2132 }
2133 return klass;
2134}
2135
2136ScriptPtr KernelLoader::LoadScriptAt(intptr_t index,
2137 UriToSourceTable* uri_to_source_table) {
2138 const String& uri_string = helper_.SourceTableUriFor(index);
2139 const String& import_uri_string =
2140 helper_.SourceTableImportUriFor(index, program_->binary_version());
2141
2142 String& sources = String::Handle(Z);
2143 TypedData& line_starts = TypedData::Handle(Z);
2144
2145 if (uri_to_source_table != nullptr) {
2146 UriToSourceTableEntry wrapper;
2147 wrapper.uri = &uri_string;
2148 UriToSourceTableEntry* pair = uri_to_source_table->LookupValue(&wrapper);
2149 if (pair != nullptr) {
2150 sources = pair->sources->raw();
2151 line_starts = pair->line_starts->raw();
2152 }
2153 }
2154
2155 if (sources.IsNull() || line_starts.IsNull()) {
2156 const String& script_source = helper_.GetSourceFor(index);
2157 line_starts = helper_.GetLineStartsFor(index);
2158
2159 if (script_source.raw() == Symbols::Empty().raw() &&
2160 line_starts.Length() == 0 && uri_string.Length() > 0) {
2161 // Entry included only to provide URI - actual source should already exist
2162 // in the VM, so try to find it.
2163 Library& lib = Library::Handle(Z);
2164 Script& script = Script::Handle(Z);
2165 const GrowableObjectArray& libs =
2166 GrowableObjectArray::Handle(isolate_->object_store()->libraries());
2167 for (intptr_t i = 0; i < libs.Length(); i++) {
2168 lib ^= libs.At(i);
2169 script = lib.LookupScript(uri_string, /* useResolvedUri = */ true);
2170 if (!script.IsNull()) {
2171 sources = script.Source();
2172 line_starts = script.line_starts();
2173 break;
2174 }
2175 }
2176 } else {
2177 sources = script_source.raw();
2178 }
2179 }
2180
2181 const Script& script =
2182 Script::Handle(Z, Script::New(import_uri_string, uri_string, sources));
2183 script.set_kernel_script_index(index);
2184 script.set_kernel_program_info(kernel_program_info_);
2185 script.set_line_starts(line_starts);
2186 script.set_debug_positions(Array::null_array());
2187 return script.raw();
2188}
2189
2190void KernelLoader::GenerateFieldAccessors(const Class& klass,
2191 const Field& field,
2192 FieldHelper* field_helper) {
2193 const Tag tag = helper_.PeekTag();
2194 const bool has_initializer = (tag == kSomething);
2195 if (has_initializer) {
2196 SimpleExpressionConverter converter(&H, &helper_);
2197 const bool has_simple_initializer =
2198 converter.IsSimple(helper_.ReaderOffset() + 1); // ignore the tag.
2199 if (has_simple_initializer) {
2200 if (field_helper->IsStatic()) {
2201 // We do not need a getter.
2202 field.SetStaticValue(converter.SimpleValue(), true);
2203 return;
2204 } else {
2205 // Note: optimizer relies on DoubleInitialized bit in its field-unboxing
2206 // heuristics. See JitCallSpecializer::VisitStoreInstanceField for more
2207 // details.
2208 field.RecordStore(converter.SimpleValue());
2209 if (!converter.SimpleValue().IsNull() &&
2210 converter.SimpleValue().IsDouble()) {
2211 field.set_is_double_initialized(true);
2212 }
2213 }
2214 }
2215 }
2216
2217 if (field_helper->IsStatic()) {
2218 if (!has_initializer && !field_helper->IsLate()) {
2219 // Static fields without an initializer are implicitly initialized to
2220 // null. We do not need a getter.
2221 field.SetStaticValue(Instance::null_instance(), true);
2222 return;
2223 }
2224
2225 // We do need a getter that evaluates the initializer if necessary.
2226 field.SetStaticValue(Object::sentinel(), true);
2227 }
2228 ASSERT(field.NeedsGetter());
2229
2230 const String& getter_name = H.DartGetterName(field_helper->canonical_name_);
2231 const Object& script_class =
2232 ClassForScriptAt(klass, field_helper->source_uri_index_);
2233 Function& getter = Function::ZoneHandle(
2234 Z,
2235 Function::New(
2236 getter_name,
2237 field_helper->IsStatic() ? FunctionLayout::kImplicitStaticGetter
2238 : FunctionLayout::kImplicitGetter,
2239 field_helper->IsStatic(),
2240 // The functions created by the parser have is_const for static fields
2241 // that are const (not just final) and they have is_const for
2242 // non-static fields that are final.
2243 field_helper->IsStatic() ? field_helper->IsConst()
2244 : field_helper->IsFinal(),
2245 false, // is_abstract
2246 false, // is_external
2247 false, // is_native
2248 script_class, field_helper->position_));
2249 functions_.Add(&getter);
2250 getter.set_end_token_pos(field_helper->end_position_);
2251 getter.set_kernel_offset(field.kernel_offset());
2252 const AbstractType& field_type = AbstractType::Handle(Z, field.type());
2253 getter.set_result_type(field_type);
2254 getter.set_is_debuggable(false);
2255 getter.set_accessor_field(field);
2256 getter.set_is_extension_member(field.is_extension_member());
2257 H.SetupFieldAccessorFunction(klass, getter, field_type);
2258 T.SetupUnboxingInfoMetadataForFieldAccessors(getter, library_kernel_offset_);
2259
2260 if (field.NeedsSetter()) {
2261 // Only static fields can be const.
2262 ASSERT(!field_helper->IsConst());
2263 const String& setter_name = H.DartSetterName(field_helper->canonical_name_);
2264 Function& setter = Function::ZoneHandle(
2265 Z, Function::New(setter_name, FunctionLayout::kImplicitSetter,
2266 field_helper->IsStatic(),
2267 false, // is_const
2268 false, // is_abstract
2269 false, // is_external
2270 false, // is_native
2271 script_class, field_helper->position_));
2272 functions_.Add(&setter);
2273 setter.set_end_token_pos(field_helper->end_position_);
2274 setter.set_kernel_offset(field.kernel_offset());
2275 setter.set_result_type(Object::void_type());
2276 setter.set_is_debuggable(false);
2277 setter.set_accessor_field(field);
2278 setter.set_is_extension_member(field.is_extension_member());
2279 H.SetupFieldAccessorFunction(klass, setter, field_type);
2280 T.SetupUnboxingInfoMetadataForFieldAccessors(getter,
2281 library_kernel_offset_);
2282 }
2283}
2284
2285LibraryPtr KernelLoader::LookupLibraryOrNull(NameIndex library) {
2286 LibraryPtr result;
2287 name_index_handle_ = Smi::New(library);
2288 {
2289 result = kernel_program_info_.LookupLibrary(thread_, name_index_handle_);
2290 NoSafepointScope no_safepoint_scope(thread_);
2291 if (result != Library::null()) {
2292 return result;
2293 }
2294 }
2295 const String& url = H.DartString(H.CanonicalNameString(library));
2296 {
2297 result = Library::LookupLibrary(thread_, url);
2298 NoSafepointScope no_safepoint_scope(thread_);
2299 if (result == Library::null()) {
2300 return result;
2301 }
2302 }
2303 const Library& handle = Library::Handle(Z, result);
2304 name_index_handle_ = Smi::New(library);
2305 return kernel_program_info_.InsertLibrary(thread_, name_index_handle_,
2306 handle);
2307}
2308
2309LibraryPtr KernelLoader::LookupLibrary(NameIndex library) {
2310 name_index_handle_ = Smi::New(library);
2311 {
2312 LibraryPtr result =
2313 kernel_program_info_.LookupLibrary(thread_, name_index_handle_);
2314 NoSafepointScope no_safepoint_scope(thread_);
2315 if (result != Library::null()) {
2316 return result;
2317 }
2318 }
2319
2320 Library& handle = Library::Handle(Z);
2321 const String& url = H.DartSymbolPlain(H.CanonicalNameString(library));
2322 // We do not register expression evaluation libraries with the VM:
2323 // The expression evaluation functions should be GC-able as soon as
2324 // they are not reachable anymore and we never look them up by name.
2325 if (url.Equals(Symbols::EvalSourceUri())) {
2326 if (expression_evaluation_library_.IsNull()) {
2327 handle = Library::New(url);
2328 expression_evaluation_library_ = handle.raw();
2329 }
2330 return expression_evaluation_library_.raw();
2331 }
2332 handle = Library::LookupLibrary(thread_, url);
2333 if (handle.IsNull()) {
2334 handle = Library::New(url);
2335 handle.Register(thread_);
2336 }
2337 ASSERT(!handle.IsNull());
2338 name_index_handle_ = Smi::New(library);
2339 return kernel_program_info_.InsertLibrary(thread_, name_index_handle_,
2340 handle);
2341}
2342
2343LibraryPtr KernelLoader::LookupLibraryFromClass(NameIndex klass) {
2344 return LookupLibrary(H.CanonicalNameParent(klass));
2345}
2346
2347ClassPtr KernelLoader::LookupClass(const Library& library, NameIndex klass) {
2348 name_index_handle_ = Smi::New(klass);
2349 {
2350 ClassPtr raw_class =
2351 kernel_program_info_.LookupClass(thread_, name_index_handle_);
2352 NoSafepointScope no_safepoint_scope(thread_);
2353 if (raw_class != Class::null()) {
2354 return raw_class;
2355 }
2356 }
2357
2358 ASSERT(!library.IsNull());
2359 const String& name = H.DartClassName(klass);
2360 Class& handle = Class::Handle(Z, library.LookupLocalClass(name));
2361 bool register_class = true;
2362 if (handle.IsNull()) {
2363 // We do not register expression evaluation classes with the VM:
2364 // The expression evaluation functions should be GC-able as soon as
2365 // they are not reachable anymore and we never look them up by name.
2366 register_class = library.raw() != expression_evaluation_library_.raw();
2367
2368 handle = Class::New(library, name, Script::Handle(Z),
2369 TokenPosition::kNoSource, register_class);
2370 if (register_class) {
2371 library.AddClass(handle);
2372 }
2373 }
2374 ASSERT(!handle.IsNull());
2375 if (register_class) {
2376 name_index_handle_ = Smi::New(klass);
2377 kernel_program_info_.InsertClass(thread_, name_index_handle_, handle);
2378 }
2379 return handle.raw();
2380}
2381
2382FunctionLayout::Kind KernelLoader::GetFunctionType(
2383 ProcedureHelper::Kind procedure_kind) {
2384 intptr_t lookuptable[] = {
2385 FunctionLayout::kRegularFunction, // Procedure::kMethod
2386 FunctionLayout::kGetterFunction, // Procedure::kGetter
2387 FunctionLayout::kSetterFunction, // Procedure::kSetter
2388 FunctionLayout::kRegularFunction, // Procedure::kOperator
2389 FunctionLayout::kConstructor, // Procedure::kFactory
2390 };
2391 intptr_t kind = static_cast<int>(procedure_kind);
2392 ASSERT(0 <= kind && kind <= ProcedureHelper::kFactory);
2393 return static_cast<FunctionLayout::Kind>(lookuptable[kind]);
2394}
2395
2396FunctionPtr CreateFieldInitializerFunction(Thread* thread,
2397 Zone* zone,
2398 const Field& field) {
2399 ASSERT(field.InitializerFunction() == Function::null());
2400
2401 String& init_name = String::Handle(zone, field.name());
2402 init_name = Symbols::FromConcat(thread, Symbols::InitPrefix(), init_name);
2403
2404 // Static field initializers are not added as members of their owning class,
2405 // so they must be pre-emptively given a patch class to avoid the meaning of
2406 // their kernel/token position changing during a reload. Compare
2407 // Class::PatchFieldsAndFunctions().
2408 // This might also be necessary for lazy computation of local var descriptors.
2409 // Compare https://codereview.chromium.org//1317753004
2410 const Script& script = Script::Handle(zone, field.Script());
2411 const Class& field_owner = Class::Handle(zone, field.Owner());
2412 const PatchClass& initializer_owner =
2413 PatchClass::Handle(zone, PatchClass::New(field_owner, script));
2414 const Library& lib = Library::Handle(zone, field_owner.library());
2415 if (!lib.is_declared_in_bytecode()) {
2416 initializer_owner.set_library_kernel_data(
2417 ExternalTypedData::Handle(zone, lib.kernel_data()));
2418 initializer_owner.set_library_kernel_offset(lib.kernel_offset());
2419 }
2420
2421 // Create a static initializer.
2422 const Function& initializer_fun = Function::Handle(
2423 zone, Function::New(init_name, FunctionLayout::kFieldInitializer,
2424 field.is_static(), // is_static
2425 false, // is_const
2426 false, // is_abstract
2427 false, // is_external
2428 false, // is_native
2429 initializer_owner, TokenPosition::kNoSource));
2430 if (!field.is_static()) {
2431 initializer_fun.set_num_fixed_parameters(1);
2432 initializer_fun.set_parameter_types(
2433 Array::Handle(zone, Array::New(1, Heap::kOld)));
2434 initializer_fun.set_parameter_names(
2435 Array::Handle(zone, Array::New(1, Heap::kOld)));
2436 initializer_fun.SetParameterTypeAt(
2437 0, AbstractType::Handle(zone, field_owner.DeclarationType()));
2438 initializer_fun.SetParameterNameAt(0, Symbols::This());
2439 }
2440 initializer_fun.set_result_type(AbstractType::Handle(zone, field.type()));
2441 initializer_fun.set_is_reflectable(false);
2442 initializer_fun.set_is_inlinable(false);
2443 initializer_fun.set_token_pos(field.token_pos());
2444 initializer_fun.set_end_token_pos(field.end_token_pos());
2445 initializer_fun.set_accessor_field(field);
2446 initializer_fun.InheritBinaryDeclarationFrom(field);
2447 initializer_fun.set_is_extension_member(field.is_extension_member());
2448 field.SetInitializerFunction(initializer_fun);
2449 return initializer_fun.raw();
2450}
2451
2452} // namespace kernel
2453} // namespace dart
2454#endif // !defined(DART_PRECOMPILED_RUNTIME)
2455