Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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 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:505
static IsolateGroup * Current()
Definition isolate.h:534
static Object & Handle()
Definition object.h:407

◆ AllocateFinalizeClass()

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

Definition at line 743 of file class_finalizer.cc.

743 {
744 ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
745 ASSERT(cls.is_finalized());
746 ASSERT(!cls.is_allocate_finalized());
747
748 Thread* thread = Thread::Current();
749 HANDLESCOPE(thread);
750
751 if (FLAG_trace_class_finalization) {
752 THR_Print("Allocate finalize %s\n", cls.ToCString());
753 }
754
755#if defined(SUPPORT_TIMELINE)
756 TimelineBeginEndScope tbes(thread, Timeline::GetCompilerStream(),
757 "AllocateFinalizeClass");
758 if (tbes.enabled()) {
759 tbes.SetNumArguments(1);
760 tbes.CopyArgument(0, "class", cls.ToCString());
761 }
762#endif // defined(SUPPORT_TIMELINE)
763
764 // Run additional checks after all types are finalized.
765 if (FLAG_use_cha_deopt && !cls.IsTopLevel()) {
766 {
767 GrowableArray<intptr_t> cids;
770 RemoveCHAOptimizedCode(cls, cids);
771 }
772
773 Zone* zone = thread->zone();
774 ClassTable* class_table = thread->isolate_group()->class_table();
775 auto& interface_class = Class::Handle(zone);
776
777 // We scan every interface this [cls] implements and invalidate all CHA
778 // code which depends on knowing the implementors of that interface.
779 {
780 GrowableArray<intptr_t> cids;
781 InterfaceFinder finder(zone, class_table, &cids);
782 finder.FindAllInterfaces(cls);
783 for (intptr_t j = 0; j < cids.length(); ++j) {
784 interface_class = class_table->At(cids[j]);
785 interface_class.DisableCHAImplementorUsers();
786 }
787 }
788 }
789
790 cls.set_is_allocate_finalized();
791 return Error::null();
792}
static ObjectPtr null()
Definition object.h:433
static Thread * Current()
Definition thread.h:361
#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 1258 of file class_finalizer.cc.

1258 {
1259 auto const thread = Thread::Current();
1260 auto const isolate_group = thread->isolate_group();
1261 SafepointWriteRwLocker ml(thread, isolate_group->program_lock());
1262 StackZone stack_zone(thread);
1263 auto const zone = thread->zone();
1264
1265 class ClearCodeVisitor : public FunctionVisitor {
1266 public:
1267 ClearCodeVisitor(Zone* zone, bool force)
1268 : force_(force),
1269 pool_(ObjectPool::Handle(zone)),
1270 entry_(Object::Handle(zone)) {}
1271
1272 void VisitClass(const Class& cls) {
1273 if (force_ || cls.id() >= kNumPredefinedCids) {
1274 cls.DisableAllocationStub();
1275 }
1276 }
1277
1278 void VisitFunction(const Function& function) {
1279 function.ClearCode();
1280 function.ClearICDataArray();
1281 }
1282
1283 private:
1284 const bool force_;
1285 ObjectPool& pool_;
1286 Object& entry_;
1287 };
1288
1289 ClearCodeVisitor visitor(zone, including_nonchanging_cids);
1290 ProgramVisitor::WalkProgram(zone, isolate_group, &visitor);
1291}
static void WalkProgram(Zone *zone, IsolateGroup *isolate_group, ClassVisitor *visitor)
Dart_NativeFunction function
Definition fuchsia.cc:51

◆ FinalizeClass()

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

Definition at line 683 of file class_finalizer.cc.

683 {
684 ASSERT(cls.is_type_finalized());
685 if (cls.is_finalized()) {
686 return;
687 }
688
689#if defined(DART_PRECOMPILED_RUNTIME)
690 UNREACHABLE();
691#else
692 Thread* thread = Thread::Current();
693 HANDLESCOPE(thread);
694
695 if (FLAG_trace_class_finalization) {
696 THR_Print("Finalize %s\n", cls.ToCString());
697 }
698
699#if defined(SUPPORT_TIMELINE)
700 TimelineBeginEndScope tbes(thread, Timeline::GetCompilerStream(),
701 "FinalizeClass");
702 if (tbes.enabled()) {
703 tbes.SetNumArguments(1);
704 tbes.CopyArgument(0, "class", cls.ToCString());
705 }
706#endif // defined(SUPPORT_TIMELINE)
707
708 // If loading from a kernel, make sure that the class is fully loaded.
709 ASSERT(cls.IsTopLevel() || (cls.kernel_offset() > 0));
710 if (!cls.is_loaded()) {
712 if (cls.is_finalized()) {
713 return;
714 }
715 }
716
717 // Ensure super class is finalized.
718 const Class& super = Class::Handle(cls.SuperClass());
719 if (!super.IsNull()) {
720 FinalizeClass(super);
721 if (cls.is_finalized()) {
722 return;
723 }
724 }
725 // Mark as loaded and finalized.
726 cls.Finalize();
727 if (FLAG_print_classes) {
728 PrintClassInformation(cls);
729 }
730 FinalizeMemberTypes(cls);
731
732 // The rest of finalization for non-top-level class has to be done with
733 // stopped mutators. It will be done by AllocateFinalizeClass. before new
734 // instance of a class is created in GetAllocationStubForClass.
735 if (cls.IsTopLevel()) {
736 cls.set_is_allocate_finalized();
737 }
738#endif // defined(DART_PRECOMPILED_RUNTIME)
739}
#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}
static AbstractTypePtr FinalizeType(const AbstractType &type, FinalizationKind finalization=kCanonicalize)
static bool IsUint(intptr_t N, T value)
Definition utils.h:313
#define FATAL(error)
@ kIllegalCid
Definition class_id.h:214
Point 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
616 RegisterClassInHierarchy(zone, cls);
617#endif // defined(DART_PRECOMPILED_RUNTIME)
618}
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 794 of file class_finalizer.cc.

794 {
795 ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
796 ASSERT(!cls.is_finalized());
797
798 LongJumpScope jump;
799 if (setjmp(*jump.Set()) == 0) {
800#if !defined(DART_PRECOMPILED_RUNTIME)
801 cls.EnsureDeclarationLoaded();
802#endif
803 ASSERT(cls.is_type_finalized());
805 return Error::null();
806 } else {
808 }
809}
DART_WARN_UNUSED_RESULT ErrorPtr StealStickyError()
Definition thread.cc:243

◆ MarkClassCanBeFuture()

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

Definition at line 664 of file class_finalizer.cc.

664 {
665 if (cls.can_be_future()) return;
666
667 cls.set_can_be_future(true);
668
669 Class& base = Class::Handle(zone, cls.SuperClass());
670 if (!base.IsNull()) {
672 }
673 auto& interfaces = Array::Handle(zone, cls.interfaces());
674 auto& type = AbstractType::Handle(zone);
675 for (intptr_t i = 0; i < interfaces.Length(); ++i) {
676 type ^= interfaces.At(i);
677 base = type.type_class();
679 }
680}

◆ 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:11118
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 621 of file class_finalizer.cc.

621 {
622 auto& type = AbstractType::Handle(zone, cls.super_type());
623 auto& other_cls = Class::Handle(zone);
624 // Add this class to the direct subclasses of the superclass, unless the
625 // superclass is Object.
626 if (!type.IsNull() && !type.IsObjectType()) {
627 other_cls = cls.SuperClass();
628 ASSERT(!other_cls.IsNull());
629 other_cls.AddDirectSubclass(cls);
630 }
631
632 // Add this class as an implementor to the implemented interface's type
633 // classes.
634 auto& interfaces = Array::Handle(zone, cls.interfaces());
635 const intptr_t mixin_index =
636 cls.is_transformed_mixin_application() ? interfaces.Length() - 1 : -1;
637 for (intptr_t i = 0; i < interfaces.Length(); ++i) {
638 type ^= interfaces.At(i);
639 other_cls = type.type_class();
640 MarkImplemented(zone, other_cls);
641 other_cls.AddDirectImplementor(cls, /* is_mixin = */ i == mixin_index);
642 }
643
644 // Propagate known concrete implementors to interfaces.
645 if (!cls.is_abstract()) {
646 GrowableArray<const Class*> worklist;
647 worklist.Add(&cls);
648 while (!worklist.is_empty()) {
649 const Class& implemented = *worklist.RemoveLast();
650 if (!implemented.NoteImplementor(cls)) continue;
651 type = implemented.super_type();
652 if (!type.IsNull()) {
653 worklist.Add(&Class::Handle(zone, implemented.SuperClass()));
654 }
655 interfaces = implemented.interfaces();
656 for (intptr_t i = 0; i < interfaces.Length(); i++) {
657 type ^= interfaces.At(i);
658 worklist.Add(&Class::Handle(zone, type.type_class()));
659 }
660 }
661 }
662}
static void MarkImplemented(Zone *zone, const Class &iface)

◆ RehashTypes()

void dart::ClassFinalizer::RehashTypes ( )
static

Definition at line 1141 of file class_finalizer.cc.

1141 {
1142 auto T = Thread::Current();
1143 auto Z = T->zone();
1144 auto IG = T->isolate_group();
1145
1146 // Clear all cached hash values.
1147 {
1148 HeapIterationScope his(T);
1149 ClearTypeHashVisitor visitor(Z);
1150 IG->heap()->VisitObjects(&visitor);
1151 }
1152
1153 // Rehash the canonical Types table.
1154 ObjectStore* object_store = IG->object_store();
1155 Array& types = Array::Handle(Z);
1156 Type& type = Type::Handle(Z);
1157 {
1158 CanonicalTypeSet types_table(Z, object_store->canonical_types());
1159 types = HashTables::ToArray(types_table, false);
1160 types_table.Release();
1161 }
1162
1163 intptr_t dict_size = Utils::RoundUpToPowerOfTwo(types.Length() * 4 / 3);
1164 CanonicalTypeSet types_table(
1165 Z, HashTables::New<CanonicalTypeSet>(dict_size, Heap::kOld));
1166 for (intptr_t i = 0; i < types.Length(); i++) {
1167 type ^= types.At(i);
1168 bool present = types_table.Insert(type);
1169 ASSERT(!present);
1170 }
1171 object_store->set_canonical_types(types_table.Release());
1172
1173 // Rehash the canonical FunctionTypes table.
1174 Array& function_types = Array::Handle(Z);
1175 FunctionType& function_type = FunctionType::Handle(Z);
1176 {
1177 CanonicalFunctionTypeSet function_types_table(
1178 Z, object_store->canonical_function_types());
1179 function_types = HashTables::ToArray(function_types_table, false);
1180 function_types_table.Release();
1181 }
1182
1183 dict_size = Utils::RoundUpToPowerOfTwo(function_types.Length() * 4 / 3);
1184 CanonicalFunctionTypeSet function_types_table(
1185 Z, HashTables::New<CanonicalFunctionTypeSet>(dict_size, Heap::kOld));
1186 for (intptr_t i = 0; i < function_types.Length(); i++) {
1187 function_type ^= function_types.At(i);
1188 bool present = function_types_table.Insert(function_type);
1189 ASSERT(!present);
1190 }
1191 object_store->set_canonical_function_types(function_types_table.Release());
1192
1193 // Rehash the canonical RecordTypes table.
1194 Array& record_types = Array::Handle(Z);
1195 RecordType& record_type = RecordType::Handle(Z);
1196 {
1197 CanonicalRecordTypeSet record_types_table(
1198 Z, object_store->canonical_record_types());
1199 record_types = HashTables::ToArray(record_types_table, false);
1200 record_types_table.Release();
1201 }
1202
1203 dict_size = Utils::RoundUpToPowerOfTwo(record_types.Length() * 4 / 3);
1204 CanonicalRecordTypeSet record_types_table(
1205 Z, HashTables::New<CanonicalRecordTypeSet>(dict_size, Heap::kOld));
1206 for (intptr_t i = 0; i < record_types.Length(); i++) {
1207 record_type ^= record_types.At(i);
1208 bool present = record_types_table.Insert(record_type);
1209 ASSERT(!present);
1210 }
1211 object_store->set_canonical_record_types(record_types_table.Release());
1212
1213 // Rehash the canonical TypeParameters table.
1214 Array& typeparams = Array::Handle(Z);
1215 TypeParameter& typeparam = TypeParameter::Handle(Z);
1216 {
1217 CanonicalTypeParameterSet typeparams_table(
1218 Z, object_store->canonical_type_parameters());
1219 typeparams = HashTables::ToArray(typeparams_table, false);
1220 typeparams_table.Release();
1221 }
1222
1223 dict_size = Utils::RoundUpToPowerOfTwo(typeparams.Length() * 4 / 3);
1224 CanonicalTypeParameterSet typeparams_table(
1225 Z, HashTables::New<CanonicalTypeParameterSet>(dict_size, Heap::kOld));
1226 for (intptr_t i = 0; i < typeparams.Length(); i++) {
1227 typeparam ^= typeparams.At(i);
1228 bool present = typeparams_table.Insert(typeparam);
1229 ASSERT(!present);
1230 }
1231 object_store->set_canonical_type_parameters(typeparams_table.Release());
1232
1233 // Rehash the canonical TypeArguments table.
1234 Array& typeargs = Array::Handle(Z);
1235 TypeArguments& typearg = TypeArguments::Handle(Z);
1236 {
1237 CanonicalTypeArgumentsSet typeargs_table(
1238 Z, object_store->canonical_type_arguments());
1239 typeargs = HashTables::ToArray(typeargs_table, false);
1240 typeargs_table.Release();
1241 }
1242
1243 // The canonical constant tables use canonical hashcodes which can change
1244 // due to cid-renumbering.
1245 IG->RehashConstants(nullptr);
1246
1247 dict_size = Utils::RoundUpToPowerOfTwo(typeargs.Length() * 4 / 3);
1248 CanonicalTypeArgumentsSet typeargs_table(
1249 Z, HashTables::New<CanonicalTypeArgumentsSet>(dict_size, Heap::kOld));
1250 for (intptr_t i = 0; i < typeargs.Length(); i++) {
1251 typearg ^= typeargs.At(i);
1252 bool present = typeargs_table.Insert(typearg);
1253 ASSERT(!present);
1254 }
1255 object_store->set_canonical_type_arguments(typeargs_table.Release());
1256}
#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:120
UnorderedHashSet< CanonicalFunctionTypeTraits > CanonicalFunctionTypeSet
UnorderedHashSet< CanonicalTypeArgumentsTraits > CanonicalTypeArgumentsSet
UnorderedHashSet< CanonicalTypeParameterTraits > CanonicalTypeParameterSet
UnorderedHashSet< CanonicalTypeTraits > CanonicalTypeSet
UnorderedHashSet< CanonicalRecordTypeTraits > CanonicalRecordTypeSet
#define T

◆ RemapClassIds()

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

Definition at line 1050 of file class_finalizer.cc.

1050 {
1051 Thread* T = Thread::Current();
1052 IsolateGroup* IG = T->isolate_group();
1053
1054 // Code, ICData, allocation stubs have now-invalid cids.
1055 ClearAllCode();
1056
1057 {
1058 // The [HeapIterationScope] also safepoints all threads.
1059 HeapIterationScope his(T);
1060
1061 // Update the class table. Do it before rewriting cids in headers, as
1062 // the heap walkers load an object's size *after* calling the visitor.
1063 IG->class_table()->Remap(old_to_new_cid);
1064 IG->set_remapping_cids(true);
1065
1066 // Rewrite cids in headers and cids in Classes, Fields, Types and
1067 // TypeParameters.
1068 {
1069 CidRewriteVisitor visitor(old_to_new_cid);
1070 IG->heap()->VisitObjects(&visitor);
1071 }
1072
1073 IG->set_remapping_cids(false);
1074#if defined(DEBUG)
1075 IG->class_table()->Validate();
1076#endif
1077 }
1078
1079#if defined(DEBUG)
1080 IG->heap()->Verify("RemapClassIds");
1081#endif
1082}
static void ClearAllCode(bool including_nonchanging_cids=false)

◆ SortClasses()

void dart::ClassFinalizer::SortClasses ( )
static

Definition at line 918 of file class_finalizer.cc.

918 {
919 auto T = Thread::Current();
920 StackZone stack_zone(T);
921 auto Z = T->zone();
922 auto IG = T->isolate_group();
923
924 // Prevent background compiler from adding deferred classes or canonicalizing
925 // new types while classes are being sorted and type hashes are modified.
926 NoBackgroundCompilerScope no_bg_compiler(T);
927 SafepointWriteRwLocker ml(T, T->isolate_group()->program_lock());
928
929 ClassTable* table = IG->class_table();
930 intptr_t num_cids = table->NumCids();
931
932 std::unique_ptr<intptr_t[]> old_to_new_cid(new intptr_t[num_cids]);
933
934 for (intptr_t cid = 0; cid < kNumPredefinedCids; cid++) {
935 old_to_new_cid[cid] = cid; // The predefined classes cannot change cids.
936 }
937 for (intptr_t cid = kNumPredefinedCids; cid < num_cids; cid++) {
938 old_to_new_cid[cid] = -1;
939 }
940
941 intptr_t next_new_cid = kNumPredefinedCids;
942 GrowableArray<intptr_t> dfs_stack;
943 Class& cls = Class::Handle(Z);
944 GrowableObjectArray& subclasses = GrowableObjectArray::Handle(Z);
945
946 // Object doesn't use its subclasses list.
947 for (intptr_t cid = kNumPredefinedCids; cid < num_cids; cid++) {
948 if (!table->HasValidClassAt(cid)) {
949 continue;
950 }
951 cls = table->At(cid);
952 if (!cls.is_declaration_loaded()) {
953 continue;
954 }
955 if (cls.SuperClass() == IG->object_store()->object_class()) {
956 dfs_stack.Add(cid);
957 }
958 }
959
960 while (dfs_stack.length() > 0) {
961 intptr_t cid = dfs_stack.RemoveLast();
962 ASSERT(table->HasValidClassAt(cid));
963 cls = table->At(cid);
964 ASSERT(!cls.IsNull());
965 if (old_to_new_cid[cid] == -1) {
966 old_to_new_cid[cid] = next_new_cid++;
967 if (FLAG_trace_class_finalization) {
968 THR_Print("%" Pd ": %s, was %" Pd "\n", old_to_new_cid[cid],
969 cls.ToCString(), cid);
970 }
971 }
972 subclasses = cls.direct_subclasses();
973 if (!subclasses.IsNull()) {
974 for (intptr_t i = 0; i < subclasses.Length(); i++) {
975 cls ^= subclasses.At(i);
976 ASSERT(!cls.IsNull());
977 dfs_stack.Add(cls.id());
978 }
979 }
980 }
981
982 // Top-level classes, typedefs, patch classes, etc.
983 for (intptr_t cid = kNumPredefinedCids; cid < num_cids; cid++) {
984 if (old_to_new_cid[cid] == -1) {
985 old_to_new_cid[cid] = next_new_cid++;
986 if (FLAG_trace_class_finalization && table->HasValidClassAt(cid)) {
987 cls = table->At(cid);
988 THR_Print("%" Pd ": %s, was %" Pd "\n", old_to_new_cid[cid],
989 cls.ToCString(), cid);
990 }
991 }
992 }
993 ASSERT(next_new_cid == num_cids);
994 RemapClassIds(old_to_new_cid.get());
995 // Types use cid's as part of their hashes.
996 RehashTypes();
997 // Const objects use cid's as part of their hashes.
998 IG->RehashConstants(nullptr);
999}
SI F table(const skcms_Curve *curve, F v)
static void RemapClassIds(intptr_t *old_to_new_cid)
@ kNumPredefinedCids
Definition class_id.h:257
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:10910
static intptr_t InstanceSize()
Definition object.h:10772
static bool ProcessPendingClasses()
static intptr_t InstanceSize()
Definition object.h:10114
static intptr_t InstanceSize()
Definition object.h:12986
static intptr_t InstanceSize()
Definition object.h:13055
bool Verify(const char *msg, MarkExpectation mark_expectation=kForbidMarked)
Definition heap.cc:760
static intptr_t InstanceSize()
Definition object.h:11020
static intptr_t InstanceSize()
Definition object.h:8308
Heap * heap() const
Definition isolate.h:295
static intptr_t InstanceSize()
Definition object.h:12085
static intptr_t InstanceSize()
Definition object.h:10069
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:592
static intptr_t InstanceSize()
Definition object.h:10543
static intptr_t InstanceSize()
Definition object.h:12188
static intptr_t InstanceSize()
Definition object.h:9983
static intptr_t InstanceSize()
Definition object.h:10683
static intptr_t InstanceSize()
Definition object.h:12906
static intptr_t InstanceSize()
Definition object.h:12932

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