Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(594)

Side by Side Diff: runtime/vm/kernel_reader.cc

Issue 3010543002: Rename the class "KernelReader" to "KernelLoader". (Closed)
Patch Set: Fix names in few places Created 3 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
5 #include "vm/kernel_reader.h"
6
7 #include <string.h>
8
9 #include "vm/dart_api_impl.h"
10 #include "vm/kernel_binary.h"
11 #include "vm/kernel_binary_flowgraph.h"
12 #include "vm/kernel_to_il.h"
13 #include "vm/longjump.h"
14 #include "vm/object_store.h"
15 #include "vm/parser.h"
16 #include "vm/symbols.h"
17
18 #if !defined(DART_PRECOMPILED_RUNTIME)
19 namespace dart {
20 namespace kernel {
21
22 #define Z (zone_)
23 #define I (isolate_)
24 #define T (builder_.type_translator_)
25 #define H (translation_helper_)
26
27 class SimpleExpressionConverter {
28 public:
29 SimpleExpressionConverter(TranslationHelper* helper,
30 StreamingFlowGraphBuilder* builder)
31 : translation_helper_(*helper),
32 zone_(translation_helper_.zone()),
33 simple_value_(NULL),
34 builder_(builder) {}
35
36 bool IsSimple(intptr_t kernel_offset) {
37 AlternativeReadingScope alt(builder_->reader_, kernel_offset);
38 uint8_t payload = 0;
39 Tag tag = builder_->ReadTag(&payload); // read tag.
40 switch (tag) {
41 case kBigIntLiteral: {
42 const String& literal_str =
43 H.DartString(builder_->ReadStringReference(),
44 Heap::kOld); // read index into string table.
45 simple_value_ = &Integer::ZoneHandle(Z, Integer::New(literal_str));
46 if (simple_value_->IsNull()) {
47 H.ReportError("Integer literal %s is out of range",
48 literal_str.ToCString());
49 UNREACHABLE();
50 }
51 *simple_value_ = H.Canonicalize(*simple_value_);
52 return true;
53 }
54 case kStringLiteral:
55 simple_value_ = &H.DartSymbol(
56 builder_->ReadStringReference()); // read index into string table.
57 return true;
58 case kSpecialIntLiteral:
59 simple_value_ =
60 &Integer::ZoneHandle(Z, Integer::New(static_cast<int32_t>(payload) -
61 SpecializedIntLiteralBias,
62 Heap::kOld));
63 *simple_value_ = H.Canonicalize(*simple_value_);
64 return true;
65 case kNegativeIntLiteral:
66 simple_value_ = &Integer::ZoneHandle(
67 Z, Integer::New(-static_cast<int64_t>(builder_->ReadUInt()),
68 Heap::kOld)); // read value.
69 *simple_value_ = H.Canonicalize(*simple_value_);
70 return true;
71 case kPositiveIntLiteral:
72 simple_value_ = &Integer::ZoneHandle(
73 Z, Integer::New(static_cast<int64_t>(builder_->ReadUInt()),
74 Heap::kOld)); // read value.
75 *simple_value_ = H.Canonicalize(*simple_value_);
76 return true;
77 case kDoubleLiteral:
78 simple_value_ = &Double::ZoneHandle(
79 Z, Double::New(H.DartString(builder_->ReadStringReference()),
80 Heap::kOld)); // read string reference.
81 *simple_value_ = H.Canonicalize(*simple_value_);
82 return true;
83 case kTrueLiteral:
84 simple_value_ = &Bool::Handle(Z, Bool::Get(true).raw());
85 return true;
86 case kFalseLiteral:
87 simple_value_ = &Bool::Handle(Z, Bool::Get(false).raw());
88 return true;
89 case kNullLiteral:
90 simple_value_ = &Instance::ZoneHandle(Z, Instance::null());
91 return true;
92 default:
93 return false;
94 }
95 }
96
97 const Instance& SimpleValue() { return *simple_value_; }
98 Zone* zone() const { return zone_; }
99
100 private:
101 TranslationHelper& translation_helper_;
102 Zone* zone_;
103 Instance* simple_value_;
104 StreamingFlowGraphBuilder* builder_;
105 };
106
107 RawArray* KernelReader::MakeFunctionsArray() {
108 const intptr_t len = functions_.length();
109 const Array& res = Array::Handle(zone_, Array::New(len, Heap::kOld));
110 for (intptr_t i = 0; i < len; i++) {
111 res.SetAt(i, *functions_[i]);
112 }
113 return res.raw();
114 }
115
116 RawLibrary* BuildingTranslationHelper::LookupLibraryByKernelLibrary(
117 NameIndex library) {
118 return reader_->LookupLibrary(library).raw();
119 }
120
121 RawClass* BuildingTranslationHelper::LookupClassByKernelClass(NameIndex klass) {
122 return reader_->LookupClass(klass).raw();
123 }
124
125 KernelReader::KernelReader(Program* program)
126 : program_(program),
127 thread_(Thread::Current()),
128 zone_(thread_->zone()),
129 isolate_(thread_->isolate()),
130 scripts_(Array::ZoneHandle(zone_)),
131 patch_classes_(Array::ZoneHandle(zone_)),
132 translation_helper_(this, thread_),
133 builder_(&translation_helper_,
134 zone_,
135 program_->kernel_data(),
136 program_->kernel_data_size()) {
137 T.active_class_ = &active_class_;
138 T.finalize_ = false;
139
140 scripts_ = Array::New(builder_.SourceTableSize(), Heap::kOld);
141 patch_classes_ = Array::New(builder_.SourceTableSize(), Heap::kOld);
142
143 // Copy the Kernel string offsets out of the binary and into the VM's heap.
144 ASSERT(program->string_table_offset() >= 0);
145 Reader reader(program->kernel_data(), program->kernel_data_size());
146 reader.set_offset(program->string_table_offset());
147 intptr_t count = reader.ReadUInt() + 1;
148 TypedData& offsets = TypedData::Handle(
149 Z, TypedData::New(kTypedDataUint32ArrayCid, count, Heap::kOld));
150 offsets.SetUint32(0, 0);
151 intptr_t end_offset = 0;
152 for (intptr_t i = 1; i < count; ++i) {
153 end_offset = reader.ReadUInt();
154 offsets.SetUint32(i << 2, end_offset);
155 }
156
157 // Copy the string data out of the binary and into the VM's heap.
158 TypedData& data =
159 reader.CopyDataToVMHeap(Z, reader.offset(), reader.offset() + end_offset);
160
161 // Copy the canonical names into the VM's heap. Encode them as unsigned, so
162 // the parent indexes are adjusted when extracted.
163 reader.set_offset(program->name_table_offset());
164 count = reader.ReadUInt() * 2;
165 TypedData& names = TypedData::Handle(
166 Z, TypedData::New(kTypedDataUint32ArrayCid, count, Heap::kOld));
167 for (intptr_t i = 0; i < count; ++i) {
168 names.SetUint32(i << 2, reader.ReadUInt());
169 }
170
171 H.SetStringOffsets(offsets);
172 H.SetStringData(data);
173 H.SetCanonicalNames(names);
174 }
175
176 Object& KernelReader::ReadProgram() {
177 LongJumpScope jump;
178 if (setjmp(*jump.Set()) == 0) {
179 intptr_t length = program_->library_count();
180 for (intptr_t i = 0; i < length; i++) {
181 ReadLibrary(library_offset(i));
182 }
183
184 for (intptr_t i = 0; i < length; i++) {
185 Library& library = LookupLibrary(library_canonical_name(i));
186 if (!library.Loaded()) library.SetLoaded();
187 }
188
189 if (ClassFinalizer::ProcessPendingClasses(/*from_kernel=*/true)) {
190 // If 'main' is not found return a null library, this is the case
191 // when bootstrapping is in progress.
192 NameIndex main = program_->main_method();
193 if (main == -1) {
194 return Library::Handle(Z);
195 }
196
197 NameIndex main_library = H.EnclosingName(main);
198 Library& library = LookupLibrary(main_library);
199 // Sanity check that we can find the main entrypoint.
200 ASSERT(library.LookupObjectAllowPrivate(H.DartSymbol("main")) !=
201 Object::null());
202 return library;
203 }
204 }
205
206 // Either class finalization failed or we caught a compile error.
207 // In both cases sticky error would be set.
208 Error& error = Error::Handle(Z);
209 error = thread_->sticky_error();
210 thread_->clear_sticky_error();
211 return error;
212 }
213
214 void KernelReader::FindModifiedLibraries(Isolate* isolate,
215 BitVector* modified_libs,
216 bool force_reload) {
217 LongJumpScope jump;
218 if (setjmp(*jump.Set()) == 0) {
219 if (force_reload) {
220 // If a reload is being forced we mark all libraries as having
221 // been modified.
222 const GrowableObjectArray& libs =
223 GrowableObjectArray::Handle(isolate->object_store()->libraries());
224 intptr_t num_libs = libs.Length();
225 Library& lib = dart::Library::Handle(Z);
226 for (intptr_t i = 0; i < num_libs; i++) {
227 lib ^= libs.At(i);
228 if (!lib.is_dart_scheme()) {
229 modified_libs->Add(lib.index());
230 }
231 }
232 return;
233 }
234 // Now go through all the libraries that are present in the incremental
235 // kernel files, these will constitute the modified libraries.
236 intptr_t length = program_->library_count();
237 for (intptr_t i = 0; i < length; i++) {
238 intptr_t kernel_offset = library_offset(i);
239 builder_.SetOffset(kernel_offset);
240 LibraryHelper library_helper(&builder_);
241 library_helper.ReadUntilIncluding(LibraryHelper::kCanonicalName);
242 dart::Library& lib = LookupLibrary(library_helper.canonical_name_);
243 if (!lib.IsNull() && !lib.is_dart_scheme()) {
244 // This is a library that already exists so mark it as being modified.
245 modified_libs->Add(lib.index());
246 }
247 }
248 }
249 }
250
251 void KernelReader::ReadLibrary(intptr_t kernel_offset) {
252 builder_.SetOffset(kernel_offset);
253 LibraryHelper library_helper(&builder_);
254 library_helper.ReadUntilIncluding(LibraryHelper::kCanonicalName);
255 Library& library = LookupLibrary(library_helper.canonical_name_);
256 // The Kernel library is external implies that it is already loaded.
257 ASSERT(!library_helper.IsExternal() || library.Loaded());
258 if (library.Loaded()) return;
259
260 library_helper.ReadUntilIncluding(LibraryHelper::kName);
261 library.SetName(H.DartSymbol(library_helper.name_index_));
262
263 // The bootstrapper will take care of creating the native wrapper classes, but
264 // we will add the synthetic constructors to them here.
265 if (library.name() ==
266 Symbols::Symbol(Symbols::kDartNativeWrappersLibNameId).raw()) {
267 ASSERT(library.LoadInProgress());
268 } else {
269 library.SetLoadInProgress();
270 }
271 // Setup toplevel class (which contains library fields/procedures).
272
273 StringIndex import_uri_index =
274 H.CanonicalNameString(library_helper.canonical_name_);
275 library_helper.ReadUntilIncluding(LibraryHelper::kSourceUriIndex);
276 Script& script = ScriptAt(library_helper.source_uri_index_, import_uri_index);
277
278 Class& toplevel_class =
279 Class::Handle(Z, Class::New(library, Symbols::TopLevel(), script,
280 TokenPosition::kNoSource));
281 toplevel_class.set_is_cycle_free();
282 library.set_toplevel_class(toplevel_class);
283
284 const GrowableObjectArray& classes =
285 GrowableObjectArray::Handle(Z, I->object_store()->pending_classes());
286
287 library_helper.ReadUntilExcluding(LibraryHelper::kClasses);
288
289 // Load all classes.
290 int class_count = builder_.ReadListLength(); // read list length.
291 for (intptr_t i = 0; i < class_count; ++i) {
292 classes.Add(ReadClass(library, toplevel_class), Heap::kOld);
293 }
294
295 fields_.Clear();
296 functions_.Clear();
297 ActiveClassScope active_class_scope(&active_class_, &toplevel_class);
298 // Load toplevel fields.
299 intptr_t field_count = builder_.ReadListLength(); // read list length.
300 for (intptr_t i = 0; i < field_count; ++i) {
301 intptr_t field_offset = builder_.ReaderOffset();
302 ActiveMemberScope active_member_scope(&active_class_, NULL);
303 FieldHelper field_helper(&builder_);
304 field_helper.ReadUntilExcluding(FieldHelper::kName);
305
306 const String& name = builder_.ReadNameAsFieldName();
307 field_helper.SetJustRead(FieldHelper::kName);
308 field_helper.ReadUntilExcluding(FieldHelper::kType);
309 const Object& script_class =
310 ClassForScriptAt(toplevel_class, field_helper.source_uri_index_);
311 Field& field = Field::Handle(
312 Z,
313 Field::NewTopLevel(name, field_helper.IsFinal(), field_helper.IsConst(),
314 script_class, field_helper.position_));
315 field.set_kernel_offset(field_offset);
316 const AbstractType& type = T.BuildType(); // read type.
317 field.SetFieldType(type);
318 field_helper.SetJustRead(FieldHelper::kType);
319 field_helper.ReadUntilExcluding(FieldHelper::kInitializer);
320 intptr_t field_initializer_offset = builder_.ReaderOffset();
321 field.set_has_initializer(builder_.PeekTag() == kSomething);
322 field_helper.ReadUntilExcluding(FieldHelper::kEnd);
323 TypedData& kernel_data = builder_.reader_->CopyDataToVMHeap(
324 Z, field_offset, builder_.ReaderOffset());
325 field.set_kernel_data(kernel_data);
326 {
327 // GenerateFieldAccessors reads (some of) the initializer.
328 AlternativeReadingScope alt(builder_.reader_, field_initializer_offset);
329 GenerateFieldAccessors(toplevel_class, field, &field_helper,
330 field_offset);
331 }
332 if (FLAG_enable_mirrors && field_helper.annotation_count_ > 0) {
333 library.AddFieldMetadata(field, TokenPosition::kNoSource, field_offset,
334 &kernel_data);
335 }
336 fields_.Add(&field);
337 library.AddObject(field, name);
338 }
339 toplevel_class.AddFields(fields_);
340
341 // Load toplevel procedures.
342 intptr_t procedure_count = builder_.ReadListLength(); // read list length.
343 for (intptr_t i = 0; i < procedure_count; ++i) {
344 ReadProcedure(library, toplevel_class, false);
345 }
346
347 toplevel_class.SetFunctions(Array::Handle(MakeFunctionsArray()));
348
349 classes.Add(toplevel_class, Heap::kOld);
350 }
351
352 void KernelReader::ReadPreliminaryClass(Class* klass,
353 ClassHelper* class_helper,
354 intptr_t type_parameter_count) {
355 // Note: This assumes that ClassHelper is exactly at the position where
356 // the length of the type parameters have been read, and that the order in
357 // the binary is as follows: [...], kTypeParameters, kSuperClass, kMixinType,
358 // kImplementedClasses, [...].
359
360 // Set type parameters.
361 ReadAndSetupTypeParameters(*klass, type_parameter_count, *klass,
362 Function::Handle(Z));
363
364 // Set super type. Some classes (e.g., Object) do not have one.
365 Tag type_tag = builder_.ReadTag(); // read super class type (part 1).
366 if (type_tag == kSomething) {
367 AbstractType& super_type =
368 T.BuildTypeWithoutFinalization(); // read super class type (part 2).
369 if (super_type.IsMalformed()) H.ReportError("Malformed super type");
370 klass->set_super_type(super_type);
371 }
372
373 class_helper->SetJustRead(ClassHelper::kSuperClass);
374 class_helper->ReadUntilIncluding(ClassHelper::kMixinType);
375
376 // Build implemented interface types
377 intptr_t interface_count = builder_.ReadListLength();
378 const Array& interfaces =
379 Array::Handle(Z, Array::New(interface_count, Heap::kOld));
380 for (intptr_t i = 0; i < interface_count; i++) {
381 const AbstractType& type =
382 T.BuildTypeWithoutFinalization(); // read ith type.
383 if (type.IsMalformed()) H.ReportError("Malformed interface type.");
384 interfaces.SetAt(i, type);
385 }
386 class_helper->SetJustRead(ClassHelper::kImplementedClasses);
387 klass->set_interfaces(interfaces);
388
389 if (class_helper->is_abstract_) klass->set_is_abstract();
390 }
391
392 Class& KernelReader::ReadClass(const Library& library,
393 const Class& toplevel_class) {
394 ClassHelper class_helper(&builder_);
395 intptr_t class_offset = builder_.ReaderOffset();
396 class_helper.ReadUntilIncluding(ClassHelper::kCanonicalName);
397 Class& klass = LookupClass(class_helper.canonical_name_);
398
399 // The class needs to have a script because all the functions in the class
400 // will inherit it. The predicate Function::IsOptimizable uses the absence of
401 // a script to detect test functions that should not be optimized.
402 if (klass.script() == Script::null()) {
403 class_helper.ReadUntilIncluding(ClassHelper::kSourceUriIndex);
404 klass.set_script(ScriptAt(class_helper.source_uri_index_));
405 }
406 if (klass.token_pos() == TokenPosition::kNoSource) {
407 class_helper.ReadUntilIncluding(ClassHelper::kPosition);
408 klass.set_token_pos(class_helper.position_);
409 }
410
411 class_helper.ReadUntilIncluding(ClassHelper::kAnnotations);
412 intptr_t class_offset_after_annotations = builder_.ReaderOffset();
413 class_helper.ReadUntilExcluding(ClassHelper::kTypeParameters);
414 intptr_t type_parameter_counts =
415 builder_.ReadListLength(); // read type_parameters list length.
416
417 ActiveClassScope active_class_scope(&active_class_, &klass);
418 if (!klass.is_cycle_free()) {
419 ReadPreliminaryClass(&klass, &class_helper, type_parameter_counts);
420 } else {
421 for (intptr_t i = 0; i < type_parameter_counts; ++i) {
422 builder_.SkipStringReference(); // read ith name index.
423 builder_.SkipDartType(); // read ith bound.
424 }
425 class_helper.SetJustRead(ClassHelper::kTypeParameters);
426 }
427
428 fields_.Clear();
429 functions_.Clear();
430
431 if (library.raw() == Library::InternalLibrary() &&
432 klass.Name() == Symbols::ClassID().raw()) {
433 // If this is a dart:internal.ClassID class ignore field declarations
434 // contained in the Kernel file and instead inject our own const
435 // fields.
436 klass.InjectCIDFields();
437 } else {
438 class_helper.ReadUntilExcluding(ClassHelper::kFields);
439 int field_count = builder_.ReadListLength(); // read list length.
440 for (intptr_t i = 0; i < field_count; ++i) {
441 intptr_t field_offset = builder_.ReaderOffset();
442 ActiveMemberScope active_member(&active_class_, NULL);
443 FieldHelper field_helper(&builder_);
444 field_helper.ReadUntilExcluding(FieldHelper::kName);
445
446 const String& name = builder_.ReadNameAsFieldName();
447 field_helper.SetJustRead(FieldHelper::kName);
448 field_helper.ReadUntilExcluding(FieldHelper::kType);
449 const AbstractType& type =
450 T.BuildTypeWithoutFinalization(); // read type.
451 field_helper.SetJustRead(FieldHelper::kType);
452 const Object& script_class =
453 ClassForScriptAt(klass, field_helper.source_uri_index_);
454
455 const bool is_reflectable =
456 field_helper.position_.IsReal() &&
457 !(library.is_dart_scheme() && library.IsPrivate(name));
458 Field& field = Field::Handle(
459 Z, Field::New(name, field_helper.IsStatic(),
460 // In the VM all const fields are implicitly final
461 // whereas in Kernel they are not final because they
462 // are not explicitly declared that way.
463 field_helper.IsFinal() || field_helper.IsConst(),
464 field_helper.IsConst(), is_reflectable, script_class,
465 type, field_helper.position_));
466 field.set_kernel_offset(field_offset);
467 field_helper.ReadUntilExcluding(FieldHelper::kInitializer);
468 intptr_t field_initializer_offset = builder_.ReaderOffset();
469 field.set_has_initializer(builder_.PeekTag() == kSomething);
470 field_helper.ReadUntilExcluding(FieldHelper::kEnd);
471 TypedData& kernel_data = builder_.reader_->CopyDataToVMHeap(
472 Z, field_offset, builder_.ReaderOffset());
473 field.set_kernel_data(kernel_data);
474 {
475 // GenerateFieldAccessors reads (some of) the initializer.
476 AlternativeReadingScope alt(builder_.reader_, field_initializer_offset);
477 GenerateFieldAccessors(klass, field, &field_helper, field_offset);
478 }
479 if (FLAG_enable_mirrors && field_helper.annotation_count_ > 0) {
480 library.AddFieldMetadata(field, TokenPosition::kNoSource, field_offset,
481 &kernel_data);
482 }
483 fields_.Add(&field);
484 }
485 klass.AddFields(fields_);
486 class_helper.SetJustRead(ClassHelper::kFields);
487 }
488
489 class_helper.ReadUntilExcluding(ClassHelper::kConstructors);
490 int constructor_count = builder_.ReadListLength(); // read list length.
491 for (intptr_t i = 0; i < constructor_count; ++i) {
492 intptr_t constructor_offset = builder_.ReaderOffset();
493 ActiveMemberScope active_member_scope(&active_class_, NULL);
494 ConstructorHelper constructor_helper(&builder_);
495 constructor_helper.ReadUntilExcluding(ConstructorHelper::kFunction);
496
497 const String& name =
498 H.DartConstructorName(constructor_helper.canonical_name_);
499 Function& function = Function::ZoneHandle(
500 Z, Function::New(name, RawFunction::kConstructor,
501 false, // is_static
502 constructor_helper.IsConst(),
503 false, // is_abstract
504 constructor_helper.IsExternal(),
505 false, // is_native
506 klass, constructor_helper.position_));
507 function.set_end_token_pos(constructor_helper.end_position_);
508 functions_.Add(&function);
509 function.set_kernel_offset(constructor_offset);
510 function.set_result_type(T.ReceiverType(klass));
511
512 FunctionNodeHelper function_node_helper(&builder_);
513 function_node_helper.ReadUntilExcluding(
514 FunctionNodeHelper::kRequiredParameterCount);
515 builder_.SetupFunctionParameters(klass, function,
516 true, // is_method
517 false, // is_closure
518 &function_node_helper);
519 function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kEnd);
520 constructor_helper.SetJustRead(ConstructorHelper::kFunction);
521 constructor_helper.ReadUntilExcluding(ConstructorHelper::kEnd);
522 TypedData& kernel_data = builder_.reader_->CopyDataToVMHeap(
523 Z, constructor_offset, builder_.ReaderOffset());
524 function.set_kernel_data(kernel_data);
525
526 if (FLAG_enable_mirrors && constructor_helper.annotation_count_ > 0) {
527 library.AddFunctionMetadata(function, TokenPosition::kNoSource,
528 constructor_offset, &kernel_data);
529 }
530 }
531 class_helper.SetJustRead(ClassHelper::kConstructors);
532
533 class_helper.ReadUntilExcluding(ClassHelper::kProcedures);
534 int procedure_count = builder_.ReadListLength(); // read list length.
535 for (intptr_t i = 0; i < procedure_count; ++i) {
536 ReadProcedure(library, klass, true);
537 }
538 class_helper.SetJustRead(ClassHelper::kProcedures);
539
540 klass.SetFunctions(Array::Handle(MakeFunctionsArray()));
541
542 if (!klass.is_marked_for_parsing()) {
543 klass.set_is_marked_for_parsing();
544 }
545
546 if (FLAG_enable_mirrors && class_helper.annotation_count_ > 0) {
547 TypedData& header_data = builder_.reader_->CopyDataToVMHeap(
548 Z, class_offset, class_offset_after_annotations);
549 library.AddClassMetadata(klass, toplevel_class, TokenPosition::kNoSource,
550 class_offset, &header_data);
551 }
552
553 class_helper.ReadUntilExcluding(ClassHelper::kEnd);
554
555 return klass;
556 }
557
558 void KernelReader::ReadProcedure(const Library& library,
559 const Class& owner,
560 bool in_class) {
561 intptr_t procedure_offset = builder_.ReaderOffset();
562 ProcedureHelper procedure_helper(&builder_);
563
564 procedure_helper.ReadUntilExcluding(ProcedureHelper::kAnnotations);
565 const String& name = H.DartProcedureName(procedure_helper.canonical_name_);
566 bool is_method = in_class && !procedure_helper.IsStatic();
567 bool is_abstract = procedure_helper.IsAbstract();
568 bool is_external = procedure_helper.IsExternal();
569 String* native_name = NULL;
570 intptr_t annotation_count;
571 if (is_external) {
572 // Maybe it has a native implementation, which is not external as far as
573 // the VM is concerned because it does have an implementation. Check for
574 // an ExternalName annotation and extract the string from it.
575 annotation_count = builder_.ReadListLength(); // read list length.
576 for (int i = 0; i < annotation_count; ++i) {
577 if (builder_.PeekTag() != kConstructorInvocation &&
578 builder_.PeekTag() != kConstConstructorInvocation) {
579 builder_.SkipExpression();
580 continue;
581 }
582 builder_.ReadTag();
583 builder_.ReadPosition();
584 NameIndex annotation_class = H.EnclosingName(
585 builder_.ReadCanonicalNameReference()); // read target reference,
586 ASSERT(H.IsClass(annotation_class));
587 StringIndex class_name_index = H.CanonicalNameString(annotation_class);
588 // Just compare by name, do not generate the annotation class.
589 if (!H.StringEquals(class_name_index, "ExternalName")) {
590 builder_.SkipArguments();
591 continue;
592 }
593 ASSERT(H.IsLibrary(H.CanonicalNameParent(annotation_class)));
594 StringIndex library_name_index =
595 H.CanonicalNameString(H.CanonicalNameParent(annotation_class));
596 if (!H.StringEquals(library_name_index, "dart:_internal")) {
597 builder_.SkipArguments();
598 continue;
599 }
600
601 is_external = false;
602 // Read arguments:
603 intptr_t total_arguments = builder_.ReadUInt(); // read argument count.
604 builder_.SkipListOfDartTypes(); // read list of types.
605 intptr_t positional_arguments = builder_.ReadListLength();
606 ASSERT(total_arguments == 1 && positional_arguments == 1);
607
608 Tag tag = builder_.ReadTag();
609 ASSERT(tag == kStringLiteral);
610 native_name = &H.DartSymbol(
611 builder_.ReadStringReference()); // read index into string table.
612
613 // List of named.
614 intptr_t list_length = builder_.ReadListLength(); // read list length.
615 ASSERT(list_length == 0);
616
617 // Skip remaining annotations
618 for (++i; i < annotation_count; ++i) {
619 builder_.SkipExpression(); // read ith annotation.
620 }
621
622 break;
623 }
624 procedure_helper.SetJustRead(ProcedureHelper::kAnnotations);
625 } else {
626 procedure_helper.ReadUntilIncluding(ProcedureHelper::kAnnotations);
627 annotation_count = procedure_helper.annotation_count_;
628 }
629 const Object& script_class =
630 ClassForScriptAt(owner, procedure_helper.source_uri_index_);
631 Function& function = Function::ZoneHandle(
632 Z, Function::New(name, GetFunctionType(procedure_helper.kind_),
633 !is_method, // is_static
634 false, // is_const
635 is_abstract, is_external,
636 native_name != NULL, // is_native
637 script_class, procedure_helper.position_));
638 function.set_end_token_pos(procedure_helper.end_position_);
639 functions_.Add(&function);
640 function.set_kernel_offset(procedure_offset);
641
642 ActiveMemberScope active_member(&active_class_, &function);
643
644 procedure_helper.ReadUntilExcluding(ProcedureHelper::kFunction);
645 Tag function_node_tag = builder_.ReadTag();
646 ASSERT(function_node_tag == kSomething);
647 FunctionNodeHelper function_node_helper(&builder_);
648 function_node_helper.ReadUntilIncluding(FunctionNodeHelper::kDartAsyncMarker);
649 function.set_is_debuggable(function_node_helper.dart_async_marker_ ==
650 FunctionNodeHelper::kSync);
651 switch (function_node_helper.dart_async_marker_) {
652 case FunctionNodeHelper::kSyncStar:
653 function.set_modifier(RawFunction::kSyncGen);
654 break;
655 case FunctionNodeHelper::kAsync:
656 function.set_modifier(RawFunction::kAsync);
657 function.set_is_inlinable(!FLAG_causal_async_stacks);
658 break;
659 case FunctionNodeHelper::kAsyncStar:
660 function.set_modifier(RawFunction::kAsyncGen);
661 function.set_is_inlinable(!FLAG_causal_async_stacks);
662 break;
663 default:
664 // no special modifier
665 break;
666 }
667 ASSERT(function_node_helper.async_marker_ == FunctionNodeHelper::kSync);
668
669 if (native_name != NULL) {
670 function.set_native_name(*native_name);
671 }
672
673 function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kTypeParameters);
674 if (!function.IsFactory()) {
675 // Read type_parameters list length.
676 intptr_t type_parameter_count = builder_.ReadListLength();
677 // Set type parameters.
678 ReadAndSetupTypeParameters(function, type_parameter_count, Class::Handle(Z),
679 function);
680 function_node_helper.SetJustRead(FunctionNodeHelper::kTypeParameters);
681 }
682
683 function_node_helper.ReadUntilExcluding(
684 FunctionNodeHelper::kRequiredParameterCount);
685 builder_.SetupFunctionParameters(owner, function, is_method,
686 false, // is_closure
687 &function_node_helper);
688 function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kEnd);
689 procedure_helper.SetJustRead(ProcedureHelper::kFunction);
690
691 if (!in_class) {
692 library.AddObject(function, name);
693 ASSERT(!Object::Handle(
694 Z, library.LookupObjectAllowPrivate(
695 H.DartProcedureName(procedure_helper.canonical_name_)))
696 .IsNull());
697 }
698
699 procedure_helper.ReadUntilExcluding(ProcedureHelper::kEnd);
700 TypedData& kernel_data = builder_.reader_->CopyDataToVMHeap(
701 Z, procedure_offset, builder_.ReaderOffset());
702 function.set_kernel_data(kernel_data);
703
704 if (FLAG_enable_mirrors && annotation_count > 0) {
705 library.AddFunctionMetadata(function, TokenPosition::kNoSource,
706 procedure_offset, &kernel_data);
707 }
708 }
709
710 void KernelReader::ReadAndSetupTypeParameters(
711 const Object& set_on,
712 intptr_t type_parameter_count,
713 const Class& parameterized_class,
714 const Function& parameterized_function) {
715 ASSERT(type_parameter_count >= 0);
716 if (type_parameter_count == 0) {
717 return;
718 }
719 // First setup the type parameters, so if any of the following code uses it
720 // (in a recursive way) we're fine.
721 TypeArguments& type_parameters =
722 TypeArguments::Handle(Z, TypeArguments::null());
723 TypeParameter& parameter = TypeParameter::Handle(Z);
724 Type& null_bound = Type::Handle(Z, Type::null());
725
726 // Step a) Create array of [TypeParameter] objects (without bound).
727 type_parameters = TypeArguments::New(type_parameter_count);
728 {
729 AlternativeReadingScope alt(builder_.reader_);
730 for (intptr_t i = 0; i < type_parameter_count; i++) {
731 parameter = TypeParameter::New(
732 parameterized_class, parameterized_function, i,
733 H.DartSymbol(builder_.ReadStringReference()), // read ith name index.
734 null_bound, TokenPosition::kNoSource);
735 type_parameters.SetTypeAt(i, parameter);
736 builder_.SkipDartType(); // read guard.
737 }
738 }
739
740 ASSERT(set_on.IsClass() || set_on.IsFunction());
741 if (set_on.IsClass()) {
742 Class::Cast(set_on).set_type_parameters(type_parameters);
743 } else {
744 Function::Cast(set_on).set_type_parameters(type_parameters);
745 }
746
747 // Step b) Fill in the bounds of all [TypeParameter]s.
748 for (intptr_t i = 0; i < type_parameter_count; i++) {
749 builder_.SkipStringReference(); // read ith name index.
750
751 // TODO(github.com/dart-lang/kernel/issues/42): This should be handled
752 // by the frontend.
753 parameter ^= type_parameters.TypeAt(i);
754 Tag tag = builder_.PeekTag(); // peek ith bound type.
755 if (tag == kDynamicType) {
756 builder_.SkipDartType(); // read ith bound.
757 parameter.set_bound(Type::Handle(Z, I->object_store()->object_type()));
758 } else {
759 AbstractType& bound =
760 T.BuildTypeWithoutFinalization(); // read ith bound.
761 if (bound.IsMalformedOrMalbounded()) {
762 bound = I->object_store()->object_type();
763 }
764 parameter.set_bound(bound);
765 }
766 }
767 }
768
769 const Object& KernelReader::ClassForScriptAt(const Class& klass,
770 intptr_t source_uri_index) {
771 Script& correct_script = ScriptAt(source_uri_index);
772 if (klass.script() != correct_script.raw()) {
773 // Use cache for patch classes. This works best for in-order usages.
774 PatchClass& patch_class = PatchClass::ZoneHandle(Z);
775 patch_class ^= patch_classes_.At(source_uri_index);
776 if (patch_class.IsNull() || patch_class.origin_class() != klass.raw()) {
777 patch_class = PatchClass::New(klass, correct_script);
778 patch_classes_.SetAt(source_uri_index, patch_class);
779 }
780 return patch_class;
781 }
782 return klass;
783 }
784
785 Script& KernelReader::ScriptAt(intptr_t index, StringIndex import_uri) {
786 Script& script = Script::ZoneHandle(Z);
787 script ^= scripts_.At(index);
788 if (script.IsNull()) {
789 // Create script with correct uri(s).
790 String& uri_string = builder_.SourceTableUriFor(index);
791 String& import_uri_string =
792 import_uri == -1 ? uri_string : H.DartString(import_uri, Heap::kOld);
793 script = Script::New(import_uri_string, uri_string,
794 builder_.GetSourceFor(index), RawScript::kKernelTag);
795 script.set_kernel_script_index(index);
796 script.set_kernel_string_offsets(H.string_offsets());
797 script.set_kernel_string_data(H.string_data());
798 script.set_kernel_canonical_names(H.canonical_names());
799 scripts_.SetAt(index, script);
800
801 script.set_line_starts(builder_.GetLineStartsFor(index));
802 script.set_debug_positions(Array::Handle(Array::null()));
803 script.set_yield_positions(Array::Handle(Array::null()));
804 }
805 return script;
806 }
807
808 void KernelReader::GenerateFieldAccessors(const Class& klass,
809 const Field& field,
810 FieldHelper* field_helper,
811 intptr_t field_offset) {
812 Tag tag = builder_.PeekTag();
813 if (field_helper->IsStatic() && tag == kNothing) {
814 // Static fields without an initializer are implicitly initialized to null.
815 // We do not need a getter.
816 field.SetStaticValue(Instance::Handle(Z), true);
817 return;
818 }
819 if (tag == kSomething) {
820 SimpleExpressionConverter converter(&H, &builder_);
821 const bool has_simple_initializer =
822 converter.IsSimple(builder_.ReaderOffset() + 1); // ignore the tag.
823 if (field_helper->IsStatic()) {
824 // Static fields with initializers either have the static value set to the
825 // initializer value if it is simple enough or else set to an
826 // uninitialized sentinel.
827 if (has_simple_initializer) {
828 // We do not need a getter.
829 field.SetStaticValue(converter.SimpleValue(), true);
830 return;
831 }
832 // We do need a getter that evaluates the initializer if necessary.
833 field.SetStaticValue(Object::sentinel(), true);
834 } else if (has_simple_initializer) {
835 // Note: optimizer relies on DoubleInitialized bit in its field-unboxing
836 // heuristics. See JitOptimizer::VisitStoreInstanceField for more details.
837 field.RecordStore(converter.SimpleValue());
838 if (!converter.SimpleValue().IsNull() &&
839 converter.SimpleValue().IsDouble()) {
840 field.set_is_double_initialized(true);
841 }
842 }
843 }
844
845 const String& getter_name = H.DartGetterName(field_helper->canonical_name_);
846 const Object& script_class =
847 ClassForScriptAt(klass, field_helper->source_uri_index_);
848 Function& getter = Function::ZoneHandle(
849 Z,
850 Function::New(
851 getter_name,
852 field_helper->IsStatic() ? RawFunction::kImplicitStaticFinalGetter
853 : RawFunction::kImplicitGetter,
854 field_helper->IsStatic(),
855 // The functions created by the parser have is_const for static fields
856 // that are const (not just final) and they have is_const for
857 // non-static
858 // fields that are final.
859 field_helper->IsStatic() ? field_helper->IsConst()
860 : field_helper->IsFinal(),
861 false, // is_abstract
862 false, // is_external
863 false, // is_native
864 script_class, field_helper->position_));
865 functions_.Add(&getter);
866 getter.set_kernel_data(TypedData::Handle(Z, field.kernel_data()));
867 getter.set_end_token_pos(field_helper->end_position_);
868 getter.set_kernel_offset(field_offset);
869 getter.set_result_type(AbstractType::Handle(Z, field.type()));
870 getter.set_is_debuggable(false);
871 SetupFieldAccessorFunction(klass, getter);
872
873 if (!field_helper->IsStatic() && !field_helper->IsFinal()) {
874 // Only static fields can be const.
875 ASSERT(!field_helper->IsConst());
876 const String& setter_name = H.DartSetterName(field_helper->canonical_name_);
877 Function& setter = Function::ZoneHandle(
878 Z, Function::New(setter_name, RawFunction::kImplicitSetter,
879 false, // is_static
880 false, // is_const
881 false, // is_abstract
882 false, // is_external
883 false, // is_native
884 script_class, field_helper->position_));
885 functions_.Add(&setter);
886 setter.set_kernel_data(TypedData::Handle(Z, field.kernel_data()));
887 setter.set_end_token_pos(field_helper->end_position_);
888 setter.set_kernel_offset(field_offset);
889 setter.set_result_type(Object::void_type());
890 setter.set_is_debuggable(false);
891 SetupFieldAccessorFunction(klass, setter);
892 }
893 }
894
895 void KernelReader::SetupFieldAccessorFunction(const Class& klass,
896 const Function& function) {
897 bool is_setter = function.IsImplicitSetterFunction();
898 bool is_method = !function.IsStaticFunction();
899 intptr_t parameter_count = (is_method ? 1 : 0) + (is_setter ? 1 : 0);
900
901 function.SetNumOptionalParameters(0, false);
902 function.set_num_fixed_parameters(parameter_count);
903 function.set_parameter_types(
904 Array::Handle(Z, Array::New(parameter_count, Heap::kOld)));
905 function.set_parameter_names(
906 Array::Handle(Z, Array::New(parameter_count, Heap::kOld)));
907
908 intptr_t pos = 0;
909 if (is_method) {
910 function.SetParameterTypeAt(pos, T.ReceiverType(klass));
911 function.SetParameterNameAt(pos, Symbols::This());
912 pos++;
913 }
914 if (is_setter) {
915 function.SetParameterTypeAt(pos, AbstractType::dynamic_type());
916 function.SetParameterNameAt(pos, Symbols::Value());
917 pos++;
918 }
919 }
920
921 Library& KernelReader::LookupLibrary(NameIndex library) {
922 Library* handle = NULL;
923 if (!libraries_.Lookup(library, &handle)) {
924 const String& url = H.DartSymbol(H.CanonicalNameString(library));
925 handle = &Library::Handle(Z, Library::LookupLibrary(thread_, url));
926 if (handle->IsNull()) {
927 *handle = Library::New(url);
928 handle->Register(thread_);
929 }
930 ASSERT(!handle->IsNull());
931 libraries_.Insert(library, handle);
932 }
933 return *handle;
934 }
935
936 Class& KernelReader::LookupClass(NameIndex klass) {
937 Class* handle = NULL;
938 if (!classes_.Lookup(klass, &handle)) {
939 Library& library = LookupLibrary(H.CanonicalNameParent(klass));
940 const String& name = H.DartClassName(klass);
941 handle = &Class::Handle(Z, library.LookupClass(name));
942 if (handle->IsNull()) {
943 *handle = Class::New(library, name, Script::Handle(Z),
944 TokenPosition::kNoSource);
945 library.AddClass(*handle);
946 }
947 // Insert the class in the cache before calling ReadPreliminaryClass so
948 // we do not risk allocating the class again by calling LookupClass
949 // recursively from ReadPreliminaryClass for the same class.
950 classes_.Insert(klass, handle);
951 }
952 return *handle;
953 }
954
955 RawFunction::Kind KernelReader::GetFunctionType(
956 ProcedureHelper::Kind procedure_kind) {
957 intptr_t lookuptable[] = {
958 RawFunction::kRegularFunction, // Procedure::kMethod
959 RawFunction::kGetterFunction, // Procedure::kGetter
960 RawFunction::kSetterFunction, // Procedure::kSetter
961 RawFunction::kRegularFunction, // Procedure::kOperator
962 RawFunction::kConstructor, // Procedure::kFactory
963 };
964 intptr_t kind = static_cast<int>(procedure_kind);
965 ASSERT(0 <= kind && kind <= ProcedureHelper::kFactory);
966 return static_cast<RawFunction::Kind>(lookuptable[kind]);
967 }
968
969 bool KernelReader::FieldHasFunctionLiteralInitializer(const Field& field,
970 TokenPosition* start,
971 TokenPosition* end) {
972 Zone* zone = Thread::Current()->zone();
973 const Script& script = Script::Handle(zone, field.Script());
974
975 TranslationHelper translation_helper(
976 Thread::Current(), script.kernel_string_offsets(),
977 script.kernel_string_data(), script.kernel_canonical_names());
978
979 StreamingFlowGraphBuilder builder(
980 &translation_helper, zone, field.kernel_offset(),
981 TypedData::Handle(zone, field.kernel_data()));
982 kernel::FieldHelper field_helper(&builder);
983 field_helper.ReadUntilExcluding(kernel::FieldHelper::kEnd, true);
984 return field_helper.FieldHasFunctionLiteralInitializer(start, end);
985 }
986
987 ParsedFunction* ParseStaticFieldInitializer(Zone* zone, const Field& field) {
988 Thread* thread = Thread::Current();
989
990 String& init_name = String::Handle(zone, field.name());
991 init_name = Symbols::FromConcat(thread, Symbols::InitPrefix(), init_name);
992
993 // Create a static initializer.
994 const Object& owner = Object::Handle(field.RawOwner());
995 const Function& initializer_fun = Function::ZoneHandle(
996 zone, Function::New(init_name, RawFunction::kImplicitStaticFinalGetter,
997 true, // is_static
998 false, // is_const
999 false, // is_abstract
1000 false, // is_external
1001 false, // is_native
1002 owner, TokenPosition::kNoSource));
1003 initializer_fun.set_kernel_data(TypedData::Handle(zone, field.kernel_data()));
1004 initializer_fun.set_kernel_offset(field.kernel_offset());
1005 initializer_fun.set_result_type(AbstractType::Handle(zone, field.type()));
1006 initializer_fun.set_is_debuggable(false);
1007 initializer_fun.set_is_reflectable(false);
1008 initializer_fun.set_is_inlinable(false);
1009 return new (zone) ParsedFunction(thread, initializer_fun);
1010 }
1011
1012 } // namespace kernel
1013 } // namespace dart
1014 #endif // !defined(DART_PRECOMPILED_RUNTIME)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698