Flutter Engine
The Flutter Engine
Public Types | Static Public Member Functions | List of all members
dart::ClassFinalizer Class Reference

#include <class_finalizer.h>

Inheritance diagram for dart::ClassFinalizer:
dart::AllStatic

Public Types

enum  FinalizationKind { kFinalize , kCanonicalize }
 

Static Public Member Functions

static AbstractTypePtr FinalizeType (const AbstractType &type, FinalizationKind finalization=kCanonicalize)
 
static bool AllClassesFinalized ()
 
static void SortClasses ()
 
static void RemapClassIds (intptr_t *old_to_new_cid)
 
static void RehashTypes ()
 
static void ClearAllCode (bool including_nonchanging_cids=false)
 
static bool ProcessPendingClasses ()
 
static void FinalizeTypesInClass (const Class &cls)
 
static void RegisterClassInHierarchy (Zone *zone, const Class &cls)
 
static void MarkClassCanBeFuture (Zone *zone, const Class &cls)
 
static void MarkClassHasDynamicallyExtendableSubtypes (Zone *zone, const Class &cls)
 
static void FinalizeClass (const Class &cls)
 
static ErrorPtr AllocateFinalizeClass (const Class &cls)
 
static ErrorPtr LoadClassMembers (const Class &cls)
 
static void VerifyBootstrapClasses ()
 

Detailed Description

Definition at line 18 of file class_finalizer.h.

Member Enumeration Documentation

◆ FinalizationKind

Enumerator
kFinalize 
kCanonicalize 

Definition at line 21 of file class_finalizer.h.

21 {
22 kFinalize, // Finalize type and type arguments.
23 kCanonicalize // Finalize and canonicalize.
24 };

Member Function Documentation

◆ AllClassesFinalized()

bool dart::ClassFinalizer::AllClassesFinalized ( )
static

Definition at line 33 of file class_finalizer.cc.

33 {
34 ObjectStore* object_store = IsolateGroup::Current()->object_store();
35 const GrowableObjectArray& classes =
36 GrowableObjectArray::Handle(object_store->pending_classes());
37 return classes.Length() == 0;
38}
ObjectStore * object_store() const
Definition: isolate.h:510
static IsolateGroup * Current()
Definition: isolate.h:539
static Object & Handle()
Definition: object.h:407

◆ AllocateFinalizeClass()

ErrorPtr dart::ClassFinalizer::AllocateFinalizeClass ( const Class cls)
static

Definition at line 766 of file class_finalizer.cc.

766 {
767 ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
768 ASSERT(cls.is_finalized());
769 ASSERT(!cls.is_allocate_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 {
790 GrowableArray<intptr_t> cids;
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 {
803 GrowableArray<intptr_t> cids;
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
813 cls.set_is_allocate_finalized();
814 return Error::null();
815}
static ObjectPtr null()
Definition: object.h:433
static Thread * Current()
Definition: thread.h:362
#define THR_Print(format,...)
Definition: log.h:20
#define ASSERT(E)
#define HANDLESCOPE(thread)
Definition: handles.h:321
static void CollectFinalizedSuperClasses(const Class &cls_, GrowableArray< intptr_t > *finalized_super_classes)
static void RemoveCHAOptimizedCode(const Class &subclass, const GrowableArray< intptr_t > &added_subclass_to_cids)
static void CollectImmediateSuperInterfaces(const Class &cls, GrowableArray< intptr_t > *cids)

◆ ClearAllCode()

void dart::ClassFinalizer::ClearAllCode ( bool  including_nonchanging_cids = false)
static

Definition at line 1281 of file class_finalizer.cc.

1281 {
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) {
1297 cls.DisableAllocationStub();
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}
static void WalkProgram(Zone *zone, IsolateGroup *isolate_group, ClassVisitor *visitor)
Dart_NativeFunction function
Definition: fuchsia.cc:51
@ kNumPredefinedCids
Definition: class_id.h:257

◆ FinalizeClass()

void dart::ClassFinalizer::FinalizeClass ( const Class cls)
static

Definition at line 706 of file class_finalizer.cc.

706 {
707 ASSERT(cls.is_type_finalized());
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()) {
759 cls.set_is_allocate_finalized();
760 }
761#endif // defined(DART_PRECOMPILED_RUNTIME)
762}
#define UNREACHABLE()
Definition: assert.h:248
static void FinalizeClass(const Class &cls)
static void FinishLoading(const Class &klass)

◆ FinalizeType()

AbstractTypePtr dart::ClassFinalizer::FinalizeType ( const AbstractType type,
FinalizationKind  finalization = kCanonicalize 
)
static

Definition at line 350 of file class_finalizer.cc.

351 {
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.
403 type_parameter.set_parameterized_class_id(kIllegalCid);
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
412 AbstractType& type = AbstractType::Handle(zone);
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);
423 AbstractType& type = AbstractType::Handle(zone);
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}
GLenum type
static AbstractTypePtr FinalizeType(const AbstractType &type, FinalizationKind finalization=kCanonicalize)
static bool IsUint(intptr_t N, T value)
Definition: utils.h:328
#define FATAL(error)
@ kIllegalCid
Definition: class_id.h:214
SeparatedVector2 offset

◆ FinalizeTypesInClass()

void dart::ClassFinalizer::FinalizeTypesInClass ( const Class cls)
static

Definition at line 550 of file class_finalizer.cc.

550 {
551 Thread* thread = Thread::Current();
552 HANDLESCOPE(thread);
553 cls.EnsureDeclarationLoaded();
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 =
572 cls.is_isolate_unsendable_due_to_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(
582 zone, TypeParameters::Handle(zone, cls.type_parameters()), kCanonicalize);
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 |=
591 super_class.is_isolate_unsendable_due_to_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 }
609 cls.set_is_type_finalized();
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}
static void MarkClassHasDynamicallyExtendableSubtypes(Zone *zone, const Class &cls)
static void MarkClassCanBeFuture(Zone *zone, const Class &cls)
static void FinalizeTypesInClass(const Class &cls)
static void RegisterClassInHierarchy(Zone *zone, const Class &cls)

◆ LoadClassMembers()

ErrorPtr dart::ClassFinalizer::LoadClassMembers ( const Class cls)
static

Definition at line 817 of file class_finalizer.cc.

817 {
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)
824 cls.EnsureDeclarationLoaded();
825#endif
826 ASSERT(cls.is_type_finalized());
828 return Error::null();
829 } else {
831 }
832}
DART_WARN_UNUSED_RESULT ErrorPtr StealStickyError()
Definition: thread.cc:245

◆ MarkClassCanBeFuture()

void dart::ClassFinalizer::MarkClassCanBeFuture ( Zone zone,
const Class cls 
)
static

Definition at line 667 of file class_finalizer.cc.

667 {
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}

◆ MarkClassHasDynamicallyExtendableSubtypes()

void dart::ClassFinalizer::MarkClassHasDynamicallyExtendableSubtypes ( Zone zone,
const Class cls 
)
static

Definition at line 685 of file class_finalizer.cc.

687 {
688 if (cls.has_dynamically_extendable_subtypes()) return;
689
690 cls.set_has_dynamically_extendable_subtypes(true);
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}

◆ ProcessPendingClasses()

bool dart::ClassFinalizer::ProcessPendingClasses ( )
static

Definition at line 185 of file class_finalizer.cc.

185 {
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) {
202 GrowableObjectArray& class_array = GrowableObjectArray::Handle();
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')?
211 ASSERT(cls.is_declaration_loaded());
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)
220 cls.SetUserVisibleNameInClassTable();
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}
static bool AllClassesFinalized()
static GrowableObjectArrayPtr New(Heap::Space space=Heap::kNew)
Definition: object.h:11144
const uint8_t uint32_t uint32_t GError ** error
#define TIMELINE_DURATION(thread, stream, name)
Definition: timeline.h:39

◆ RegisterClassInHierarchy()

void dart::ClassFinalizer::RegisterClassInHierarchy ( Zone zone,
const Class cls 
)
static

Definition at line 624 of file class_finalizer.cc.

624 {
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()) {
649 GrowableArray<const Class*> worklist;
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}
static void MarkImplemented(Zone *zone, const Class &iface)

◆ RehashTypes()

void dart::ClassFinalizer::RehashTypes ( )
static

Definition at line 1164 of file class_finalizer.cc.

1164 {
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);
1238 TypeParameter& typeparam = TypeParameter::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);
1258 TypeArguments& typearg = TypeArguments::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}
#define IG
#define Z
static ArrayPtr ToArray(const Table &table, bool include_payload)
Definition: hash_table.h:653
@ kOld
Definition: heap.h:39
static constexpr uintptr_t RoundUpToPowerOfTwo(uintptr_t x)
Definition: utils.h:135
UnorderedHashSet< CanonicalFunctionTypeTraits > CanonicalFunctionTypeSet
UnorderedHashSet< CanonicalTypeArgumentsTraits > CanonicalTypeArgumentsSet
UnorderedHashSet< CanonicalTypeParameterTraits > CanonicalTypeParameterSet
UnorderedHashSet< CanonicalTypeTraits > CanonicalTypeSet
UnorderedHashSet< CanonicalRecordTypeTraits > CanonicalRecordTypeSet
#define T
Definition: precompiler.cc:65

◆ RemapClassIds()

void dart::ClassFinalizer::RemapClassIds ( intptr_t *  old_to_new_cid)
static

Definition at line 1073 of file class_finalizer.cc.

1073 {
1074 Thread* T = Thread::Current();
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}
static void ClearAllCode(bool including_nonchanging_cids=false)

◆ SortClasses()

void dart::ClassFinalizer::SortClasses ( )
static

Definition at line 941 of file class_finalizer.cc.

941 {
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);
967 GrowableObjectArray& subclasses = GrowableObjectArray::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}
SI F table(const skcms_Curve *curve, F v)
static void RemapClassIds(intptr_t *old_to_new_cid)
const intptr_t cid
#define Pd
Definition: globals.h:408

◆ VerifyBootstrapClasses()

void dart::ClassFinalizer::VerifyBootstrapClasses ( )
static

Definition at line 237 of file class_finalizer.cc.

237 {
238 if (FLAG_trace_class_finalization) {
239 OS::PrintErr("VerifyBootstrapClasses START.\n");
240 }
241 ObjectStore* object_store = IsolateGroup::Current()->object_store();
242
243 Class& cls = Class::Handle();
244#if defined(DEBUG)
245 // Basic checking.
246 cls = object_store->object_class();
247 ASSERT_EQUAL(Instance::InstanceSize(), cls.host_instance_size());
248 cls = object_store->integer_implementation_class();
249 ASSERT_EQUAL(Integer::InstanceSize(), cls.host_instance_size());
250 cls = object_store->smi_class();
251 ASSERT_EQUAL(Smi::InstanceSize(), cls.host_instance_size());
252 cls = object_store->mint_class();
253 ASSERT_EQUAL(Mint::InstanceSize(), cls.host_instance_size());
254 cls = object_store->one_byte_string_class();
255 ASSERT_EQUAL(OneByteString::InstanceSize(), cls.host_instance_size());
256 cls = object_store->two_byte_string_class();
257 ASSERT_EQUAL(TwoByteString::InstanceSize(), cls.host_instance_size());
258 cls = object_store->double_class();
259 ASSERT_EQUAL(Double::InstanceSize(), cls.host_instance_size());
260 cls = object_store->bool_class();
261 ASSERT_EQUAL(Bool::InstanceSize(), cls.host_instance_size());
262 cls = object_store->array_class();
263 ASSERT_EQUAL(Array::InstanceSize(), cls.host_instance_size());
264 cls = object_store->immutable_array_class();
265 ASSERT_EQUAL(ImmutableArray::InstanceSize(), cls.host_instance_size());
266 cls = object_store->weak_property_class();
267 ASSERT_EQUAL(WeakProperty::InstanceSize(), cls.host_instance_size());
268 cls = object_store->weak_reference_class();
269 ASSERT_EQUAL(WeakReference::InstanceSize(), cls.host_instance_size());
270 cls = object_store->finalizer_class();
271 ASSERT_EQUAL(Finalizer::InstanceSize(), cls.host_instance_size());
272 cls = object_store->finalizer_entry_class();
273 ASSERT_EQUAL(FinalizerEntry::InstanceSize(), cls.host_instance_size());
274 cls = object_store->map_impl_class();
275 ASSERT_EQUAL(Map::InstanceSize(), cls.host_instance_size());
276 cls = object_store->const_map_impl_class();
277 ASSERT_EQUAL(Map::InstanceSize(), cls.host_instance_size());
278 cls = object_store->set_impl_class();
279 ASSERT_EQUAL(Set::InstanceSize(), cls.host_instance_size());
280 cls = object_store->const_set_impl_class();
281 ASSERT_EQUAL(Set::InstanceSize(), cls.host_instance_size());
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.
292 ASSERT(!cls.HasInstanceFields());
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}
#define ASSERT_EQUAL(expected, actual)
Definition: assert.h:309
static intptr_t InstanceSize()
Definition: object.h:10936
static intptr_t InstanceSize()
Definition: object.h:10793
static bool ProcessPendingClasses()
static intptr_t InstanceSize()
Definition: object.h:10135
static intptr_t InstanceSize()
Definition: object.h:13012
static intptr_t InstanceSize()
Definition: object.h:13081
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
Heap * heap() const
Definition: isolate.h:296
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
static intptr_t InstanceSize()
Definition: object.h:10564
static intptr_t InstanceSize()
Definition: object.h:12214
static intptr_t InstanceSize()
Definition: object.h:10004
static intptr_t InstanceSize()
Definition: object.h:10704
static intptr_t InstanceSize()
Definition: object.h:12932
static intptr_t InstanceSize()
Definition: object.h:12958

The documentation for this class was generated from the following files: