Flutter Engine
The Flutter Engine
class_finalizer.cc
Go to the documentation of this file.
1// Copyright (c) 2013, 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 <memory>
6#include <utility>
7
9
10#include "vm/canonical_tables.h"
13#include "vm/flags.h"
14#include "vm/hash_table.h"
15#include "vm/heap/heap.h"
16#include "vm/isolate.h"
17#include "vm/kernel_loader.h"
18#include "vm/log.h"
19#include "vm/longjump.h"
20#include "vm/object_store.h"
21#include "vm/program_visitor.h"
22#include "vm/runtime_entry.h"
23#include "vm/symbols.h"
24#include "vm/timeline.h"
26
27namespace dart {
28
29DEFINE_FLAG(bool, print_classes, false, "Prints details about loaded classes.");
30DEFINE_FLAG(bool, trace_class_finalization, false, "Trace class finalization.");
31DEFINE_FLAG(bool, trace_type_finalization, false, "Trace type finalization.");
32
35 const GrowableObjectArray& classes =
36 GrowableObjectArray::Handle(object_store->pending_classes());
37 return classes.Length() == 0;
38}
39
40#if defined(DART_PRECOMPILED_RUNTIME)
41
44 return true;
45}
46
47#else
48
49// Removes optimized code once we load more classes, since CHA based
50// optimizations may have become invalid.
51// Only methods which owner classes where subclasses can be invalid.
52// TODO(srdjan): Be even more precise by recording the exact CHA optimization.
54 const Class& subclass,
55 const GrowableArray<intptr_t>& added_subclass_to_cids) {
56 ASSERT(FLAG_use_cha_deopt);
57 if (added_subclass_to_cids.is_empty()) {
58 return;
59 }
60 // Switch all functions' code to unoptimized.
61 const ClassTable& class_table = *IsolateGroup::Current()->class_table();
62 Class& cls = Class::Handle();
63 for (intptr_t i = 0; i < added_subclass_to_cids.length(); i++) {
64 intptr_t cid = added_subclass_to_cids[i];
65 cls = class_table.At(cid);
66 ASSERT(!cls.IsNull());
67 cls.DisableCHAOptimizedCode(subclass);
68 }
69}
70
71static void AddSuperType(const AbstractType& type,
72 GrowableArray<intptr_t>* finalized_super_classes) {
73 ASSERT(type.HasTypeClass());
74 ASSERT(!type.IsDynamicType());
75 if (type.IsObjectType()) {
76 return;
77 }
78 const Class& cls = Class::Handle(type.type_class());
79 ASSERT(cls.is_finalized());
80 const intptr_t cid = cls.id();
81 for (intptr_t i = 0; i < finalized_super_classes->length(); i++) {
82 if ((*finalized_super_classes)[i] == cid) {
83 // Already added.
84 return;
85 }
86 }
87 finalized_super_classes->Add(cid);
88 const AbstractType& super_type = AbstractType::Handle(cls.super_type());
89 AddSuperType(super_type, finalized_super_classes);
90}
91
92// Use array instead of set since we expect very few subclassed classes
93// to occur.
95 const Class& cls_,
96 GrowableArray<intptr_t>* finalized_super_classes) {
97 Class& cls = Class::Handle(cls_.ptr());
98 AbstractType& super_type = Type::Handle();
99 super_type = cls.super_type();
100 if (!super_type.IsNull()) {
101 if (super_type.HasTypeClass()) {
102 cls = super_type.type_class();
103 if (cls.is_finalized()) {
104 AddSuperType(super_type, finalized_super_classes);
105 }
106 }
107 }
108}
109
111 public:
113 ClassTable* class_table,
115 : class_table_(class_table),
116 array_handles_(zone),
117 class_handles_(zone),
118 type_handles_(zone),
119 cids_(cids) {}
120
121 void FindAllInterfaces(const Class& klass) {
122 // The class is implementing its own interface.
123 cids_->Add(klass.id());
124
125 ScopedHandle<Array> array(&array_handles_);
126 ScopedHandle<Class> interface_class(&class_handles_);
127 ScopedHandle<Class> current_class(&class_handles_);
128 ScopedHandle<AbstractType> type(&type_handles_);
129
130 *current_class = klass.ptr();
131 while (true) {
132 // We don't care about top types.
133 const intptr_t cid = current_class->id();
134 if (cid == kObjectCid || cid == kDynamicCid || cid == kVoidCid) {
135 break;
136 }
137
138 // The class is implementing its directly declared implemented interfaces.
139 *array = klass.interfaces();
140 if (!array->IsNull()) {
141 for (intptr_t i = 0; i < array->Length(); ++i) {
142 *type ^= array->At(i);
143 *interface_class = class_table_->At(type->type_class_id());
144 FindAllInterfaces(*interface_class);
145 }
146 }
147
148 // The class is implementing its super type's interfaces.
149 *type = current_class->super_type();
150 if (type->IsNull()) break;
151 *current_class = class_table_->At(type->type_class_id());
152 }
153 }
154
155 private:
156 ClassTable* class_table_;
157 ReusableHandleStack<Array> array_handles_;
158 ReusableHandleStack<Class> class_handles_;
161};
162
165 const Array& interfaces = Array::Handle(cls.interfaces());
166 Class& ifc = Class::Handle();
168 for (intptr_t i = 0; i < interfaces.Length(); ++i) {
169 type ^= interfaces.At(i);
170 if (!type.HasTypeClass()) continue;
171 ifc = type.type_class();
172 for (intptr_t j = 0; j < cids->length(); ++j) {
173 if ((*cids)[j] == ifc.id()) {
174 // Already added.
175 return;
176 }
177 }
178 cids->Add(ifc.id());
179 }
180}
181
182// Processing ObjectStore::pending_classes_ occurs:
183// a) when bootstrap process completes (VerifyBootstrapClasses).
184// b) after the user classes are loaded (dart_api).
186 Thread* thread = Thread::Current();
187 TIMELINE_DURATION(thread, Isolate, "ProcessPendingClasses");
188 auto isolate_group = thread->isolate_group();
189 ASSERT(isolate_group != nullptr);
190 HANDLESCOPE(thread);
191 ObjectStore* object_store = isolate_group->object_store();
192 const Error& error = Error::Handle(thread->zone(), thread->sticky_error());
193 if (!error.IsNull()) {
194 return false;
195 }
196 if (AllClassesFinalized()) {
197 return true;
198 }
199
200 LongJumpScope jump;
201 if (setjmp(*jump.Set()) == 0) {
203 class_array = object_store->pending_classes();
204 ASSERT(!class_array.IsNull());
205 Class& cls = Class::Handle();
206
207#if defined(DEBUG)
208 for (intptr_t i = 0; i < class_array.Length(); i++) {
209 cls ^= class_array.At(i);
210 // Recognized a new class, but forgot to add @pragma('vm:entrypoint')?
212 }
213#endif
214
215 // Finalize types in all classes.
216 for (intptr_t i = 0; i < class_array.Length(); i++) {
217 cls ^= class_array.At(i);
219#if !defined(PRODUCT) || defined(FORCE_INCLUDE_SAMPLING_HEAP_PROFILER)
221#endif
222 }
223
224 // Clear pending classes array.
225 class_array = GrowableObjectArray::New();
226 object_store->set_pending_classes(class_array);
227 VerifyImplicitFieldOffsets(); // Verification after an error may fail.
228
229 return true;
230 } else {
231 return false;
232 }
233 UNREACHABLE();
234 return true;
235}
236
238 if (FLAG_trace_class_finalization) {
239 OS::PrintErr("VerifyBootstrapClasses START.\n");
240 }
242
243 Class& cls = Class::Handle();
244#if defined(DEBUG)
245 // Basic checking.
246 cls = object_store->object_class();
248 cls = object_store->integer_implementation_class();
250 cls = object_store->smi_class();
252 cls = object_store->mint_class();
254 cls = object_store->one_byte_string_class();
256 cls = object_store->two_byte_string_class();
258 cls = object_store->double_class();
260 cls = object_store->bool_class();
262 cls = object_store->array_class();
264 cls = object_store->immutable_array_class();
266 cls = object_store->weak_property_class();
268 cls = object_store->weak_reference_class();
270 cls = object_store->finalizer_class();
272 cls = object_store->finalizer_entry_class();
274 cls = object_store->map_impl_class();
276 cls = object_store->const_map_impl_class();
278 cls = object_store->set_impl_class();
280 cls = object_store->const_set_impl_class();
282#endif // defined(DEBUG)
283
284 // Remember the currently pending classes.
285 const GrowableObjectArray& class_array =
286 GrowableObjectArray::Handle(object_store->pending_classes());
287 for (intptr_t i = 0; i < class_array.Length(); i++) {
288 // TODO(iposva): Add real checks.
289 cls ^= class_array.At(i);
290 if (cls.is_finalized() || cls.is_prefinalized()) {
291 // Pre-finalized bootstrap classes must not define any fields.
293 }
294 }
295
296 // Finalize type hierarchy for types that aren't pre-finalized
297 // by Object::Init().
298 if (!ProcessPendingClasses()) {
299 // TODO(srdjan): Exit like a real VM instead.
300 const Error& err = Error::Handle(Thread::Current()->sticky_error());
301 OS::PrintErr("Could not verify bootstrap classes : %s\n",
302 err.ToErrorCString());
303 OS::Exit(255);
304 }
305
306 if (FLAG_trace_class_finalization) {
307 OS::PrintErr("VerifyBootstrapClasses END.\n");
308 }
309 IsolateGroup::Current()->heap()->Verify("VerifyBootstrapClasses END");
310}
311#endif // defined(DART_PRECOMPILED_RUNTIME)
312
313void ClassFinalizer::FinalizeTypeParameters(Zone* zone,
314 const TypeParameters& type_params,
315 FinalizationKind finalization) {
316 if (!type_params.IsNull()) {
317 TypeArguments& type_args = TypeArguments::Handle(zone);
318
319 type_args = type_params.bounds();
320 type_args = FinalizeTypeArguments(zone, type_args, finalization);
321 type_params.set_bounds(type_args);
322
323 type_args = type_params.defaults();
324 type_args = FinalizeTypeArguments(zone, type_args, finalization);
325 type_params.set_defaults(type_args);
326
327 type_params.OptimizeFlags();
328 }
329}
330
331TypeArgumentsPtr ClassFinalizer::FinalizeTypeArguments(
332 Zone* zone,
333 const TypeArguments& type_args,
334 FinalizationKind finalization) {
335 if (type_args.IsNull()) {
336 return TypeArguments::null();
337 }
338 ASSERT(type_args.ptr() != Object::empty_type_arguments().ptr());
339 AbstractType& type = AbstractType::Handle(zone);
340 for (intptr_t i = 0, n = type_args.Length(); i < n; ++i) {
341 type = type_args.TypeAt(i);
343 }
344 if (finalization >= kCanonicalize) {
345 return type_args.Canonicalize(Thread::Current());
346 }
347 return type_args.ptr();
348}
349
351 FinalizationKind finalization) {
352 if (type.IsFinalized()) {
353 if ((finalization >= kCanonicalize) && !type.IsCanonical()) {
354 return type.Canonicalize(Thread::Current());
355 }
356 return type.ptr();
357 }
358
359 Thread* thread = Thread::Current();
360 Zone* zone = thread->zone();
361
362 if (FLAG_trace_type_finalization) {
363 THR_Print("Finalizing type '%s'\n", type.ToCString());
364 }
365
366 if (type.IsType()) {
367 const auto& t = Type::Cast(type);
368 const auto& type_args = TypeArguments::Handle(zone, t.arguments());
369 ASSERT(type_args.IsNull() ||
370 type_args.Length() ==
371 Class::Handle(zone, t.type_class()).NumTypeParameters(thread));
372 FinalizeTypeArguments(zone, type_args, kFinalize);
373
374 } else if (type.IsTypeParameter()) {
375 const TypeParameter& type_parameter = TypeParameter::Cast(type);
376 // The base and index of a function type parameter are eagerly calculated
377 // upon loading and do not require adjustment here.
378 if (type_parameter.IsClassTypeParameter()) {
379 const Class& parameterized_class = Class::Cast(
380 Object::Handle(zone, type_parameter.parameterized_class()));
381 ASSERT(!parameterized_class.IsNull());
382 // The index must reflect the position of this type parameter in the type
383 // arguments vector of its parameterized class. The offset to add is the
384 // number of type arguments in the super type, which is equal to the
385 // difference in number of type arguments and type parameters of the
386 // parameterized class.
387 const intptr_t offset = parameterized_class.NumTypeArguments() -
388 parameterized_class.NumTypeParameters();
389 const intptr_t index = type_parameter.index() + offset;
390 if (!Utils::IsUint(16, index)) {
391 FATAL("Too many type parameters in %s",
392 parameterized_class.UserVisibleNameCString());
393 }
394 type_parameter.set_base(offset); // Informative, but not needed.
395 type_parameter.set_index(index);
396
397 if (AbstractType::Handle(zone, type_parameter.bound())
398 .IsNullableObjectType()) {
399 // Remove the reference to the parameterized class to
400 // canonicalize common class type parameters
401 // with 'Object?' bound and same indices to the same
402 // instances.
404 }
405 }
406 } else if (type.IsFunctionType()) {
407 const auto& signature = FunctionType::Cast(type);
408 FinalizeTypeParameters(
409 zone, TypeParameters::Handle(zone, signature.type_parameters()),
410 kFinalize);
411
413 type = signature.result_type();
415
416 for (intptr_t i = 0, n = signature.NumParameters(); i < n; ++i) {
417 type = signature.ParameterTypeAt(i);
419 }
420
421 } else if (type.IsRecordType()) {
422 const auto& record = RecordType::Cast(type);
424 for (intptr_t i = 0, n = record.NumFields(); i < n; ++i) {
425 type = record.FieldTypeAt(i);
427 }
428 }
429
430 type.SetIsFinalized();
431
432 if (finalization >= kCanonicalize) {
433 return type.Canonicalize(thread);
434 } else {
435 return type.ptr();
436 }
437}
438
439#if !defined(DART_PRECOMPILED_RUNTIME)
440
441#if defined(TARGET_ARCH_X64)
442static bool IsPotentialExactGeneric(const AbstractType& type) {
443 // TODO(dartbug.com/34170) Investigate supporting this for fields with types
444 // that depend on type parameters of the enclosing class.
445 if (type.IsType() && !type.IsDartFunctionType() && type.IsInstantiated() &&
446 !type.IsFutureOrType()) {
447 const Class& cls = Class::Handle(type.type_class());
448 return cls.IsGeneric();
449 }
450
451 return false;
452}
453#else
454// TODO(dartbug.com/34170) Support other architectures.
456 return false;
457}
458#endif
459
460void ClassFinalizer::FinalizeMemberTypes(const Class& cls) {
461 // Note that getters and setters are explicitly listed as such in the list of
462 // functions of a class, so we do not need to consider fields as implicitly
463 // generating getters and setters.
464 // Most overriding conflicts are only static warnings, i.e. they are not
465 // reported as compile-time errors by the vm.
466 // Static warning examples are:
467 // - a static getter 'v' conflicting with an inherited instance setter 'v='.
468 // - a static setter 'v=' conflicting with an inherited instance member 'v'.
469 // - an instance member 'v' conflicting with an accessible static member 'v'
470 // or 'v=' of a super class (except that an instance method 'v' does not
471 // conflict with an accessible static setter 'v=' of a super class).
472 // The compile-time errors we report are:
473 // - a static member 'v' conflicting with an inherited instance member 'v'.
474 // - a static setter 'v=' conflicting with an inherited instance setter 'v='.
475 // - an instance method conflicting with an inherited instance field or
476 // instance getter.
477 // - an instance field or instance getter conflicting with an inherited
478 // instance method.
479
480 // Finalize type of fields and check for conflicts in super classes.
481 auto isolate_group = IsolateGroup::Current();
482 Zone* zone = Thread::Current()->zone();
483 Array& array = Array::Handle(zone, cls.fields());
484 Field& field = Field::Handle(zone);
485 AbstractType& type = AbstractType::Handle(zone);
486 Function& function = Function::Handle(zone);
487 FunctionType& signature = FunctionType::Handle(zone);
488 const intptr_t num_fields = array.Length();
489 const bool track_exactness = isolate_group->use_field_guards();
490 for (intptr_t i = 0; i < num_fields; i++) {
491 field ^= array.At(i);
492 type = field.type();
494 field.SetFieldType(type);
495 ASSERT(!field.static_type_exactness_state().IsTracking());
496 if (track_exactness && (field.guarded_cid() != kDynamicCid) &&
498 field.set_static_type_exactness_state(
500 }
501 function = field.InitializerFunction();
502 if (!function.IsNull()) {
503 // TODO(regis): It looks like the initializer is never set at this point.
504 // Remove this finalization code?
505 signature = function.signature();
506 signature ^= FinalizeType(signature);
507 function.SetSignature(signature);
508 }
509 }
510 // Finalize function signatures and check for conflicts in super classes and
511 // interfaces.
512 array = cls.current_functions();
513 const intptr_t num_functions = array.Length();
514 for (intptr_t i = 0; i < num_functions; i++) {
515 function ^= array.At(i);
516 signature = function.signature();
517 signature ^= FinalizeType(signature);
518 function.SetSignature(signature);
519 if (function.IsSetterFunction() || function.IsImplicitSetterFunction()) {
520 continue;
521 }
522 }
523}
524
525// For a class used as an interface marks this class and all its superclasses
526// implemented.
527//
528// Does not mark its interfaces implemented because those would already be
529// marked as such.
530static void MarkImplemented(Zone* zone, const Class& iface) {
531 if (iface.is_implemented()) {
532 return;
533 }
534
535 Class& cls = Class::Handle(zone, iface.ptr());
537
538 while (!cls.is_implemented()) {
539 cls.set_is_implemented();
540
541 type = cls.super_type();
542 if (type.IsNull() || type.IsObjectType()) {
543 break;
544 }
545 cls = type.type_class();
546 }
547}
548#endif // !defined(DART_PRECOMPILED_RUNTIME)
549
551 Thread* thread = Thread::Current();
552 HANDLESCOPE(thread);
554 if (cls.is_type_finalized()) {
555 return;
556 }
557
558#if defined(DART_PRECOMPILED_RUNTIME)
559 UNREACHABLE();
560#else
561 Zone* zone = thread->zone();
562 SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
563 if (cls.is_type_finalized()) {
564 return;
565 }
566
567 if (FLAG_trace_class_finalization) {
568 THR_Print("Finalize types in %s\n", cls.ToCString());
569 }
570
571 bool has_isolate_unsendable_pragma =
573 bool is_future_subtype = cls.IsFutureClass();
574
575 // Finalize super class.
576 Class& super_class = Class::Handle(zone, cls.SuperClass());
577 if (!super_class.IsNull()) {
578 FinalizeTypesInClass(super_class);
579 }
580 // Finalize type parameters before finalizing the super type.
581 FinalizeTypeParameters(
583 ASSERT(super_class.ptr() == cls.SuperClass()); // Not modified.
584 ASSERT(super_class.IsNull() || super_class.is_type_finalized());
585 // Finalize super type.
586 Type& super_type = Type::Handle(zone, cls.super_type());
587 if (!super_type.IsNull()) {
588 super_type ^= FinalizeType(super_type);
589 cls.set_super_type(super_type);
590 has_isolate_unsendable_pragma |=
592 is_future_subtype |= super_class.is_future_subtype();
593 }
594 // Finalize interface types (but not necessarily interface classes).
595 const auto& interface_types = Array::Handle(zone, cls.interfaces());
596 auto& interface_type = AbstractType::Handle(zone);
597 auto& interface_class = Class::Handle(zone);
598 for (intptr_t i = 0; i < interface_types.Length(); i++) {
599 interface_type ^= interface_types.At(i);
600 interface_type = FinalizeType(interface_type);
601 interface_class = interface_type.type_class();
602 ASSERT(!interface_class.IsNull());
603 FinalizeTypesInClass(interface_class);
604 interface_types.SetAt(i, interface_type);
605 has_isolate_unsendable_pragma |=
606 interface_class.is_isolate_unsendable_due_to_pragma();
607 is_future_subtype |= interface_class.is_future_subtype();
608 }
610 cls.set_is_isolate_unsendable_due_to_pragma(has_isolate_unsendable_pragma);
611 cls.set_is_future_subtype(is_future_subtype);
612 if (is_future_subtype && !cls.is_abstract()) {
613 MarkClassCanBeFuture(zone, cls);
614 }
615 if (cls.is_dynamically_extendable()) {
617 }
618
619 RegisterClassInHierarchy(zone, cls);
620#endif // defined(DART_PRECOMPILED_RUNTIME)
621}
622
623#if !defined(DART_PRECOMPILED_RUNTIME)
625 auto& type = AbstractType::Handle(zone, cls.super_type());
626 auto& other_cls = Class::Handle(zone);
627 // Add this class to the direct subclasses of the superclass, unless the
628 // superclass is Object.
629 if (!type.IsNull() && !type.IsObjectType()) {
630 other_cls = cls.SuperClass();
631 ASSERT(!other_cls.IsNull());
632 other_cls.AddDirectSubclass(cls);
633 }
634
635 // Add this class as an implementor to the implemented interface's type
636 // classes.
637 auto& interfaces = Array::Handle(zone, cls.interfaces());
638 const intptr_t mixin_index =
639 cls.is_transformed_mixin_application() ? interfaces.Length() - 1 : -1;
640 for (intptr_t i = 0; i < interfaces.Length(); ++i) {
641 type ^= interfaces.At(i);
642 other_cls = type.type_class();
643 MarkImplemented(zone, other_cls);
644 other_cls.AddDirectImplementor(cls, /* is_mixin = */ i == mixin_index);
645 }
646
647 // Propagate known concrete implementors to interfaces.
648 if (!cls.is_abstract()) {
650 worklist.Add(&cls);
651 while (!worklist.is_empty()) {
652 const Class& implemented = *worklist.RemoveLast();
653 if (!implemented.NoteImplementor(cls)) continue;
654 type = implemented.super_type();
655 if (!type.IsNull()) {
656 worklist.Add(&Class::Handle(zone, implemented.SuperClass()));
657 }
658 interfaces = implemented.interfaces();
659 for (intptr_t i = 0; i < interfaces.Length(); i++) {
660 type ^= interfaces.At(i);
661 worklist.Add(&Class::Handle(zone, type.type_class()));
662 }
663 }
664 }
665}
666
668 if (cls.can_be_future()) return;
669
670 cls.set_can_be_future(true);
671
672 Class& base = Class::Handle(zone, cls.SuperClass());
673 if (!base.IsNull()) {
675 }
676 auto& interfaces = Array::Handle(zone, cls.interfaces());
677 auto& type = AbstractType::Handle(zone);
678 for (intptr_t i = 0; i < interfaces.Length(); ++i) {
679 type ^= interfaces.At(i);
680 base = type.type_class();
682 }
683}
684
686 Zone* zone,
687 const Class& cls) {
688 if (cls.has_dynamically_extendable_subtypes()) return;
689
691
692 Class& base = Class::Handle(zone, cls.SuperClass());
693 if (!base.IsNull()) {
695 }
696 auto& interfaces = Array::Handle(zone, cls.interfaces());
697 auto& type = AbstractType::Handle(zone);
698 for (intptr_t i = 0; i < interfaces.Length(); ++i) {
699 type ^= interfaces.At(i);
700 base = type.type_class();
702 }
703}
704#endif // defined(DART_PRECOMPILED_RUNTIME)
705
708 if (cls.is_finalized()) {
709 return;
710 }
711
712#if defined(DART_PRECOMPILED_RUNTIME)
713 UNREACHABLE();
714#else
715 Thread* thread = Thread::Current();
716 HANDLESCOPE(thread);
717
718 if (FLAG_trace_class_finalization) {
719 THR_Print("Finalize %s\n", cls.ToCString());
720 }
721
722#if defined(SUPPORT_TIMELINE)
723 TimelineBeginEndScope tbes(thread, Timeline::GetCompilerStream(),
724 "FinalizeClass");
725 if (tbes.enabled()) {
726 tbes.SetNumArguments(1);
727 tbes.CopyArgument(0, "class", cls.ToCString());
728 }
729#endif // defined(SUPPORT_TIMELINE)
730
731 // If loading from a kernel, make sure that the class is fully loaded.
732 ASSERT(cls.IsTopLevel() || (cls.kernel_offset() > 0));
733 if (!cls.is_loaded()) {
735 if (cls.is_finalized()) {
736 return;
737 }
738 }
739
740 // Ensure super class is finalized.
741 const Class& super = Class::Handle(cls.SuperClass());
742 if (!super.IsNull()) {
743 FinalizeClass(super);
744 if (cls.is_finalized()) {
745 return;
746 }
747 }
748 // Mark as loaded and finalized.
749 cls.Finalize();
750 if (FLAG_print_classes) {
751 PrintClassInformation(cls);
752 }
753 FinalizeMemberTypes(cls);
754
755 // The rest of finalization for non-top-level class has to be done with
756 // stopped mutators. It will be done by AllocateFinalizeClass. before new
757 // instance of a class is created in GetAllocationStubForClass.
758 if (cls.IsTopLevel()) {
760 }
761#endif // defined(DART_PRECOMPILED_RUNTIME)
762}
763
764#if !defined(DART_PRECOMPILED_RUNTIME)
765
767 ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
768 ASSERT(cls.is_finalized());
770
771 Thread* thread = Thread::Current();
772 HANDLESCOPE(thread);
773
774 if (FLAG_trace_class_finalization) {
775 THR_Print("Allocate finalize %s\n", cls.ToCString());
776 }
777
778#if defined(SUPPORT_TIMELINE)
779 TimelineBeginEndScope tbes(thread, Timeline::GetCompilerStream(),
780 "AllocateFinalizeClass");
781 if (tbes.enabled()) {
782 tbes.SetNumArguments(1);
783 tbes.CopyArgument(0, "class", cls.ToCString());
784 }
785#endif // defined(SUPPORT_TIMELINE)
786
787 // Run additional checks after all types are finalized.
788 if (FLAG_use_cha_deopt && !cls.IsTopLevel()) {
789 {
793 RemoveCHAOptimizedCode(cls, cids);
794 }
795
796 Zone* zone = thread->zone();
797 ClassTable* class_table = thread->isolate_group()->class_table();
798 auto& interface_class = Class::Handle(zone);
799
800 // We scan every interface this [cls] implements and invalidate all CHA
801 // code which depends on knowing the implementors of that interface.
802 {
804 InterfaceFinder finder(zone, class_table, &cids);
805 finder.FindAllInterfaces(cls);
806 for (intptr_t j = 0; j < cids.length(); ++j) {
807 interface_class = class_table->At(cids[j]);
808 interface_class.DisableCHAImplementorUsers();
809 }
810 }
811 }
812
814 return Error::null();
815}
816
818 ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
819 ASSERT(!cls.is_finalized());
820
821 LongJumpScope jump;
822 if (setjmp(*jump.Set()) == 0) {
823#if !defined(DART_PRECOMPILED_RUNTIME)
825#endif
828 return Error::null();
829 } else {
831 }
832}
833
834void ClassFinalizer::PrintClassInformation(const Class& cls) {
835 Thread* thread = Thread::Current();
836 HANDLESCOPE(thread);
837 const String& class_name = String::Handle(cls.Name());
838 THR_Print("class '%s'", class_name.ToCString());
839 const Library& library = Library::Handle(cls.library());
840 if (!library.IsNull()) {
841 THR_Print(" library '%s%s':\n", String::Handle(library.url()).ToCString(),
843 } else {
844 THR_Print(" (null library):\n");
845 }
846 const AbstractType& super_type = AbstractType::Handle(cls.super_type());
847 if (super_type.IsNull()) {
848 THR_Print(" Super: nullptr");
849 } else {
850 const String& super_name = String::Handle(super_type.Name());
851 THR_Print(" Super: %s", super_name.ToCString());
852 }
853 const Array& interfaces_array = Array::Handle(cls.interfaces());
854 if (interfaces_array.Length() > 0) {
855 THR_Print("; interfaces: ");
856 AbstractType& interface = AbstractType::Handle();
857 intptr_t len = interfaces_array.Length();
858 for (intptr_t i = 0; i < len; i++) {
859 interface ^= interfaces_array.At(i);
860 THR_Print(" %s ", interface.ToCString());
861 }
862 }
863 THR_Print("\n");
864 const Array& functions_array = Array::Handle(cls.current_functions());
865 Function& function = Function::Handle();
866 intptr_t len = functions_array.Length();
867 for (intptr_t i = 0; i < len; i++) {
868 function ^= functions_array.At(i);
869 THR_Print(" %s\n", function.ToCString());
870 }
871 const Array& fields_array = Array::Handle(cls.fields());
872 Field& field = Field::Handle();
873 len = fields_array.Length();
874 for (intptr_t i = 0; i < len; i++) {
875 field ^= fields_array.At(i);
876 THR_Print(" %s\n", field.ToCString());
877 }
878}
879
880#endif // !defined(DART_PRECOMPILED_RUNTIME)
881
882void ClassFinalizer::ReportError(const Error& error) {
884 UNREACHABLE();
885}
886
887void ClassFinalizer::ReportError(const char* format, ...) {
888 va_list args;
890 const Script& null_script = Script::Handle();
891 Report::MessageV(Report::kError, null_script, TokenPosition::kNoSource,
893 va_end(args);
894 UNREACHABLE();
895}
896
897#if !defined(DART_PRECOMPILED_RUNTIME)
898
899void ClassFinalizer::VerifyImplicitFieldOffsets() {
900#ifdef DEBUG
901 Thread* thread = Thread::Current();
902 auto isolate_group = thread->isolate_group();
903
904 if (isolate_group->obfuscate()) {
905 // Field names are obfuscated.
906 return;
907 }
908
909 Zone* zone = thread->zone();
910 const ClassTable& class_table = *(isolate_group->class_table());
911 Class& cls = Class::Handle(zone);
912 Array& fields_array = Array::Handle(zone);
913 Field& field = Field::Handle(zone);
914 String& name = String::Handle(zone);
915 String& expected_name = String::Handle(zone);
916 Error& error = Error::Handle(zone);
917 TypeParameter& type_param = TypeParameter::Handle(zone);
918
919 // Now verify field offsets of '_ByteBuffer' class.
920 cls = class_table.At(kByteBufferCid);
921 error = cls.EnsureIsFinalized(thread);
922 ASSERT(error.IsNull());
923 fields_array ^= cls.fields();
924 ASSERT(fields_array.Length() == ByteBuffer::NumberOfFields());
925 field ^= fields_array.At(0);
926 ASSERT(field.HostOffset() == ByteBuffer::data_offset());
927 name ^= field.name();
928 expected_name ^= String::New("_data");
930
931 // Now verify field offsets of 'Pointer' class.
932 cls = class_table.At(kPointerCid);
933 error = cls.EnsureIsFinalized(thread);
934 ASSERT(error.IsNull());
935 ASSERT(cls.NumTypeParameters() == 1);
936 type_param = cls.TypeParameterAt(0);
937 ASSERT(Pointer::kNativeTypeArgPos == type_param.index());
938#endif
939}
940
942 auto T = Thread::Current();
943 StackZone stack_zone(T);
944 auto Z = T->zone();
945 auto IG = T->isolate_group();
946
947 // Prevent background compiler from adding deferred classes or canonicalizing
948 // new types while classes are being sorted and type hashes are modified.
949 NoBackgroundCompilerScope no_bg_compiler(T);
950 SafepointWriteRwLocker ml(T, T->isolate_group()->program_lock());
951
952 ClassTable* table = IG->class_table();
953 intptr_t num_cids = table->NumCids();
954
955 std::unique_ptr<intptr_t[]> old_to_new_cid(new intptr_t[num_cids]);
956
957 for (intptr_t cid = 0; cid < kNumPredefinedCids; cid++) {
958 old_to_new_cid[cid] = cid; // The predefined classes cannot change cids.
959 }
960 for (intptr_t cid = kNumPredefinedCids; cid < num_cids; cid++) {
961 old_to_new_cid[cid] = -1;
962 }
963
964 intptr_t next_new_cid = kNumPredefinedCids;
965 GrowableArray<intptr_t> dfs_stack;
966 Class& cls = Class::Handle(Z);
968
969 // Object doesn't use its subclasses list.
970 for (intptr_t cid = kNumPredefinedCids; cid < num_cids; cid++) {
971 if (!table->HasValidClassAt(cid)) {
972 continue;
973 }
974 cls = table->At(cid);
975 if (!cls.is_declaration_loaded()) {
976 continue;
977 }
978 if (cls.SuperClass() == IG->object_store()->object_class()) {
979 dfs_stack.Add(cid);
980 }
981 }
982
983 while (dfs_stack.length() > 0) {
984 intptr_t cid = dfs_stack.RemoveLast();
985 ASSERT(table->HasValidClassAt(cid));
986 cls = table->At(cid);
987 ASSERT(!cls.IsNull());
988 if (old_to_new_cid[cid] == -1) {
989 old_to_new_cid[cid] = next_new_cid++;
990 if (FLAG_trace_class_finalization) {
991 THR_Print("%" Pd ": %s, was %" Pd "\n", old_to_new_cid[cid],
992 cls.ToCString(), cid);
993 }
994 }
995 subclasses = cls.direct_subclasses();
996 if (!subclasses.IsNull()) {
997 for (intptr_t i = 0; i < subclasses.Length(); i++) {
998 cls ^= subclasses.At(i);
999 ASSERT(!cls.IsNull());
1000 dfs_stack.Add(cls.id());
1001 }
1002 }
1003 }
1004
1005 // Top-level classes, typedefs, patch classes, etc.
1006 for (intptr_t cid = kNumPredefinedCids; cid < num_cids; cid++) {
1007 if (old_to_new_cid[cid] == -1) {
1008 old_to_new_cid[cid] = next_new_cid++;
1009 if (FLAG_trace_class_finalization && table->HasValidClassAt(cid)) {
1010 cls = table->At(cid);
1011 THR_Print("%" Pd ": %s, was %" Pd "\n", old_to_new_cid[cid],
1012 cls.ToCString(), cid);
1013 }
1014 }
1015 }
1016 ASSERT(next_new_cid == num_cids);
1017 RemapClassIds(old_to_new_cid.get());
1018 // Types use cid's as part of their hashes.
1019 RehashTypes();
1020 // Const objects use cid's as part of their hashes.
1021 IG->RehashConstants(nullptr);
1022}
1023
1025 public:
1026 explicit CidRewriteVisitor(intptr_t* old_to_new_cids)
1027 : old_to_new_cids_(old_to_new_cids) {}
1028
1029 intptr_t Map(intptr_t cid) {
1030 ASSERT(cid != -1);
1031 return old_to_new_cids_[cid];
1032 }
1033
1034 void VisitObject(ObjectPtr obj) override {
1035 if (obj->IsClass()) {
1036 ClassPtr cls = Class::RawCast(obj);
1037 const classid_t old_cid = cls->untag()->id_;
1038 if (ClassTable::IsTopLevelCid(old_cid)) {
1039 // We don't remap cids of top level classes.
1040 return;
1041 }
1042 cls->untag()->id_ = Map(old_cid);
1043 cls->untag()->implementor_cid_ = Map(cls->untag()->implementor_cid_);
1044 } else if (obj->IsField()) {
1045 FieldPtr field = Field::RawCast(obj);
1046 field->untag()->guarded_cid_ = Map(field->untag()->guarded_cid_);
1047 field->untag()->is_nullable_ = Map(field->untag()->is_nullable_);
1048 } else if (obj->IsTypeParameter()) {
1049 TypeParameterPtr param = TypeParameter::RawCast(obj);
1051 param->untag()->flags())) {
1052 param->untag()->set_owner(
1053 Smi::New(Map(Smi::Value(Smi::RawCast(param->untag()->owner())))));
1054 }
1055 } else if (obj->IsType()) {
1056 TypePtr type = Type::RawCast(obj);
1057 type->untag()->set_type_class_id(Map(type->untag()->type_class_id()));
1058 } else {
1059 intptr_t old_cid = obj->GetClassId();
1060 intptr_t new_cid = Map(old_cid);
1061 if (old_cid != new_cid) {
1062 // Don't touch objects that are unchanged. In particular, Instructions,
1063 // which are write-protected.
1064 obj->untag()->SetClassIdUnsynchronized(new_cid);
1065 }
1066 }
1067 }
1068
1069 private:
1070 intptr_t* old_to_new_cids_;
1071};
1072
1073void ClassFinalizer::RemapClassIds(intptr_t* old_to_new_cid) {
1075 IsolateGroup* IG = T->isolate_group();
1076
1077 // Code, ICData, allocation stubs have now-invalid cids.
1078 ClearAllCode();
1079
1080 {
1081 // The [HeapIterationScope] also safepoints all threads.
1082 HeapIterationScope his(T);
1083
1084 // Update the class table. Do it before rewriting cids in headers, as
1085 // the heap walkers load an object's size *after* calling the visitor.
1086 IG->class_table()->Remap(old_to_new_cid);
1087 IG->set_remapping_cids(true);
1088
1089 // Rewrite cids in headers and cids in Classes, Fields, Types and
1090 // TypeParameters.
1091 {
1092 CidRewriteVisitor visitor(old_to_new_cid);
1093 IG->heap()->VisitObjects(&visitor);
1094 }
1095
1096 IG->set_remapping_cids(false);
1097#if defined(DEBUG)
1098 IG->class_table()->Validate();
1099#endif
1100 }
1101
1102#if defined(DEBUG)
1103 IG->heap()->Verify("RemapClassIds");
1104#endif
1105}
1106
1107// Clears the cached canonicalized hash codes for all instances which directly
1108// (or indirectly) depend on class ids.
1109//
1110// In the Dart VM heap the following instances directly use cids for the
1111// computation of canonical hash codes:
1112//
1113// * TypePtr (due to UntaggedType::type_class_id)
1114// * TypeParameterPtr (due to UntaggedTypeParameter::owner_)
1115//
1116// The following instances use cids for the computation of canonical hash codes
1117// indirectly:
1118//
1119// * TypePtr (due to type arguments)
1120// * FunctionTypePtr (due to the result and parameter types)
1121// * RecordTypePtr (due to field types)
1122// * TypeArgumentsPtr (due to type references)
1123// * InstancePtr (due to instance fields)
1124// * ArrayPtr (due to type arguments & array entries)
1125//
1126// Caching of the canonical hash codes happens for:
1127//
1128// * UntaggedAbstractType::hash_
1129// * UntaggedTypeArguments::hash_
1130// * InstancePtr (weak table)
1131// * ArrayPtr (weak table)
1132//
1133// Usages of canonical hash codes are:
1134//
1135// * ObjectStore::canonical_types()
1136// * ObjectStore::canonical_function_types()
1137// * ObjectStore::canonical_record_types()
1138// * ObjectStore::canonical_type_parameters()
1139// * ObjectStore::canonical_type_arguments()
1140// * Class::constants()
1141//
1143 public:
1145 : type_(AbstractType::Handle(zone)),
1146 type_args_(TypeArguments::Handle(zone)) {}
1147
1148 void VisitObject(ObjectPtr obj) override {
1149 if (obj->IsType() || obj->IsTypeParameter() || obj->IsFunctionType() ||
1150 obj->IsRecordType()) {
1151 type_ ^= obj;
1152 type_.SetHash(0);
1153 } else if (obj->IsTypeArguments()) {
1154 type_args_ ^= obj;
1155 type_args_.SetHash(0);
1156 }
1157 }
1158
1159 private:
1160 AbstractType& type_;
1161 TypeArguments& type_args_;
1162};
1163
1165 auto T = Thread::Current();
1166 auto Z = T->zone();
1167 auto IG = T->isolate_group();
1168
1169 // Clear all cached hash values.
1170 {
1171 HeapIterationScope his(T);
1172 ClearTypeHashVisitor visitor(Z);
1173 IG->heap()->VisitObjects(&visitor);
1174 }
1175
1176 // Rehash the canonical Types table.
1177 ObjectStore* object_store = IG->object_store();
1178 Array& types = Array::Handle(Z);
1179 Type& type = Type::Handle(Z);
1180 {
1181 CanonicalTypeSet types_table(Z, object_store->canonical_types());
1182 types = HashTables::ToArray(types_table, false);
1183 types_table.Release();
1184 }
1185
1186 intptr_t dict_size = Utils::RoundUpToPowerOfTwo(types.Length() * 4 / 3);
1187 CanonicalTypeSet types_table(
1188 Z, HashTables::New<CanonicalTypeSet>(dict_size, Heap::kOld));
1189 for (intptr_t i = 0; i < types.Length(); i++) {
1190 type ^= types.At(i);
1191 bool present = types_table.Insert(type);
1192 ASSERT(!present);
1193 }
1194 object_store->set_canonical_types(types_table.Release());
1195
1196 // Rehash the canonical FunctionTypes table.
1197 Array& function_types = Array::Handle(Z);
1198 FunctionType& function_type = FunctionType::Handle(Z);
1199 {
1200 CanonicalFunctionTypeSet function_types_table(
1201 Z, object_store->canonical_function_types());
1202 function_types = HashTables::ToArray(function_types_table, false);
1203 function_types_table.Release();
1204 }
1205
1206 dict_size = Utils::RoundUpToPowerOfTwo(function_types.Length() * 4 / 3);
1207 CanonicalFunctionTypeSet function_types_table(
1208 Z, HashTables::New<CanonicalFunctionTypeSet>(dict_size, Heap::kOld));
1209 for (intptr_t i = 0; i < function_types.Length(); i++) {
1210 function_type ^= function_types.At(i);
1211 bool present = function_types_table.Insert(function_type);
1212 ASSERT(!present);
1213 }
1214 object_store->set_canonical_function_types(function_types_table.Release());
1215
1216 // Rehash the canonical RecordTypes table.
1217 Array& record_types = Array::Handle(Z);
1218 RecordType& record_type = RecordType::Handle(Z);
1219 {
1220 CanonicalRecordTypeSet record_types_table(
1221 Z, object_store->canonical_record_types());
1222 record_types = HashTables::ToArray(record_types_table, false);
1223 record_types_table.Release();
1224 }
1225
1226 dict_size = Utils::RoundUpToPowerOfTwo(record_types.Length() * 4 / 3);
1227 CanonicalRecordTypeSet record_types_table(
1228 Z, HashTables::New<CanonicalRecordTypeSet>(dict_size, Heap::kOld));
1229 for (intptr_t i = 0; i < record_types.Length(); i++) {
1230 record_type ^= record_types.At(i);
1231 bool present = record_types_table.Insert(record_type);
1232 ASSERT(!present);
1233 }
1234 object_store->set_canonical_record_types(record_types_table.Release());
1235
1236 // Rehash the canonical TypeParameters table.
1237 Array& typeparams = Array::Handle(Z);
1239 {
1240 CanonicalTypeParameterSet typeparams_table(
1241 Z, object_store->canonical_type_parameters());
1242 typeparams = HashTables::ToArray(typeparams_table, false);
1243 typeparams_table.Release();
1244 }
1245
1246 dict_size = Utils::RoundUpToPowerOfTwo(typeparams.Length() * 4 / 3);
1247 CanonicalTypeParameterSet typeparams_table(
1248 Z, HashTables::New<CanonicalTypeParameterSet>(dict_size, Heap::kOld));
1249 for (intptr_t i = 0; i < typeparams.Length(); i++) {
1250 typeparam ^= typeparams.At(i);
1251 bool present = typeparams_table.Insert(typeparam);
1252 ASSERT(!present);
1253 }
1254 object_store->set_canonical_type_parameters(typeparams_table.Release());
1255
1256 // Rehash the canonical TypeArguments table.
1257 Array& typeargs = Array::Handle(Z);
1259 {
1260 CanonicalTypeArgumentsSet typeargs_table(
1261 Z, object_store->canonical_type_arguments());
1262 typeargs = HashTables::ToArray(typeargs_table, false);
1263 typeargs_table.Release();
1264 }
1265
1266 // The canonical constant tables use canonical hashcodes which can change
1267 // due to cid-renumbering.
1268 IG->RehashConstants(nullptr);
1269
1270 dict_size = Utils::RoundUpToPowerOfTwo(typeargs.Length() * 4 / 3);
1271 CanonicalTypeArgumentsSet typeargs_table(
1272 Z, HashTables::New<CanonicalTypeArgumentsSet>(dict_size, Heap::kOld));
1273 for (intptr_t i = 0; i < typeargs.Length(); i++) {
1274 typearg ^= typeargs.At(i);
1275 bool present = typeargs_table.Insert(typearg);
1276 ASSERT(!present);
1277 }
1278 object_store->set_canonical_type_arguments(typeargs_table.Release());
1279}
1280
1281void ClassFinalizer::ClearAllCode(bool including_nonchanging_cids) {
1282 auto const thread = Thread::Current();
1283 auto const isolate_group = thread->isolate_group();
1284 SafepointWriteRwLocker ml(thread, isolate_group->program_lock());
1285 StackZone stack_zone(thread);
1286 auto const zone = thread->zone();
1287
1288 class ClearCodeVisitor : public FunctionVisitor {
1289 public:
1290 ClearCodeVisitor(Zone* zone, bool force)
1291 : force_(force),
1292 pool_(ObjectPool::Handle(zone)),
1293 entry_(Object::Handle(zone)) {}
1294
1295 void VisitClass(const Class& cls) {
1296 if (force_ || cls.id() >= kNumPredefinedCids) {
1298 }
1299 }
1300
1301 void VisitFunction(const Function& function) {
1302 function.ClearCode();
1303 function.ClearICDataArray();
1304 }
1305
1306 private:
1307 const bool force_;
1308 ObjectPool& pool_;
1309 Object& entry_;
1310 };
1311
1312 ClearCodeVisitor visitor(zone, including_nonchanging_cids);
1313 ProgramVisitor::WalkProgram(zone, isolate_group, &visitor);
1314}
1315
1316#endif // !defined(DART_PRECOMPILED_RUNTIME)
1317
1318} // namespace dart
SI F table(const skcms_Curve *curve, F v)
#define IG
#define UNREACHABLE()
Definition: assert.h:248
#define ASSERT_EQUAL(expected, actual)
Definition: assert.h:309
#define Z
GLenum type
virtual bool HasTypeClass() const
Definition: object.h:9083
void SetHash(intptr_t value) const
Definition: object.h:13386
virtual ClassPtr type_class() const
Definition: object.cc:21042
static intptr_t InstanceSize()
Definition: object.h:10936
ObjectPtr At(intptr_t index) const
Definition: object.h:10875
intptr_t Length() const
Definition: object.h:10829
void Add(const T &value)
intptr_t length() const
static constexpr T decode(S value)
Definition: bitfield.h:171
static intptr_t InstanceSize()
Definition: object.h:10793
static intptr_t NumberOfFields()
Definition: object.h:11870
static intptr_t data_offset()
Definition: object.h:11872
CidRewriteVisitor(intptr_t *old_to_new_cids)
void VisitObject(ObjectPtr obj) override
intptr_t Map(intptr_t cid)
static AbstractTypePtr FinalizeType(const AbstractType &type, FinalizationKind finalization=kCanonicalize)
static bool ProcessPendingClasses()
static void MarkClassHasDynamicallyExtendableSubtypes(Zone *zone, const Class &cls)
static void MarkClassCanBeFuture(Zone *zone, const Class &cls)
static void VerifyBootstrapClasses()
static bool AllClassesFinalized()
static void FinalizeTypesInClass(const Class &cls)
static void RegisterClassInHierarchy(Zone *zone, const Class &cls)
static ErrorPtr AllocateFinalizeClass(const Class &cls)
static void FinalizeClass(const Class &cls)
static void ClearAllCode(bool including_nonchanging_cids=false)
static void RemapClassIds(intptr_t *old_to_new_cid)
static void SortClasses()
static ErrorPtr LoadClassMembers(const Class &cls)
ClassPtr At(intptr_t cid) const
Definition: class_table.h:362
static bool IsTopLevelCid(intptr_t cid)
Definition: class_table.h:496
bool has_dynamically_extendable_subtypes() const
Definition: object.h:2196
void set_is_implemented() const
Definition: object.cc:5613
intptr_t kernel_offset() const
Definition: object.h:1804
LibraryPtr library() const
Definition: object.h:1333
void set_is_isolate_unsendable_due_to_pragma(bool value) const
Definition: object.cc:3138
void set_super_type(const Type &value) const
Definition: object.cc:3684
void set_is_allocate_finalized() const
Definition: object.cc:5725
void Finalize() const
Definition: object.cc:4307
bool can_be_future() const
Definition: object.h:2188
bool is_declaration_loaded() const
Definition: object.h:1703
GrowableObjectArrayPtr direct_subclasses() const
Definition: object.h:1537
TypePtr super_type() const
Definition: object.h:1431
intptr_t id() const
Definition: object.h:1233
intptr_t NumTypeArguments() const
Definition: object.cc:3640
bool is_loaded() const
Definition: object.h:1785
ArrayPtr interfaces() const
Definition: object.h:1447
bool is_type_finalized() const
Definition: object.h:1709
void SetUserVisibleNameInClassTable()
Definition: object.cc:5383
ArrayPtr fields() const
Definition: object.h:1615
void DisableAllocationStub() const
Definition: object.cc:5879
bool HasInstanceFields() const
Definition: object.cc:3211
void set_is_future_subtype(bool value) const
Definition: object.cc:3149
intptr_t host_instance_size() const
Definition: object.h:1143
void DisableCHAOptimizedCode(const Class &subclass)
Definition: object.cc:4402
bool is_abstract() const
Definition: object.h:1696
bool IsGeneric() const
Definition: object.h:1358
StringPtr Name() const
Definition: object.cc:2977
bool is_dynamically_extendable() const
Definition: object.h:2191
bool is_prefinalized() const
Definition: object.h:1738
bool IsFutureClass() const
Definition: object.cc:5907
bool is_future_subtype() const
Definition: object.h:2182
ClassPtr SuperClass(ClassTable *class_table=nullptr) const
Definition: object.cc:3665
bool IsTopLevel() const
Definition: object.cc:6121
void set_has_dynamically_extendable_subtypes(bool value) const
Definition: object.cc:3164
bool NoteImplementor(const Class &implementor) const
Definition: object.cc:5580
TypeParametersPtr type_parameters() const
Definition: object.h:1338
void set_is_type_finalized() const
Definition: object.cc:5638
const char * UserVisibleNameCString() const
Definition: object.cc:2998
bool is_implemented() const
Definition: object.h:1692
bool is_allocate_finalized() const
Definition: object.h:1732
bool is_transformed_mixin_application() const
Definition: object.h:1754
intptr_t NumTypeParameters(Thread *thread) const
Definition: object.cc:3555
bool is_isolate_unsendable_due_to_pragma() const
Definition: object.h:2169
bool is_finalized() const
Definition: object.h:1723
ArrayPtr current_functions() const
Definition: object.h:1641
void EnsureDeclarationLoaded() const
Definition: object.cc:4913
void set_can_be_future(bool value) const
Definition: object.cc:3154
void VisitObject(ObjectPtr obj) override
static intptr_t InstanceSize()
Definition: object.h:10135
virtual const char * ToErrorCString() const
Definition: object.cc:19780
static intptr_t InstanceSize()
Definition: object.h:13012
static intptr_t InstanceSize()
Definition: object.h:13081
static GrowableObjectArrayPtr New(Heap::Space space=Heap::kNew)
Definition: object.h:11144
intptr_t Length() const
Definition: object.h:11072
ObjectPtr At(intptr_t index) const
Definition: object.h:11085
bool Insert(const Object &key)
Definition: hash_table.h:801
StorageTraits::ArrayHandle & Release()
Definition: hash_table.h:195
static ArrayPtr ToArray(const Table &table, bool include_payload)
Definition: hash_table.h:653
@ kOld
Definition: heap.h:39
bool Verify(const char *msg, MarkExpectation mark_expectation=kForbidMarked)
Definition: heap.cc:771
static intptr_t InstanceSize()
Definition: object.h:11046
static intptr_t InstanceSize()
Definition: object.h:8337
InterfaceFinder(Zone *zone, ClassTable *class_table, GrowableArray< intptr_t > *cids)
void FindAllInterfaces(const Class &klass)
Heap * heap() const
Definition: isolate.h:296
ObjectStore * object_store() const
Definition: isolate.h:510
SafepointRwLock * program_lock()
Definition: isolate.h:537
static IsolateGroup * Current()
Definition: isolate.h:539
ClassTable * class_table() const
Definition: isolate.h:496
StringPtr private_key() const
Definition: object.h:5099
StringPtr url() const
Definition: object.h:5097
jmp_buf * Set()
Definition: longjump.cc:16
static intptr_t InstanceSize()
Definition: object.h:12111
static intptr_t InstanceSize()
Definition: object.h:10090
static DART_NORETURN void Exit(int code)
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
UntaggedObject * untag() const
intptr_t GetClassId() const
Definition: raw_object.h:885
static ObjectPtr null()
Definition: object.h:433
ObjectPtr ptr() const
Definition: object.h:332
virtual const char * ToCString() const
Definition: object.h:366
bool IsNull() const
Definition: object.h:363
static Object & Handle()
Definition: object.h:407
static ObjectPtr RawCast(ObjectPtr obj)
Definition: object.h:325
static intptr_t InstanceSize()
Definition: object.h:10564
static constexpr intptr_t kNativeTypeArgPos
Definition: object.h:11906
static void WalkProgram(Zone *zone, IsolateGroup *isolate_group, ClassVisitor *visitor)
static void static void MessageV(Kind kind, const Script &script, TokenPosition token_pos, bool report_after_token, const char *format, va_list args)
Definition: report.cc:135
static DART_NORETURN void LongJump(const Error &error)
Definition: report.cc:86
static constexpr bool AtLocation
Definition: report.h:29
static intptr_t InstanceSize()
Definition: object.h:12214
static SmiPtr New(intptr_t value)
Definition: object.h:10006
static intptr_t InstanceSize()
Definition: object.h:10004
intptr_t Value() const
Definition: object.h:9990
static StaticTypeExactnessState Uninitialized()
static StringPtr New(const char *cstr, Heap::Space space=Heap::kNew)
Definition: object.cc:23698
static bool EqualsIgnoringPrivateKey(const String &str1, const String &str2)
Definition: object.cc:24299
Zone * zone() const
Definition: thread_state.h:37
static Thread * Current()
Definition: thread.h:362
DART_WARN_UNUSED_RESULT ErrorPtr StealStickyError()
Definition: thread.cc:245
IsolateGroup * isolate_group() const
Definition: thread.h:541
ErrorPtr sticky_error() const
Definition: thread.cc:232
static intptr_t InstanceSize()
Definition: object.h:10704
bool IsClassTypeParameter() const
Definition: object.h:9817
void set_parameterized_class_id(classid_t value) const
Definition: object.cc:22705
intptr_t index() const
Definition: object.h:9821
void set_index(intptr_t value) const
Definition: object.cc:22731
ClassPtr parameterized_class() const
Definition: object.cc:22710
AbstractTypePtr bound() const
Definition: object.cc:22737
void set_base(intptr_t value) const
Definition: object.cc:22725
static constexpr uintptr_t RoundUpToPowerOfTwo(uintptr_t x)
Definition: utils.h:135
static bool IsUint(intptr_t N, T value)
Definition: utils.h:328
static intptr_t InstanceSize()
Definition: object.h:12932
static intptr_t InstanceSize()
Definition: object.h:12958
static void FinishLoading(const Class &klass)
#define THR_Print(format,...)
Definition: log.h:20
#define ASSERT(E)
#define FATAL(error)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
const uint8_t uint32_t uint32_t GError ** error
uint32_t uint32_t * format
Dart_NativeFunction function
Definition: fuchsia.cc:51
#define HANDLESCOPE(thread)
Definition: handles.h:321
va_start(args, format)
va_end(args)
Definition: dart_vm.cc:33
static void MarkImplemented(Zone *zone, const Class &iface)
static void CollectFinalizedSuperClasses(const Class &cls_, GrowableArray< intptr_t > *finalized_super_classes)
const char *const name
static void AddSuperType(const AbstractType &type, GrowableArray< intptr_t > *finalized_super_classes)
static bool IsPotentialExactGeneric(const AbstractType &type)
const char *const class_name
int32_t classid_t
Definition: globals.h:524
@ kIllegalCid
Definition: class_id.h:214
@ kNumPredefinedCids
Definition: class_id.h:257
@ kVoidCid
Definition: class_id.h:254
@ kByteBufferCid
Definition: class_id.h:247
@ kDynamicCid
Definition: class_id.h:253
DEFINE_FLAG(bool, print_cluster_information, false, "Print information about clusters written to snapshot")
const intptr_t cid
static void RemoveCHAOptimizedCode(const Class &subclass, const GrowableArray< intptr_t > &added_subclass_to_cids)
static void CollectImmediateSuperInterfaces(const Class &cls, GrowableArray< intptr_t > *cids)
def ReportError(text)
Definition: main.py:86
#define Pd
Definition: globals.h:408
#define T
Definition: precompiler.cc:65
SeparatedVector2 offset
#define TIMELINE_DURATION(thread, stream, name)
Definition: timeline.h:39