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.");
37 return classes.
Length() == 0;
40#if defined(DART_PRECOMPILED_RUNTIME)
54 const Class& subclass,
56 ASSERT(FLAG_use_cha_deopt);
57 if (added_subclass_to_cids.
is_empty()) {
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);
75 if (
type.IsObjectType()) {
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) {
87 finalized_super_classes->
Add(
cid);
100 if (!super_type.
IsNull()) {
115 : class_table_(class_table),
116 array_handles_(zone),
117 class_handles_(zone),
123 cids_->
Add(klass.
id());
130 *current_class = klass.
ptr();
133 const intptr_t
cid = current_class->id();
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());
149 *
type = current_class->super_type();
150 if (
type->IsNull())
break;
151 *current_class = class_table_->
At(
type->type_class_id());
168 for (intptr_t
i = 0;
i < interfaces.
Length(); ++
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()) {
189 ASSERT(isolate_group !=
nullptr);
191 ObjectStore* object_store = isolate_group->object_store();
193 if (!
error.IsNull()) {
201 if (setjmp(*jump.
Set()) == 0) {
203 class_array = object_store->pending_classes();
208 for (intptr_t
i = 0;
i < class_array.
Length();
i++) {
209 cls ^= class_array.
At(
i);
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)
226 object_store->set_pending_classes(class_array);
227 VerifyImplicitFieldOffsets();
238 if (FLAG_trace_class_finalization) {
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();
287 for (intptr_t
i = 0;
i < class_array.
Length();
i++) {
289 cls ^= class_array.
At(
i);
301 OS::PrintErr(
"Could not verify bootstrap classes : %s\n",
306 if (FLAG_trace_class_finalization) {
313void ClassFinalizer::FinalizeTypeParameters(
Zone* zone,
315 FinalizationKind finalization) {
316 if (!type_params.
IsNull()) {
319 type_args = type_params.bounds();
320 type_args = FinalizeTypeArguments(zone, type_args, finalization);
321 type_params.set_bounds(type_args);
323 type_args = type_params.defaults();
324 type_args = FinalizeTypeArguments(zone, type_args, finalization);
325 type_params.set_defaults(type_args);
327 type_params.OptimizeFlags();
331TypeArgumentsPtr ClassFinalizer::FinalizeTypeArguments(
333 const TypeArguments& type_args,
334 FinalizationKind finalization) {
335 if (type_args.IsNull()) {
338 ASSERT(type_args.ptr() != Object::empty_type_arguments().ptr());
340 for (intptr_t
i = 0, n = type_args.Length();
i < n; ++
i) {
341 type = type_args.TypeAt(
i);
347 return type_args.ptr();
352 if (
type.IsFinalized()) {
362 if (FLAG_trace_type_finalization) {
367 const auto& t = Type::Cast(
type);
369 ASSERT(type_args.IsNull() ||
370 type_args.Length() ==
371 Class::Handle(zone, t.type_class()).NumTypeParameters(thread));
372 FinalizeTypeArguments(zone, type_args,
kFinalize);
374 }
else if (
type.IsTypeParameter()) {
379 const Class& parameterized_class = Class::Cast(
389 const intptr_t index = type_parameter.
index() +
offset;
391 FATAL(
"Too many type parameters in %s",
398 .IsNullableObjectType()) {
406 }
else if (
type.IsFunctionType()) {
407 const auto& signature = FunctionType::Cast(
type);
408 FinalizeTypeParameters(
413 type = signature.result_type();
416 for (intptr_t
i = 0, n = signature.NumParameters();
i < n; ++
i) {
417 type = signature.ParameterTypeAt(
i);
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);
430 type.SetIsFinalized();
433 return type.Canonicalize(thread);
439#if !defined(DART_PRECOMPILED_RUNTIME)
441#if defined(TARGET_ARCH_X64)
445 if (
type.IsType() && !
type.IsDartFunctionType() &&
type.IsInstantiated() &&
446 !
type.IsFutureOrType()) {
460void ClassFinalizer::FinalizeMemberTypes(
const Class& cls) {
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);
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(
501 function = field.InitializerFunction();
512 array = cls.current_functions();
513 const intptr_t num_functions = array.Length();
514 for (intptr_t
i = 0;
i < num_functions;
i++) {
542 if (
type.IsNull() ||
type.IsObjectType()) {
545 cls =
type.type_class();
558#if defined(DART_PRECOMPILED_RUNTIME)
567 if (FLAG_trace_class_finalization) {
571 bool has_isolate_unsendable_pragma =
577 if (!super_class.
IsNull()) {
581 FinalizeTypeParameters(
587 if (!super_type.
IsNull()) {
590 has_isolate_unsendable_pragma |=
598 for (intptr_t
i = 0;
i < interface_types.Length();
i++) {
599 interface_type ^= interface_types.At(
i);
601 interface_class = interface_type.type_class();
602 ASSERT(!interface_class.IsNull());
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();
623#if !defined(DART_PRECOMPILED_RUNTIME)
629 if (!
type.IsNull() && !
type.IsObjectType()) {
631 ASSERT(!other_cls.IsNull());
632 other_cls.AddDirectSubclass(cls);
638 const intptr_t mixin_index =
640 for (intptr_t
i = 0;
i < interfaces.Length(); ++
i) {
641 type ^= interfaces.At(
i);
642 other_cls =
type.type_class();
644 other_cls.AddDirectImplementor(cls,
i == mixin_index);
655 if (!
type.IsNull()) {
659 for (intptr_t
i = 0;
i < interfaces.Length();
i++) {
660 type ^= interfaces.At(
i);
673 if (!
base.IsNull()) {
678 for (intptr_t
i = 0;
i < interfaces.Length(); ++
i) {
679 type ^= interfaces.At(
i);
693 if (!
base.IsNull()) {
698 for (intptr_t
i = 0;
i < interfaces.Length(); ++
i) {
699 type ^= interfaces.At(
i);
712#if defined(DART_PRECOMPILED_RUNTIME)
718 if (FLAG_trace_class_finalization) {
722#if defined(SUPPORT_TIMELINE)
723 TimelineBeginEndScope tbes(thread, Timeline::GetCompilerStream(),
725 if (tbes.enabled()) {
726 tbes.SetNumArguments(1);
727 tbes.CopyArgument(0,
"class", cls.
ToCString());
750 if (FLAG_print_classes) {
751 PrintClassInformation(cls);
753 FinalizeMemberTypes(cls);
764#if !defined(DART_PRECOMPILED_RUNTIME)
774 if (FLAG_trace_class_finalization) {
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());
788 if (FLAG_use_cha_deopt && !cls.
IsTopLevel()) {
806 for (intptr_t j = 0; j < cids.
length(); ++j) {
807 interface_class = class_table->
At(cids[j]);
808 interface_class.DisableCHAImplementorUsers();
822 if (setjmp(*jump.
Set()) == 0) {
823#if !defined(DART_PRECOMPILED_RUNTIME)
834void ClassFinalizer::PrintClassInformation(
const Class& cls) {
847 if (super_type.IsNull()) {
851 THR_Print(
" Super: %s", super_name.ToCString());
854 if (interfaces_array.Length() > 0) {
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());
866 intptr_t
len = functions_array.Length();
867 for (intptr_t
i = 0;
i <
len;
i++) {
873 len = fields_array.Length();
874 for (intptr_t
i = 0;
i <
len;
i++) {
875 field ^= fields_array.At(
i);
897#if !defined(DART_PRECOMPILED_RUNTIME)
899void ClassFinalizer::VerifyImplicitFieldOffsets() {
902 auto isolate_group = thread->isolate_group();
904 if (isolate_group->obfuscate()) {
909 Zone* zone = thread->zone();
910 const ClassTable& class_table = *(isolate_group->class_table());
921 error = cls.EnsureIsFinalized(thread);
923 fields_array ^= cls.fields();
925 field ^= fields_array.At(0);
927 name ^= field.name();
932 cls = class_table.At(kPointerCid);
933 error = cls.EnsureIsFinalized(thread);
935 ASSERT(cls.NumTypeParameters() == 1);
936 type_param = cls.TypeParameterAt(0);
945 auto IG =
T->isolate_group();
953 intptr_t num_cids =
table->NumCids();
955 std::unique_ptr<intptr_t[]> old_to_new_cid(
new intptr_t[num_cids]);
958 old_to_new_cid[
cid] =
cid;
961 old_to_new_cid[
cid] = -1;
978 if (cls.
SuperClass() ==
IG->object_store()->object_class()) {
983 while (dfs_stack.
length() > 0) {
988 if (old_to_new_cid[
cid] == -1) {
989 old_to_new_cid[
cid] = next_new_cid++;
990 if (FLAG_trace_class_finalization) {
996 if (!subclasses.
IsNull()) {
997 for (intptr_t
i = 0;
i < subclasses.
Length();
i++) {
998 cls ^= subclasses.
At(
i);
1000 dfs_stack.
Add(cls.
id());
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)) {
1016 ASSERT(next_new_cid == num_cids);
1021 IG->RehashConstants(
nullptr);
1027 : old_to_new_cids_(old_to_new_cids) {}
1031 return old_to_new_cids_[
cid];
1035 if (obj->IsClass()) {
1037 const classid_t old_cid = cls->untag()->id_;
1042 cls->untag()->id_ =
Map(old_cid);
1043 cls->untag()->implementor_cid_ =
Map(cls->untag()->implementor_cid_);
1044 }
else if (obj->IsField()) {
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()) {
1051 param->untag()->flags())) {
1052 param->untag()->set_owner(
1055 }
else if (obj->IsType()) {
1057 type->untag()->set_type_class_id(
Map(
type->untag()->type_class_id()));
1060 intptr_t new_cid =
Map(old_cid);
1061 if (old_cid != new_cid) {
1064 obj->
untag()->SetClassIdUnsynchronized(new_cid);
1070 intptr_t* old_to_new_cids_;
1086 IG->class_table()->Remap(old_to_new_cid);
1087 IG->set_remapping_cids(
true);
1093 IG->heap()->VisitObjects(&visitor);
1096 IG->set_remapping_cids(
false);
1098 IG->class_table()->Validate();
1103 IG->heap()->Verify(
"RemapClassIds");
1149 if (obj->IsType() || obj->IsTypeParameter() || obj->IsFunctionType() ||
1150 obj->IsRecordType()) {
1153 }
else if (obj->IsTypeArguments()) {
1155 type_args_.SetHash(0);
1167 auto IG =
T->isolate_group();
1173 IG->heap()->VisitObjects(&visitor);
1188 Z, HashTables::New<CanonicalTypeSet>(dict_size,
Heap::kOld));
1189 for (intptr_t
i = 0;
i < types.
Length();
i++) {
1194 object_store->set_canonical_types(types_table.
Release());
1201 Z, object_store->canonical_function_types());
1203 function_types_table.
Release();
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);
1214 object_store->set_canonical_function_types(function_types_table.
Release());
1221 Z, object_store->canonical_record_types());
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);
1234 object_store->set_canonical_record_types(record_types_table.
Release());
1241 Z, object_store->canonical_type_parameters());
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);
1254 object_store->set_canonical_type_parameters(typeparams_table.
Release());
1261 Z, object_store->canonical_type_arguments());
1268 IG->RehashConstants(
nullptr);
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);
1278 object_store->set_canonical_type_arguments(typeargs_table.
Release());
1283 auto const isolate_group = thread->isolate_group();
1286 auto const zone = thread->zone();
1290 ClearCodeVisitor(
Zone* zone,
bool force)
1295 void VisitClass(
const Class& cls) {
1312 ClearCodeVisitor visitor(zone, including_nonchanging_cids);
#define ASSERT_EQUAL(expected, actual)
virtual bool HasTypeClass() const
void SetHash(intptr_t value) const
virtual ClassPtr type_class() const
static intptr_t InstanceSize()
ObjectPtr At(intptr_t index) const
static constexpr T decode(S value)
static intptr_t InstanceSize()
static intptr_t NumberOfFields()
static intptr_t data_offset()
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 void RehashTypes()
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
static bool IsTopLevelCid(intptr_t cid)
bool has_dynamically_extendable_subtypes() const
void set_is_implemented() const
intptr_t kernel_offset() const
LibraryPtr library() const
void set_is_isolate_unsendable_due_to_pragma(bool value) const
void set_super_type(const Type &value) const
void set_is_allocate_finalized() const
bool can_be_future() const
bool is_declaration_loaded() const
GrowableObjectArrayPtr direct_subclasses() const
TypePtr super_type() const
intptr_t NumTypeArguments() const
ArrayPtr interfaces() const
bool is_type_finalized() const
void SetUserVisibleNameInClassTable()
void DisableAllocationStub() const
bool HasInstanceFields() const
void set_is_future_subtype(bool value) const
intptr_t host_instance_size() const
void DisableCHAOptimizedCode(const Class &subclass)
bool is_dynamically_extendable() const
bool is_prefinalized() const
bool IsFutureClass() const
bool is_future_subtype() const
ClassPtr SuperClass(ClassTable *class_table=nullptr) const
void set_has_dynamically_extendable_subtypes(bool value) const
bool NoteImplementor(const Class &implementor) const
TypeParametersPtr type_parameters() const
void set_is_type_finalized() const
const char * UserVisibleNameCString() const
bool is_implemented() const
bool is_allocate_finalized() const
bool is_transformed_mixin_application() const
intptr_t NumTypeParameters(Thread *thread) const
bool is_isolate_unsendable_due_to_pragma() const
bool is_finalized() const
ArrayPtr current_functions() const
void EnsureDeclarationLoaded() const
void set_can_be_future(bool value) const
ClearTypeHashVisitor(Zone *zone)
void VisitObject(ObjectPtr obj) override
static intptr_t InstanceSize()
virtual const char * ToErrorCString() const
static intptr_t InstanceSize()
static intptr_t InstanceSize()
static GrowableObjectArrayPtr New(Heap::Space space=Heap::kNew)
ObjectPtr At(intptr_t index) const
bool Insert(const Object &key)
StorageTraits::ArrayHandle & Release()
static ArrayPtr ToArray(const Table &table, bool include_payload)
bool Verify(const char *msg, MarkExpectation mark_expectation=kForbidMarked)
static intptr_t InstanceSize()
static intptr_t InstanceSize()
InterfaceFinder(Zone *zone, ClassTable *class_table, GrowableArray< intptr_t > *cids)
void FindAllInterfaces(const Class &klass)
ObjectStore * object_store() const
SafepointRwLock * program_lock()
static IsolateGroup * Current()
ClassTable * class_table() const
StringPtr private_key() const
static intptr_t InstanceSize()
static intptr_t InstanceSize()
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
virtual const char * ToCString() const
static ObjectPtr RawCast(ObjectPtr obj)
static intptr_t InstanceSize()
static constexpr intptr_t kNativeTypeArgPos
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)
static DART_NORETURN void LongJump(const Error &error)
static constexpr bool AtLocation
static intptr_t InstanceSize()
static SmiPtr New(intptr_t value)
static intptr_t InstanceSize()
static StaticTypeExactnessState Uninitialized()
static StringPtr New(const char *cstr, Heap::Space space=Heap::kNew)
static bool EqualsIgnoringPrivateKey(const String &str1, const String &str2)
static Thread * Current()
DART_WARN_UNUSED_RESULT ErrorPtr StealStickyError()
IsolateGroup * isolate_group() const
ErrorPtr sticky_error() const
static intptr_t InstanceSize()
bool IsClassTypeParameter() const
void set_parameterized_class_id(classid_t value) const
void set_index(intptr_t value) const
ClassPtr parameterized_class() const
AbstractTypePtr bound() const
void set_base(intptr_t value) const
static constexpr uintptr_t RoundUpToPowerOfTwo(uintptr_t x)
static bool IsUint(intptr_t N, T value)
static intptr_t InstanceSize()
static intptr_t InstanceSize()
static void FinishLoading(const Class &klass)
#define THR_Print(format,...)
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
#define HANDLESCOPE(thread)
static void MarkImplemented(Zone *zone, const Class &iface)
static void CollectFinalizedSuperClasses(const Class &cls_, GrowableArray< intptr_t > *finalized_super_classes)
static void AddSuperType(const AbstractType &type, GrowableArray< intptr_t > *finalized_super_classes)
static bool IsPotentialExactGeneric(const AbstractType &type)
const char *const class_name
DEFINE_FLAG(bool, print_cluster_information, false, "Print information about clusters written to snapshot")
static void RemoveCHAOptimizedCode(const Class &subclass, const GrowableArray< intptr_t > &added_subclass_to_cids)
static void CollectImmediateSuperInterfaces(const Class &cls, GrowableArray< intptr_t > *cids)
#define TIMELINE_DURATION(thread, stream, name)