mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
[vm] Replace cycle_free and type_finalized bits with class loading state
This change renames Class::is_cycle_free to Class::is_declaration_loaded and under the hood replaces cycle_free and type_finalized bits with class loading state enum. Also, added new assertions to check is_declaration_loaded(). Change-Id: Ib43e12731d0dc782e273be8e55912494e102cd79 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/104920 Reviewed-by: Régis Crelier <regis@google.com> Commit-Queue: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
parent
cf4a9f4f75
commit
9dcb026b26
|
@ -191,15 +191,15 @@ bool ClassFinalizer::ProcessPendingClasses() {
|
|||
class_array = object_store->pending_classes();
|
||||
ASSERT(!class_array.IsNull());
|
||||
Class& cls = Class::Handle();
|
||||
// Mark all classes as cycle-free (should be checked by front-end).
|
||||
// TODO(alexmarkov): Cleanup is_cycle_free bit on classes.
|
||||
|
||||
#if defined(DEBUG)
|
||||
for (intptr_t i = 0; i < class_array.Length(); i++) {
|
||||
cls ^= class_array.At(i);
|
||||
if (!cls.is_cycle_free()) {
|
||||
cls.set_is_cycle_free();
|
||||
}
|
||||
ASSERT(cls.is_declaration_loaded());
|
||||
}
|
||||
// Finalize all classes.
|
||||
#endif
|
||||
|
||||
// Finalize types in all classes.
|
||||
for (intptr_t i = 0; i < class_array.Length(); i++) {
|
||||
cls ^= class_array.At(i);
|
||||
FinalizeTypesInClass(cls);
|
||||
|
@ -1005,6 +1005,7 @@ static void MarkImplemented(Zone* zone, const Class& iface) {
|
|||
void ClassFinalizer::FinalizeTypesInClass(const Class& cls) {
|
||||
Thread* thread = Thread::Current();
|
||||
HANDLESCOPE(thread);
|
||||
ASSERT(cls.is_declaration_loaded());
|
||||
if (cls.is_type_finalized()) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ static RawClass* CreateTestClass(const char* name) {
|
|||
const Class& cls = Class::Handle(Class::New(
|
||||
Library::Handle(), class_name, script, TokenPosition::kNoSource));
|
||||
cls.set_interfaces(Object::empty_array());
|
||||
cls.set_is_declaration_loaded();
|
||||
cls.SetFunctions(Object::empty_array());
|
||||
cls.SetFields(Object::empty_array());
|
||||
return cls.raw();
|
||||
|
|
|
@ -1066,8 +1066,8 @@ RawLibrary* KernelLoader::LoadLibrary(intptr_t index) {
|
|||
Class& toplevel_class =
|
||||
Class::Handle(Z, Class::New(library, Symbols::TopLevel(), script,
|
||||
TokenPosition::kNoSource, register_class));
|
||||
toplevel_class.set_is_declaration_loaded();
|
||||
toplevel_class.set_is_type_finalized();
|
||||
toplevel_class.set_is_cycle_free();
|
||||
library.set_toplevel_class(toplevel_class);
|
||||
|
||||
library_helper.ReadUntilExcluding(LibraryHelper::kDependencies);
|
||||
|
@ -1386,6 +1386,8 @@ void KernelLoader::LoadPreliminaryClass(ClassHelper* class_helper,
|
|||
if (class_helper->is_transformed_mixin_application()) {
|
||||
klass->set_is_transformed_mixin_application();
|
||||
}
|
||||
|
||||
klass->set_is_declaration_loaded();
|
||||
}
|
||||
|
||||
void KernelLoader::LoadClass(const Library& library,
|
||||
|
@ -1438,10 +1440,9 @@ void KernelLoader::LoadClass(const Library& library,
|
|||
helper_.ReadListLength(); // read type_parameters list length.
|
||||
|
||||
ActiveClassScope active_class_scope(&active_class_, out_class);
|
||||
if (!out_class->is_cycle_free()) {
|
||||
if (!out_class->is_declaration_loaded()) {
|
||||
LoadPreliminaryClass(&class_helper, type_parameter_counts);
|
||||
} else {
|
||||
// do not use type parameters with cycle_free
|
||||
ASSERT(type_parameter_counts == 0);
|
||||
class_helper.SetJustRead(ClassHelper::kTypeParameters);
|
||||
}
|
||||
|
|
|
@ -533,8 +533,8 @@ void Object::Init(Isolate* isolate) {
|
|||
cls.set_id(Class::kClassId);
|
||||
cls.set_state_bits(0);
|
||||
cls.set_is_finalized();
|
||||
cls.set_is_declaration_loaded();
|
||||
cls.set_is_type_finalized();
|
||||
cls.set_is_cycle_free();
|
||||
cls.set_type_arguments_field_offset_in_words(Class::kNoTypeArguments);
|
||||
cls.set_num_type_arguments(0);
|
||||
cls.set_num_own_type_arguments(0);
|
||||
|
@ -555,16 +555,16 @@ void Object::Init(Isolate* isolate) {
|
|||
cls.set_num_type_arguments(0);
|
||||
cls.set_num_own_type_arguments(0);
|
||||
cls.set_is_finalized();
|
||||
cls.set_is_declaration_loaded();
|
||||
cls.set_is_type_finalized();
|
||||
cls.set_is_cycle_free();
|
||||
|
||||
// Allocate and initialize the forwarding corpse class.
|
||||
cls = Class::New<ForwardingCorpse::FakeInstance>(kForwardingCorpse);
|
||||
cls.set_num_type_arguments(0);
|
||||
cls.set_num_own_type_arguments(0);
|
||||
cls.set_is_finalized();
|
||||
cls.set_is_declaration_loaded();
|
||||
cls.set_is_type_finalized();
|
||||
cls.set_is_cycle_free();
|
||||
|
||||
// Allocate and initialize the sentinel values of Null class.
|
||||
{
|
||||
|
@ -832,22 +832,22 @@ void Object::Init(Isolate* isolate) {
|
|||
cls.set_num_type_arguments(0);
|
||||
cls.set_num_own_type_arguments(0);
|
||||
cls.set_is_finalized();
|
||||
cls.set_is_declaration_loaded();
|
||||
cls.set_is_type_finalized();
|
||||
cls.set_is_cycle_free();
|
||||
dynamic_class_ = cls.raw();
|
||||
|
||||
cls = Class::New<Instance>(kVoidCid);
|
||||
cls.set_num_type_arguments(0);
|
||||
cls.set_num_own_type_arguments(0);
|
||||
cls.set_is_finalized();
|
||||
cls.set_is_declaration_loaded();
|
||||
cls.set_is_type_finalized();
|
||||
cls.set_is_cycle_free();
|
||||
void_class_ = cls.raw();
|
||||
|
||||
cls = Class::New<Type>();
|
||||
cls.set_is_finalized();
|
||||
cls.set_is_declaration_loaded();
|
||||
cls.set_is_type_finalized();
|
||||
cls.set_is_cycle_free();
|
||||
|
||||
cls = dynamic_class_;
|
||||
*dynamic_type_ = Type::NewNonParameterizedType(cls);
|
||||
|
@ -1604,7 +1604,6 @@ RawError* Object::Init(Isolate* isolate,
|
|||
// Class that represents the Dart class _Closure and C++ class Closure.
|
||||
cls = Class::New<Closure>();
|
||||
object_store->set_closure_class(cls);
|
||||
cls.ResetFinalization(); // To calculate field offsets from Dart source.
|
||||
RegisterPrivateClass(cls, Symbols::_Closure(), core_lib);
|
||||
pending_classes.Add(cls);
|
||||
|
||||
|
@ -2309,8 +2308,10 @@ RawClass* Class::New() {
|
|||
(FakeObject::kClassId == kTypeArgumentsCid)) {
|
||||
// VM internal classes are done. There is no finalization needed or
|
||||
// possible in this case.
|
||||
result.set_is_declaration_loaded();
|
||||
result.set_is_type_finalized();
|
||||
result.set_is_finalized();
|
||||
} else {
|
||||
} else if (FakeObject::kClassId != kClosureCid) {
|
||||
// VM backed classes are almost ready: run checks and resolve class
|
||||
// references, but do not recompute size.
|
||||
result.set_is_prefinalized();
|
||||
|
@ -3739,9 +3740,9 @@ RawClass* Class::NewNativeWrapper(const Library& library,
|
|||
cls.set_next_field_offset(instance_size);
|
||||
cls.set_num_native_fields(field_count);
|
||||
cls.set_is_finalized();
|
||||
cls.set_is_declaration_loaded();
|
||||
cls.set_is_type_finalized();
|
||||
cls.set_is_synthesized_class();
|
||||
cls.set_is_cycle_free();
|
||||
cls.set_kernel_offset(-1);
|
||||
library.AddClass(cls);
|
||||
return cls.raw();
|
||||
|
@ -4069,8 +4070,17 @@ void Class::set_is_abstract() const {
|
|||
set_state_bits(AbstractBit::update(true, raw_ptr()->state_bits_));
|
||||
}
|
||||
|
||||
void Class::set_is_declaration_loaded() const {
|
||||
ASSERT(!is_declaration_loaded());
|
||||
set_state_bits(ClassLoadingBits::update(RawClass::kDeclarationLoaded,
|
||||
raw_ptr()->state_bits_));
|
||||
}
|
||||
|
||||
void Class::set_is_type_finalized() const {
|
||||
set_state_bits(TypeFinalizedBit::update(true, raw_ptr()->state_bits_));
|
||||
ASSERT(is_declaration_loaded());
|
||||
ASSERT(!is_type_finalized());
|
||||
set_state_bits(ClassLoadingBits::update(RawClass::kTypeFinalized,
|
||||
raw_ptr()->state_bits_));
|
||||
}
|
||||
|
||||
void Class::set_is_patch() const {
|
||||
|
@ -4098,11 +4108,6 @@ void Class::set_is_fields_marked_nullable() const {
|
|||
set_state_bits(FieldsMarkedNullableBit::update(true, raw_ptr()->state_bits_));
|
||||
}
|
||||
|
||||
void Class::set_is_cycle_free() const {
|
||||
ASSERT(!is_cycle_free());
|
||||
set_state_bits(CycleFreeBit::update(true, raw_ptr()->state_bits_));
|
||||
}
|
||||
|
||||
void Class::set_is_allocated(bool value) const {
|
||||
set_state_bits(IsAllocatedBit::update(value, raw_ptr()->state_bits_));
|
||||
}
|
||||
|
@ -4117,13 +4122,6 @@ void Class::set_is_finalized() const {
|
|||
ClassFinalizedBits::update(RawClass::kFinalized, raw_ptr()->state_bits_));
|
||||
}
|
||||
|
||||
void Class::ResetFinalization() const {
|
||||
ASSERT(IsTopLevel() || IsClosureClass());
|
||||
set_state_bits(
|
||||
ClassFinalizedBits::update(RawClass::kAllocated, raw_ptr()->state_bits_));
|
||||
set_state_bits(TypeFinalizedBit::update(false, raw_ptr()->state_bits_));
|
||||
}
|
||||
|
||||
void Class::set_is_prefinalized() const {
|
||||
ASSERT(!is_finalized());
|
||||
set_state_bits(ClassFinalizedBits::update(RawClass::kPreFinalized,
|
||||
|
|
|
@ -950,7 +950,10 @@ class Class : public Object {
|
|||
}
|
||||
|
||||
// The super type of this class, Object type if not explicitly specified.
|
||||
RawAbstractType* super_type() const { return raw_ptr()->super_type_; }
|
||||
RawAbstractType* super_type() const {
|
||||
ASSERT(is_declaration_loaded());
|
||||
return raw_ptr()->super_type_;
|
||||
}
|
||||
void set_super_type(const AbstractType& value) const;
|
||||
static intptr_t super_type_offset() {
|
||||
return OFFSET_OF(RawClass, super_type_);
|
||||
|
@ -1117,8 +1120,17 @@ class Class : public Object {
|
|||
}
|
||||
void set_is_abstract() const;
|
||||
|
||||
RawClass::ClassLoadingState class_loading_state() const {
|
||||
return ClassLoadingBits::decode(raw_ptr()->state_bits_);
|
||||
}
|
||||
|
||||
bool is_declaration_loaded() const {
|
||||
return class_loading_state() >= RawClass::kDeclarationLoaded;
|
||||
}
|
||||
void set_is_declaration_loaded() const;
|
||||
|
||||
bool is_type_finalized() const {
|
||||
return TypeFinalizedBit::decode(raw_ptr()->state_bits_);
|
||||
return class_loading_state() >= RawClass::kTypeFinalized;
|
||||
}
|
||||
void set_is_type_finalized() const;
|
||||
|
||||
|
@ -1146,8 +1158,6 @@ class Class : public Object {
|
|||
|
||||
void set_is_prefinalized() const;
|
||||
|
||||
void ResetFinalization() const;
|
||||
|
||||
bool is_const() const { return ConstBit::decode(raw_ptr()->state_bits_); }
|
||||
void set_is_const() const;
|
||||
|
||||
|
@ -1167,11 +1177,6 @@ class Class : public Object {
|
|||
}
|
||||
void set_is_fields_marked_nullable() const;
|
||||
|
||||
bool is_cycle_free() const {
|
||||
return CycleFreeBit::decode(raw_ptr()->state_bits_);
|
||||
}
|
||||
void set_is_cycle_free() const;
|
||||
|
||||
bool is_allocated() const {
|
||||
return IsAllocatedBit::decode(raw_ptr()->state_bits_);
|
||||
}
|
||||
|
@ -1334,16 +1339,16 @@ class Class : public Object {
|
|||
enum StateBits {
|
||||
kConstBit = 0,
|
||||
kImplementedBit = 1,
|
||||
kTypeFinalizedBit = 2,
|
||||
kClassFinalizedPos = 3,
|
||||
kClassFinalizedPos = 2,
|
||||
kClassFinalizedSize = 2,
|
||||
kAbstractBit = kClassFinalizedPos + kClassFinalizedSize, // = 5
|
||||
kPatchBit = 6,
|
||||
kClassLoadingPos = kClassFinalizedPos + kClassFinalizedSize, // = 4
|
||||
kClassLoadingSize = 2,
|
||||
kAbstractBit = kClassLoadingPos + kClassLoadingSize, // = 6
|
||||
kPatchBit,
|
||||
kSynthesizedClassBit,
|
||||
kMixinAppAliasBit,
|
||||
kMixinTypeAppliedBit,
|
||||
kFieldsMarkedNullableBit,
|
||||
kCycleFreeBit,
|
||||
kEnumBit,
|
||||
kTransformedMixinApplicationBit,
|
||||
kIsAllocatedBit,
|
||||
|
@ -1351,19 +1356,20 @@ class Class : public Object {
|
|||
};
|
||||
class ConstBit : public BitField<uint16_t, bool, kConstBit, 1> {};
|
||||
class ImplementedBit : public BitField<uint16_t, bool, kImplementedBit, 1> {};
|
||||
class TypeFinalizedBit
|
||||
: public BitField<uint16_t, bool, kTypeFinalizedBit, 1> {};
|
||||
class ClassFinalizedBits : public BitField<uint16_t,
|
||||
RawClass::ClassFinalizedState,
|
||||
kClassFinalizedPos,
|
||||
kClassFinalizedSize> {};
|
||||
class ClassLoadingBits : public BitField<uint16_t,
|
||||
RawClass::ClassLoadingState,
|
||||
kClassLoadingPos,
|
||||
kClassLoadingSize> {};
|
||||
class AbstractBit : public BitField<uint16_t, bool, kAbstractBit, 1> {};
|
||||
class PatchBit : public BitField<uint16_t, bool, kPatchBit, 1> {};
|
||||
class SynthesizedClassBit
|
||||
: public BitField<uint16_t, bool, kSynthesizedClassBit, 1> {};
|
||||
class FieldsMarkedNullableBit
|
||||
: public BitField<uint16_t, bool, kFieldsMarkedNullableBit, 1> {};
|
||||
class CycleFreeBit : public BitField<uint16_t, bool, kCycleFreeBit, 1> {};
|
||||
class EnumBit : public BitField<uint16_t, bool, kEnumBit, 1> {};
|
||||
class TransformedMixinApplicationBit
|
||||
: public BitField<uint16_t, bool, kTransformedMixinApplicationBit, 1> {};
|
||||
|
|
|
@ -31,6 +31,7 @@ static RawClass* CreateDummyClass(const String& class_name,
|
|||
const Class& cls = Class::Handle(Class::New(
|
||||
Library::Handle(), class_name, script, TokenPosition::kNoSource));
|
||||
cls.set_is_synthesized_class(); // Dummy class for testing.
|
||||
cls.set_is_declaration_loaded();
|
||||
return cls.raw();
|
||||
}
|
||||
|
||||
|
|
|
@ -735,6 +735,19 @@ class RawClass : public RawObject {
|
|||
kPreFinalized, // VM classes: size precomputed, but no checks done.
|
||||
kFinalized, // Class parsed, finalized and ready for use.
|
||||
};
|
||||
enum ClassLoadingState {
|
||||
// Class object is created, but it is not filled up.
|
||||
// At this state class can only be used as a forward reference during
|
||||
// class loading.
|
||||
kNameOnly = 0,
|
||||
// Class declaration information such as type parameters, supertype and
|
||||
// implemented interfaces are loaded. However, types in the class are
|
||||
// not finalized yet.
|
||||
kDeclarationLoaded,
|
||||
// Types in the class are finalized. At this point, members can be loaded
|
||||
// and class can be finalized.
|
||||
kTypeFinalized,
|
||||
};
|
||||
|
||||
private:
|
||||
RAW_HEAP_OBJECT_IMPLEMENTATION(Class);
|
||||
|
|
Loading…
Reference in a new issue