Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
kernel.cc
Go to the documentation of this file.
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#if !defined(DART_PRECOMPILED_RUNTIME)
6
7#include "vm/kernel.h"
8
9#include "vm/bit_vector.h"
13#include "vm/longjump.h"
14#include "vm/object_store.h"
15#include "vm/parser.h" // For Parser::kParameter* constants.
16#include "vm/stack_frame.h"
17
18namespace dart {
19namespace kernel {
20
21KernelLineStartsReader::KernelLineStartsReader(
22 const dart::TypedData& line_starts_data,
23 dart::Zone* zone)
24 : line_starts_data_(line_starts_data) {
25 TypedDataElementType type = line_starts_data_.ElementType();
26 if (type == kUint16ArrayElement) {
27 helper_ = new KernelUint16LineStartsHelper();
28 } else if (type == kUint32ArrayElement) {
29 helper_ = new KernelUint32LineStartsHelper();
30 } else {
32 }
33}
34
35uint32_t KernelLineStartsReader::MaxPosition() const {
36 const intptr_t line_count = line_starts_data_.Length();
37 if (line_count == 0) {
38 return 0;
39 }
40 return helper_->At(line_starts_data_, line_count - 1);
41}
42
43bool KernelLineStartsReader::LocationForPosition(intptr_t position,
44 intptr_t* line,
45 intptr_t* col) const {
46 const intptr_t line_count = line_starts_data_.Length();
47 if (position < 0 || static_cast<uint32_t>(position) > MaxPosition() ||
48 line_count == 0) {
49 return false;
50 }
51
52 intptr_t lo = 0;
53 intptr_t hi = line_count;
54 while (hi > lo + 1) {
55 const intptr_t mid = lo + (hi - lo) / 2;
56 const intptr_t mid_position = helper_->At(line_starts_data_, mid);
57 if (mid_position > position) {
58 hi = mid;
59 } else {
60 lo = mid;
61 }
62 }
63 *line = lo + 1;
64 if (col != nullptr) {
65 *col = position - helper_->At(line_starts_data_, lo) + 1;
66 }
67
68 return true;
69}
70
71bool KernelLineStartsReader::TokenRangeAtLine(
72 intptr_t line_number,
73 TokenPosition* first_token_index,
74 TokenPosition* last_token_index) const {
75 const intptr_t line_count = line_starts_data_.Length();
76 if (line_number <= 0 || line_number > line_count) {
77 return false;
78 }
79 *first_token_index = dart::TokenPosition::Deserialize(
80 helper_->At(line_starts_data_, line_number - 1));
81 if (line_number == line_count) {
82 *last_token_index = *first_token_index;
83 } else {
84 *last_token_index = dart::TokenPosition::Deserialize(
85 helper_->At(line_starts_data_, line_number) - 1);
86 }
87 return true;
88}
89
90uint32_t KernelLineStartsReader::KernelUint16LineStartsHelper::At(
91 const dart::TypedData& data,
92 intptr_t index) const {
93 return data.GetUint16(index << 1);
94}
95
96uint32_t KernelLineStartsReader::KernelUint32LineStartsHelper::At(
97 const dart::TypedData& data,
98 intptr_t index) const {
99 return data.GetUint32(index << 2);
100}
101
103 public:
105 Zone* zone,
106 TranslationHelper* translation_helper,
107 const Script& script,
108 const TypedDataView& data,
109 intptr_t data_program_offset,
110 intptr_t initial_script_index,
111 intptr_t record_for_script_id,
112 GrowableArray<intptr_t>* record_token_positions_into)
113 : KernelReaderHelper(zone, translation_helper, data, data_program_offset),
114 current_script_id_(initial_script_index),
115 record_for_script_id_(record_for_script_id),
116 record_token_positions_into_(record_token_positions_into) {}
117
118 void CollectTokenPositions(intptr_t kernel_offset);
119
120 void RecordTokenPosition(TokenPosition position) override;
121
122 void set_current_script_id(intptr_t id) override { current_script_id_ = id; }
123
124 private:
125 intptr_t current_script_id_;
126 intptr_t record_for_script_id_;
127 GrowableArray<intptr_t>* record_token_positions_into_;
128
130};
131
132void KernelTokenPositionCollector::CollectTokenPositions(
133 intptr_t kernel_offset) {
134 SetOffset(kernel_offset);
135
136 const Tag tag = PeekTag();
137 if (tag == kProcedure) {
138 ProcedureHelper procedure_helper(this);
139 procedure_helper.ReadUntilExcluding(ProcedureHelper::kEnd);
140 } else if (tag == kConstructor) {
141 ConstructorHelper constructor_helper(this);
142 constructor_helper.ReadUntilExcluding(ConstructorHelper::kEnd);
143 } else if (tag == kFunctionNode) {
144 FunctionNodeHelper function_node_helper(this);
145 function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kEnd);
146 } else if (tag == kField) {
147 FieldHelper field_helper(this);
148 field_helper.ReadUntilExcluding(FieldHelper::kEnd);
149 } else if (tag == kClass) {
150 ClassHelper class_helper(this);
151 class_helper.ReadUntilExcluding(ClassHelper::kEnd);
152 } else {
153 ReportUnexpectedTag("a class or a member", tag);
154 UNREACHABLE();
155 }
156}
157
158void KernelTokenPositionCollector::RecordTokenPosition(TokenPosition position) {
159 if (record_for_script_id_ == current_script_id_ &&
160 record_token_positions_into_ != nullptr && position.IsReal()) {
161 record_token_positions_into_->Add(position.Serialize());
162 }
163}
164
165static int LowestFirst(const intptr_t* a, const intptr_t* b) {
166 return *a - *b;
167}
168
169/**
170 * If index exists as sublist in list, sort the sublist from lowest to highest,
171 * then copy it, as Smis and without duplicates,
172 * to a new Array in Heap::kOld which is returned.
173 * Note that the source list is both sorted and de-duplicated as well, but will
174 * possibly contain duplicate and unsorted data at the end.
175 * Otherwise (when sublist doesn't exist in list) return new empty array.
176 */
178 intptr_t size = source->length();
179 if (size == 0) {
180 return Object::empty_array().ptr();
181 }
182
183 source->Sort(LowestFirst);
184
185 intptr_t last = 0;
186 for (intptr_t current = 1; current < size; ++current) {
187 if (source->At(last) != source->At(current)) {
188 (*source)[++last] = source->At(current);
189 }
190 }
191 Array& array_object = Array::Handle();
192 array_object = Array::New(last + 1, Heap::kOld);
193 Smi& smi_value = Smi::Handle();
194 for (intptr_t i = 0; i <= last; ++i) {
195 smi_value = Smi::New(source->At(i));
196 array_object.SetAt(i, smi_value);
197 }
198 return array_object.ptr();
199}
200
202 const TypedDataView& kernel_data,
203 const Script& script,
204 intptr_t kernel_offset,
205 intptr_t data_kernel_offset,
206 Zone* zone,
207 TranslationHelper* helper,
208 GrowableArray<intptr_t>* token_positions) {
209 if (kernel_data.IsNull()) {
210 return;
211 }
212
213 KernelTokenPositionCollector token_position_collector(
214 zone, helper, script, kernel_data, data_kernel_offset,
215 script.kernel_script_index(), script.kernel_script_index(),
216 token_positions);
217
218 token_position_collector.CollectTokenPositions(kernel_offset);
219}
220
221} // namespace kernel
222
223void Script::CollectTokenPositionsFor() const {
224 Thread* thread = Thread::Current();
225 Zone* zone = thread->zone();
226
227 const auto& kernel_info =
228 KernelProgramInfo::Handle(zone, kernel_program_info());
229
230 kernel::TranslationHelper helper(thread);
231 helper.InitFromKernelProgramInfo(kernel_info);
232
233 GrowableArray<intptr_t> token_positions(10);
234
235 auto isolate_group = thread->isolate_group();
236 const GrowableObjectArray& libs = GrowableObjectArray::Handle(
237 zone, isolate_group->object_store()->libraries());
238 Library& lib = Library::Handle(zone);
239 Object& entry = Object::Handle(zone);
240 Script& entry_script = Script::Handle(zone);
241 auto& data = TypedDataView::Handle(zone);
242
243 auto& interesting_script = *this;
244
245 auto& temp_array = Array::Handle(zone);
246 auto& temp_field = Field::Handle(zone);
247 auto& temp_function = Function::Handle(zone);
248 for (intptr_t i = 0; i < libs.Length(); i++) {
249 lib ^= libs.At(i);
251 DictionaryIterator it(lib);
252 while (it.HasNext()) {
253 entry = it.GetNext();
254 data = TypedDataView::null();
255 if (entry.IsClass()) {
256 const Class& klass = Class::Cast(entry);
257 if (klass.script() == interesting_script.ptr()) {
258 token_positions.Add(klass.token_pos().Serialize());
259 token_positions.Add(klass.end_token_pos().Serialize());
260 }
261 if (klass.is_finalized()) {
262 temp_array = klass.fields();
263 for (intptr_t i = 0; i < temp_array.Length(); ++i) {
264 temp_field ^= temp_array.At(i);
265 if (temp_field.kernel_offset() <= 0) {
266 // Skip artificially injected fields.
267 continue;
268 }
269 entry_script = temp_field.Script();
270 if (entry_script.ptr() != interesting_script.ptr()) {
271 continue;
272 }
273 data = temp_field.KernelLibrary();
274 CollectKernelLibraryTokenPositions(data, interesting_script,
275 temp_field.kernel_offset(),
276 temp_field.KernelLibraryOffset(),
277 zone, &helper, &token_positions);
278 }
279 temp_array = klass.current_functions();
280 for (intptr_t i = 0; i < temp_array.Length(); ++i) {
281 temp_function ^= temp_array.At(i);
282 entry_script = temp_function.script();
283 if (entry_script.ptr() != interesting_script.ptr()) {
284 continue;
285 }
286 data = temp_function.KernelLibrary();
287 CollectKernelLibraryTokenPositions(
288 data, interesting_script, temp_function.kernel_offset(),
289 temp_function.KernelLibraryOffset(), zone, &helper,
290 &token_positions);
291 }
292 } else {
293 // Class isn't finalized yet: read the data attached to it.
294 ASSERT(klass.kernel_offset() > 0);
295 data = lib.KernelLibrary();
296 ASSERT(!data.IsNull());
297 const intptr_t library_kernel_offset = lib.KernelLibraryOffset();
298 ASSERT(library_kernel_offset > 0);
299 const intptr_t class_offset = klass.kernel_offset();
300
301 entry_script = klass.script();
302 if (entry_script.ptr() != interesting_script.ptr()) {
303 continue;
304 }
305 CollectKernelLibraryTokenPositions(
306 data, interesting_script, class_offset, library_kernel_offset,
307 zone, &helper, &token_positions);
308 }
309 } else if (entry.IsFunction()) {
310 temp_function ^= entry.ptr();
311 entry_script = temp_function.script();
312 if (entry_script.ptr() != interesting_script.ptr()) {
313 continue;
314 }
315 data = temp_function.KernelLibrary();
316 CollectKernelLibraryTokenPositions(data, interesting_script,
317 temp_function.kernel_offset(),
318 temp_function.KernelLibraryOffset(),
319 zone, &helper, &token_positions);
320 } else if (entry.IsField()) {
321 const Field& field = Field::Cast(entry);
322 if (field.kernel_offset() <= 0) {
323 // Skip artificially injected fields.
324 continue;
325 }
326 entry_script = field.Script();
327 if (entry_script.ptr() != interesting_script.ptr()) {
328 continue;
329 }
330 data = field.KernelLibrary();
331 CollectKernelLibraryTokenPositions(
332 data, interesting_script, field.kernel_offset(),
333 field.KernelLibraryOffset(), zone, &helper, &token_positions);
334 }
335 }
336 }
337
338 Script& script = Script::Handle(zone, interesting_script.ptr());
339 Array& array_object = Array::Handle(zone);
340 array_object = kernel::AsSortedDuplicateFreeArray(&token_positions);
341 script.set_debug_positions(array_object);
342}
343
344#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
345ArrayPtr Script::CollectConstConstructorCoverageFrom() const {
346 Thread* thread = Thread::Current();
347 Zone* zone = thread->zone();
348 kernel::TranslationHelper helper(thread);
349
350 const auto& interesting_script = *this;
351
352 const auto& kernel_info =
353 KernelProgramInfo::Handle(zone, kernel_program_info());
354 helper.InitFromKernelProgramInfo(kernel_info);
355
356 const auto& data =
357 TypedDataView::Handle(zone, interesting_script.constant_coverage());
358
359 kernel::KernelReaderHelper kernel_reader(zone, &helper, data, 0);
360
361 // Read "constant coverage constructors".
362 const intptr_t constant_coverage_constructors =
363 kernel_reader.ReadListLength();
364 const Array& constructors =
365 Array::Handle(Array::New(constant_coverage_constructors));
366 for (intptr_t i = 0; i < constant_coverage_constructors; ++i) {
367 kernel::NameIndex kernel_name = kernel_reader.ReadCanonicalNameReference();
368 Class& klass = Class::ZoneHandle(
369 zone,
370 helper.LookupClassByKernelClass(helper.EnclosingName(kernel_name)));
371 const Function& target = Function::ZoneHandle(
372 zone, helper.LookupConstructorByKernelConstructor(klass, kernel_name));
373 constructors.SetAt(i, target);
374 }
375 return constructors.ptr();
376}
377#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
378
379namespace kernel {
380
381ObjectPtr EvaluateStaticConstFieldInitializer(const Field& field) {
382 ASSERT(field.is_static() && field.is_const());
383
384 LongJumpScope jump;
385 if (setjmp(*jump.Set()) == 0) {
386 Thread* thread = Thread::Current();
387 Zone* zone = thread->zone();
388 TranslationHelper helper(thread);
389 auto& kernel_program_info =
390 KernelProgramInfo::Handle(zone, field.KernelProgramInfo());
391 helper.InitFromKernelProgramInfo(kernel_program_info);
392
393 const Class& owner_class = Class::Handle(zone, field.Owner());
394 ActiveClass active_class;
395 ActiveClassScope active_class_scope(&active_class, &owner_class);
396
397 KernelReaderHelper kernel_reader(
398 zone, &helper, TypedDataView::Handle(zone, field.KernelLibrary()),
399 field.KernelLibraryOffset());
400 kernel_reader.SetOffset(field.kernel_offset());
401 ConstantReader constant_reader(&kernel_reader, &active_class);
402
403 FieldHelper field_helper(&kernel_reader);
404 field_helper.ReadUntilExcluding(FieldHelper::kInitializer);
405 ASSERT(field_helper.IsConst());
406
407 return constant_reader.ReadConstantInitializer();
408 } else {
409 return Thread::Current()->StealStickyError();
410 }
411}
412
413class MetadataEvaluator : public KernelReaderHelper {
414 public:
415 MetadataEvaluator(Zone* zone,
416 TranslationHelper* translation_helper,
417 const TypedDataView& data,
418 intptr_t data_program_offset,
419 ActiveClass* active_class)
420 : KernelReaderHelper(zone, translation_helper, data, data_program_offset),
421 constant_reader_(this, active_class) {}
422
423 ObjectPtr EvaluateMetadata(intptr_t kernel_offset,
424 bool is_annotations_offset) {
425 SetOffset(kernel_offset);
426
427 // Library and LibraryDependency objects do not have a tag in kernel binary.
428 // Synthetic metadata fields corresponding to these objects keep kernel
429 // offset of annotations list instead of annotated object.
430 if (!is_annotations_offset) {
431 const Tag tag = PeekTag();
432
433 if (tag == kClass) {
434 ClassHelper class_helper(this);
435 class_helper.ReadUntilExcluding(ClassHelper::kAnnotations);
436 } else if (tag == kProcedure) {
437 ProcedureHelper procedure_helper(this);
438 procedure_helper.ReadUntilExcluding(ProcedureHelper::kAnnotations);
439 } else if (tag == kField) {
440 FieldHelper field_helper(this);
441 field_helper.ReadUntilExcluding(FieldHelper::kAnnotations);
442 } else if (tag == kConstructor) {
443 ConstructorHelper constructor_helper(this);
444 constructor_helper.ReadUntilExcluding(ConstructorHelper::kAnnotations);
445 } else if (tag == kFunctionDeclaration) {
446 ReadTag();
447 ReadPosition(); // fileOffset
448 VariableDeclarationHelper variable_declaration_helper(this);
449 variable_declaration_helper.ReadUntilExcluding(
450 VariableDeclarationHelper::kAnnotations);
451 } else {
452 FATAL("No support for metadata on this type of kernel node: %" Pd32
453 "\n",
454 tag);
455 }
456 }
457
458 return constant_reader_.ReadAnnotations();
459 }
460
461 private:
462 ConstantReader constant_reader_;
463
464 DISALLOW_COPY_AND_ASSIGN(MetadataEvaluator);
465};
466
467ObjectPtr EvaluateMetadata(const Library& library,
468 intptr_t kernel_offset,
469 bool is_annotations_offset) {
470 LongJumpScope jump;
471 if (setjmp(*jump.Set()) == 0) {
472 Thread* thread = Thread::Current();
473 Zone* zone = thread->zone();
474 TranslationHelper helper(thread);
475 const auto& kernel_info =
476 KernelProgramInfo::Handle(zone, library.kernel_program_info());
477 helper.InitFromKernelProgramInfo(kernel_info);
478
479 const Class& owner_class = Class::Handle(zone, library.toplevel_class());
480 ActiveClass active_class;
481 ActiveClassScope active_class_scope(&active_class, &owner_class);
482
483 MetadataEvaluator metadata_evaluator(
484 zone, &helper, TypedDataView::Handle(zone, library.KernelLibrary()),
485 library.KernelLibraryOffset(), &active_class);
486
487 return metadata_evaluator.EvaluateMetadata(kernel_offset,
488 is_annotations_offset);
489
490 } else {
491 return Thread::Current()->StealStickyError();
492 }
493}
494
495class ParameterDescriptorBuilder : public KernelReaderHelper {
496 public:
497 ParameterDescriptorBuilder(TranslationHelper* translation_helper,
498 Zone* zone,
499 const TypedDataView& data,
500 intptr_t data_program_offset,
501 ActiveClass* active_class)
502 : KernelReaderHelper(zone, translation_helper, data, data_program_offset),
503 constant_reader_(this, active_class) {}
504
505 ObjectPtr BuildParameterDescriptor(const Function& function);
506
507 private:
508 ConstantReader constant_reader_;
509
510 DISALLOW_COPY_AND_ASSIGN(ParameterDescriptorBuilder);
511};
512
513ObjectPtr ParameterDescriptorBuilder::BuildParameterDescriptor(
514 const Function& function) {
515 SetOffset(function.kernel_offset());
516 ReadUntilFunctionNode();
517 FunctionNodeHelper function_node_helper(this);
518 function_node_helper.ReadUntilExcluding(
519 FunctionNodeHelper::kPositionalParameters);
520 intptr_t param_count = function_node_helper.total_parameter_count_;
521 intptr_t positional_count = ReadListLength(); // read list length.
522 intptr_t named_parameter_count = param_count - positional_count;
523
524 const Array& param_descriptor = Array::Handle(
525 Array::New(param_count * Parser::kParameterEntrySize, Heap::kOld));
526 for (intptr_t i = 0; i < param_count; ++i) {
527 const intptr_t entry_start = i * Parser::kParameterEntrySize;
528
529 if (i == positional_count) {
530 intptr_t named_parameter_count_check =
531 ReadListLength(); // read list length.
532 ASSERT(named_parameter_count_check == named_parameter_count);
533 }
534
535 // Read ith variable declaration.
536 intptr_t param_kernel_offset = reader_.offset();
537 VariableDeclarationHelper helper(this);
538 helper.ReadUntilExcluding(VariableDeclarationHelper::kInitializer);
539 param_descriptor.SetAt(entry_start + Parser::kParameterIsFinalOffset,
540 helper.IsFinal() ? Bool::True() : Bool::False());
541
542 Tag tag = ReadTag(); // read (first part of) initializer.
543 if ((tag == kSomething) && !function.is_abstract()) {
544 // This will read the initializer.
545 Instance& constant = Instance::ZoneHandle(
546 zone_, constant_reader_.ReadConstantExpression());
547 param_descriptor.SetAt(entry_start + Parser::kParameterDefaultValueOffset,
548 constant);
549 } else {
550 if (tag == kSomething) {
551 SkipExpression(); // Skip initializer.
552 }
553 param_descriptor.SetAt(entry_start + Parser::kParameterDefaultValueOffset,
554 Object::null_instance());
555 }
556
557 if (FLAG_enable_mirrors && (helper.annotation_count_ > 0)) {
558 AlternativeReadingScope alt(&reader_, param_kernel_offset);
559 VariableDeclarationHelper helper(this);
560 helper.ReadUntilExcluding(VariableDeclarationHelper::kAnnotations);
561 Object& metadata =
562 Object::ZoneHandle(zone_, constant_reader_.ReadAnnotations());
563 param_descriptor.SetAt(entry_start + Parser::kParameterMetadataOffset,
564 metadata);
565 } else {
566 param_descriptor.SetAt(entry_start + Parser::kParameterMetadataOffset,
567 Object::null_instance());
568 }
569 }
570 return param_descriptor.ptr();
571}
572
573ObjectPtr BuildParameterDescriptor(const Function& function) {
574 LongJumpScope jump;
575 if (setjmp(*jump.Set()) == 0) {
576 Thread* thread = Thread::Current();
577 Zone* zone = thread->zone();
578
579 const auto& kernel_info =
580 KernelProgramInfo::Handle(zone, function.KernelProgramInfo());
581
582 TranslationHelper helper(thread);
583 helper.InitFromKernelProgramInfo(kernel_info);
584
585 const Class& owner_class = Class::Handle(zone, function.Owner());
586 ActiveClass active_class;
587 ActiveClassScope active_class_scope(&active_class, &owner_class);
588
589 ParameterDescriptorBuilder builder(
590 &helper, zone, TypedDataView::Handle(zone, function.KernelLibrary()),
591 function.KernelLibraryOffset(), &active_class);
592
593 return builder.BuildParameterDescriptor(function);
594 } else {
595 return Thread::Current()->StealStickyError();
596 }
597}
598
599void ReadParameterCovariance(const Function& function,
600 BitVector* is_covariant,
601 BitVector* is_generic_covariant_impl) {
602 Thread* thread = Thread::Current();
603 Zone* zone = thread->zone();
604
605 const intptr_t num_params = function.NumParameters();
606 ASSERT(is_covariant->length() == num_params);
607 ASSERT(is_generic_covariant_impl->length() == num_params);
608
609 const auto& kernel_info =
610 KernelProgramInfo::Handle(zone, function.KernelProgramInfo());
611
612 TranslationHelper translation_helper(thread);
613 translation_helper.InitFromKernelProgramInfo(kernel_info);
614
615 KernelReaderHelper reader_helper(
616 zone, &translation_helper,
617 TypedDataView::Handle(zone, function.KernelLibrary()),
618 function.KernelLibraryOffset());
619
620 reader_helper.SetOffset(function.kernel_offset());
621 reader_helper.ReadUntilFunctionNode();
622
623 FunctionNodeHelper function_node_helper(&reader_helper);
624 function_node_helper.ReadUntilExcluding(
625 FunctionNodeHelper::kPositionalParameters);
626
627 // Positional.
628 const intptr_t num_positional_params = reader_helper.ReadListLength();
629 intptr_t param_index = function.NumImplicitParameters();
630 for (intptr_t i = 0; i < num_positional_params; ++i, ++param_index) {
631 VariableDeclarationHelper helper(&reader_helper);
632 helper.ReadUntilExcluding(VariableDeclarationHelper::kEnd);
633
634 if (helper.IsCovariant()) {
635 is_covariant->Add(param_index);
636 }
637 if (helper.IsGenericCovariantImpl()) {
638 is_generic_covariant_impl->Add(param_index);
639 }
640 }
641
642 // Named.
643 const intptr_t num_named_params = reader_helper.ReadListLength();
644 for (intptr_t i = 0; i < num_named_params; ++i, ++param_index) {
645 VariableDeclarationHelper helper(&reader_helper);
646 helper.ReadUntilExcluding(VariableDeclarationHelper::kEnd);
647
648 if (helper.IsCovariant()) {
649 is_covariant->Add(param_index);
650 }
651 if (helper.IsGenericCovariantImpl()) {
652 is_generic_covariant_impl->Add(param_index);
653 }
654 }
655}
656
657bool NeedsDynamicInvocationForwarder(const Function& function) {
658 Zone* zone = Thread::Current()->zone();
659
660 // Right now closures do not need a dyn:* forwarder.
661 // See https://github.com/dart-lang/sdk/issues/40813
662 if (function.IsClosureFunction()) return false;
663
664 // Method extractors have no parameters to check and return value is a closure
665 // and therefore not an unboxed primitive type.
666 if (function.IsMethodExtractor()) {
667 return false;
668 }
669
670 // Record field getters have no parameters to check and 'dynamic' return type.
671 if (function.IsRecordFieldGetter()) {
672 return false;
673 }
674
675 // Invoke field dispatchers are dynamically generated, will invoke a getter to
676 // obtain the field value and then invoke ".call()" on the result.
677 // Those dynamically generated dispathers don't have proper kernel metadata
678 // associated with them - we can therefore not query if there are dynamic
679 // calls to them or not and are therefore conservative.
680 if (function.IsInvokeFieldDispatcher()) {
681 return true;
682 }
683
684 // The dyn:* forwarders perform unboxing of parameters before calling the
685 // actual target (which accepts unboxed parameters) and boxes return values
686 // of the return value.
687 if (function.HasUnboxedParameters() || function.HasUnboxedReturnValue()) {
688 return true;
689 }
690
691 if (function.MaxNumberOfParametersInRegisters(zone) > 0) {
692 return true;
693 }
694
695 // There are no parameters to type check for getters and if the return value
696 // is boxed, then the dyn:* forwarder is not needed.
697 if (function.IsImplicitGetterFunction()) {
698 return false;
699 }
700
701 // Covariant parameters (both explicitly covariant and generic-covariant-impl)
702 // are checked in the body of a function and therefore don't need checks in a
703 // dynamic invocation forwarder. So dynamic invocation forwarder is only
704 // needed if there are non-covariant parameters of non-top type.
705 if (function.IsImplicitSetterFunction()) {
706 const auto& field = Field::Handle(zone, function.accessor_field());
707 return !(field.is_covariant() || field.is_generic_covariant_impl());
708 }
709
710 const auto& type_params =
711 TypeParameters::Handle(zone, function.type_parameters());
712 if (!type_params.IsNull()) {
713 auto& bound = AbstractType::Handle(zone);
714 for (intptr_t i = 0, n = type_params.Length(); i < n; ++i) {
715 bound = type_params.BoundAt(i);
716 if (!bound.IsTopTypeForSubtyping() &&
717 !type_params.IsGenericCovariantImplAt(i)) {
718 return true;
719 }
720 }
721 }
722
723 const intptr_t num_params = function.NumParameters();
724 BitVector is_covariant(zone, num_params);
725 BitVector is_generic_covariant_impl(zone, num_params);
726 ReadParameterCovariance(function, &is_covariant, &is_generic_covariant_impl);
727
728 auto& type = AbstractType::Handle(zone);
729 for (intptr_t i = function.NumImplicitParameters(); i < num_params; ++i) {
730 type = function.ParameterTypeAt(i);
731 if (!type.IsTopTypeForSubtyping() &&
732 !is_generic_covariant_impl.Contains(i) && !is_covariant.Contains(i)) {
733 return true;
734 }
735 }
736
737 return false;
738}
739
740static ProcedureAttributesMetadata ProcedureAttributesOf(
741 Zone* zone,
742 const KernelProgramInfo& kernel_program_info,
743 const TypedDataView& kernel_data,
744 intptr_t kernel_data_program_offset,
745 intptr_t kernel_offset) {
746 TranslationHelper translation_helper(Thread::Current());
747 translation_helper.InitFromKernelProgramInfo(kernel_program_info);
748 KernelReaderHelper reader_helper(zone, &translation_helper, kernel_data,
749 kernel_data_program_offset);
750 ProcedureAttributesMetadataHelper procedure_attributes_metadata_helper(
751 &reader_helper);
753 procedure_attributes_metadata_helper.GetProcedureAttributes(
754 kernel_offset);
755 return attrs;
756}
757
758ProcedureAttributesMetadata ProcedureAttributesOf(const Function& function,
759 Zone* zone) {
760 const auto& kernel_program_info =
761 KernelProgramInfo::Handle(zone, function.KernelProgramInfo());
762 return ProcedureAttributesOf(
763 zone, kernel_program_info,
764 TypedDataView::Handle(zone, function.KernelLibrary()),
765 function.KernelLibraryOffset(), function.kernel_offset());
766}
767
768ProcedureAttributesMetadata ProcedureAttributesOf(const Field& field,
769 Zone* zone) {
770 const auto& kernel_program_info =
771 KernelProgramInfo::Handle(zone, field.KernelProgramInfo());
772 return ProcedureAttributesOf(
773 zone, kernel_program_info,
774 TypedDataView::Handle(zone, field.KernelLibrary()),
775 field.KernelLibraryOffset(), field.kernel_offset());
776}
777
778static UnboxingInfoMetadata* UnboxingInfoMetadataOf(
779 Zone* zone,
780 const KernelProgramInfo& kernel_program_info,
781 const TypedDataView& kernel_data,
782 intptr_t kernel_data_program_offset,
783 intptr_t kernel_offset) {
784 TranslationHelper translation_helper(Thread::Current());
785 translation_helper.InitFromKernelProgramInfo(kernel_program_info);
786 KernelReaderHelper reader_helper(zone, &translation_helper, kernel_data,
787 kernel_data_program_offset);
788 UnboxingInfoMetadataHelper unboxing_info_metadata_helper(&reader_helper);
789 return unboxing_info_metadata_helper.GetUnboxingInfoMetadata(kernel_offset);
790}
791
792UnboxingInfoMetadata* UnboxingInfoMetadataOf(const Function& function,
793 Zone* zone) {
794 const auto& kernel_program_info =
795 KernelProgramInfo::Handle(zone, function.KernelProgramInfo());
796 return UnboxingInfoMetadataOf(
797 zone, kernel_program_info,
798 TypedDataView::Handle(zone, function.KernelLibrary()),
799 function.KernelLibraryOffset(), function.kernel_offset());
800}
801
802TableSelectorMetadata* TableSelectorMetadataForProgram(
803 const KernelProgramInfo& info,
804 Zone* zone) {
805 TranslationHelper translation_helper(Thread::Current());
806 translation_helper.InitFromKernelProgramInfo(info);
807 const auto& data = TypedDataView::Handle(zone, info.metadata_payloads());
808 KernelReaderHelper reader_helper(zone, &translation_helper, data, 0);
809 TableSelectorMetadataHelper table_selector_metadata_helper(&reader_helper);
810 return table_selector_metadata_helper.GetTableSelectorMetadata(zone);
811}
812
813} // namespace kernel
814} // namespace dart
815
816#endif // !defined(DART_PRECOMPILED_RUNTIME)
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213
#define UNREACHABLE()
Definition assert.h:248
void SetAt(intptr_t index, const Object &value) const
Definition object.h:10858
void Add(const T &value)
bool Contains(intptr_t i) const
Definition bit_vector.h:91
intptr_t kernel_offset() const
Definition object.h:1806
ArrayPtr fields() const
Definition object.h:1617
TokenPosition token_pos() const
Definition object.h:1281
TokenPosition end_token_pos() const
Definition object.h:1293
bool is_finalized() const
Definition object.h:1725
ArrayPtr current_functions() const
Definition object.h:1643
ScriptPtr script() const
Definition object.h:1274
bool HasNext() const
Definition object.h:5020
ClassPtr Owner() const
Definition object.cc:11911
intptr_t kernel_offset() const
Definition object.h:4468
intptr_t KernelLibraryOffset() const
Definition object.cc:11963
ScriptPtr Script() const
Definition object.cc:11922
bool is_static() const
Definition object.h:4418
bool is_covariant() const
Definition object.h:4454
TypedDataViewPtr KernelLibrary() const
Definition object.cc:11958
bool is_generic_covariant_impl() const
Definition object.h:4460
bool is_const() const
Definition object.h:4421
KernelProgramInfoPtr KernelProgramInfo() const
Definition object.cc:11936
void EnsureTopLevelClassIsFinalized() const
Definition object.cc:14091
TypedDataViewPtr KernelLibrary() const
Definition object.cc:13648
intptr_t KernelLibraryOffset() const
Definition object.cc:13653
jmp_buf * Set()
Definition longjump.cc:16
ObjectPtr ptr() const
Definition object.h:332
bool IsNull() const
Definition object.h:363
Zone * zone() const
IsolateGroup * isolate_group() const
Definition thread.h:540
int32_t Serialize() const
static TokenPosition Deserialize(int32_t value)
KernelTokenPositionCollector(Zone *zone, TranslationHelper *translation_helper, const Script &script, const TypedDataView &data, intptr_t data_program_offset, intptr_t initial_script_index, intptr_t record_for_script_id, GrowableArray< intptr_t > *record_token_positions_into)
Definition kernel.cc:104
void CollectTokenPositions(intptr_t kernel_offset)
Definition kernel.cc:132
void set_current_script_id(intptr_t id) override
Definition kernel.cc:122
void InitFromKernelProgramInfo(const KernelProgramInfo &info)
FunctionPtr LookupConstructorByKernelConstructor(NameIndex constructor, bool required=true)
virtual ClassPtr LookupClassByKernelClass(NameIndex klass, bool required=true)
#define ASSERT(E)
SkBitmap source
Definition examples.cpp:28
static bool b
struct MyStruct a[10]
#define FATAL(error)
uint32_t * target
Dart_NativeFunction function
Definition fuchsia.cc:51
static void CollectKernelLibraryTokenPositions(const TypedDataView &kernel_data, const Script &script, intptr_t kernel_offset, intptr_t data_kernel_offset, Zone *zone, TranslationHelper *helper, GrowableArray< intptr_t > *token_positions)
Definition kernel.cc:201
static ArrayPtr AsSortedDuplicateFreeArray(GrowableArray< intptr_t > *source)
Definition kernel.cc:177
int LowestFirst(const TokenPosition *a, const TokenPosition *b)
TypedDataElementType
Definition raw_object.h:123
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
Definition switches.h:41
#define Pd32
Definition globals.h:412
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition globals.h:581
const uintptr_t id