OLD | NEW |
| (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) | |
OLD | NEW |