mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 01:13:04 +00:00
[VM/nnbd] Class Future may be used for type normalization before it is cached in the object store.
Class Future is resolved on the fly if not already cached. Note that postponing type normalization until type finalization does not help and results in the same error. Fixes issue https://github.com/dart-lang/sdk/issues/42643 Change-Id: Id4dbeba6a246dbc952cce4168a10137a49d3ce70 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/153901 Reviewed-by: Alexander Markov <alexmarkov@google.com> Commit-Queue: Régis Crelier <regis@google.com>
This commit is contained in:
parent
b75df6f268
commit
994c6ba6cd
|
@ -5802,6 +5802,8 @@ intptr_t Serializer::WriteVMSnapshot(const Array& symbols) {
|
|||
static const char* kObjectStoreFieldNames[] = {
|
||||
#define DECLARE_OBJECT_STORE_FIELD(Type, Name) #Name,
|
||||
OBJECT_STORE_FIELD_LIST(DECLARE_OBJECT_STORE_FIELD,
|
||||
DECLARE_OBJECT_STORE_FIELD,
|
||||
DECLARE_OBJECT_STORE_FIELD,
|
||||
DECLARE_OBJECT_STORE_FIELD)
|
||||
#undef DECLARE_OBJECT_STORE_FIELD
|
||||
};
|
||||
|
|
|
@ -148,16 +148,9 @@ class CheckFunctionTypesVisitor : public ObjectVisitor {
|
|||
static InstancePtr GetListInstance(Zone* zone, const Object& obj) {
|
||||
if (obj.IsInstance()) {
|
||||
ObjectStore* object_store = Isolate::Current()->object_store();
|
||||
Type& list_rare_type =
|
||||
const Type& list_rare_type =
|
||||
Type::Handle(zone, object_store->non_nullable_list_rare_type());
|
||||
if (list_rare_type.IsNull()) {
|
||||
const Library& core_lib = Library::Handle(zone, Library::CoreLibrary());
|
||||
const Class& list_class =
|
||||
Class::Handle(zone, core_lib.LookupClass(Symbols::List()));
|
||||
ASSERT(!list_class.IsNull());
|
||||
list_rare_type ^= list_class.RareType();
|
||||
object_store->set_non_nullable_list_rare_type(list_rare_type);
|
||||
}
|
||||
ASSERT(!list_rare_type.IsNull());
|
||||
const Instance& instance = Instance::Cast(obj);
|
||||
const Class& obj_class = Class::Handle(zone, obj.clazz());
|
||||
if (Class::IsSubtypeOf(obj_class, Object::null_type_arguments(),
|
||||
|
@ -172,16 +165,9 @@ static InstancePtr GetListInstance(Zone* zone, const Object& obj) {
|
|||
static InstancePtr GetMapInstance(Zone* zone, const Object& obj) {
|
||||
if (obj.IsInstance()) {
|
||||
ObjectStore* object_store = Isolate::Current()->object_store();
|
||||
Type& map_rare_type =
|
||||
const Type& map_rare_type =
|
||||
Type::Handle(zone, object_store->non_nullable_map_rare_type());
|
||||
if (map_rare_type.IsNull()) {
|
||||
const Library& core_lib = Library::Handle(zone, Library::CoreLibrary());
|
||||
const Class& map_class =
|
||||
Class::Handle(zone, core_lib.LookupClass(Symbols::Map()));
|
||||
ASSERT(!map_class.IsNull());
|
||||
map_rare_type ^= map_class.RareType();
|
||||
object_store->set_non_nullable_map_rare_type(map_rare_type);
|
||||
}
|
||||
ASSERT(!map_rare_type.IsNull());
|
||||
const Instance& instance = Instance::Cast(obj);
|
||||
const Class& obj_class = Class::Handle(zone, obj.clazz());
|
||||
if (Class::IsSubtypeOf(obj_class, Object::null_type_arguments(),
|
||||
|
@ -2416,14 +2402,9 @@ DART_EXPORT bool Dart_IsFuture(Dart_Handle handle) {
|
|||
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(handle));
|
||||
if (obj.IsInstance()) {
|
||||
ObjectStore* object_store = T->isolate()->object_store();
|
||||
Type& future_rare_type =
|
||||
const Type& future_rare_type =
|
||||
Type::Handle(Z, object_store->non_nullable_future_rare_type());
|
||||
if (future_rare_type.IsNull()) {
|
||||
const Class& future_class = Class::Handle(object_store->future_class());
|
||||
ASSERT(!future_class.IsNull());
|
||||
future_rare_type ^= future_class.RareType();
|
||||
object_store->set_non_nullable_future_rare_type(future_rare_type);
|
||||
}
|
||||
ASSERT(!future_rare_type.IsNull());
|
||||
const Class& obj_class = Class::Handle(Z, obj.clazz());
|
||||
bool is_future = Class::IsSubtypeOf(
|
||||
obj_class, Object::null_type_arguments(), Nullability::kNonNullable,
|
||||
|
|
|
@ -18531,7 +18531,9 @@ AbstractTypePtr AbstractType::SetInstantiatedNullability(
|
|||
|
||||
AbstractTypePtr AbstractType::NormalizeFutureOrType(Heap::Space space) const {
|
||||
if (IsFutureOrType()) {
|
||||
const AbstractType& unwrapped_type = AbstractType::Handle(UnwrapFutureOr());
|
||||
Zone* zone = Thread::Current()->zone();
|
||||
const AbstractType& unwrapped_type =
|
||||
AbstractType::Handle(zone, UnwrapFutureOr());
|
||||
const classid_t cid = unwrapped_type.type_class_id();
|
||||
if (cid == kDynamicCid || cid == kVoidCid) {
|
||||
return unwrapped_type.raw();
|
||||
|
@ -18549,38 +18551,14 @@ AbstractTypePtr AbstractType::NormalizeFutureOrType(Heap::Space space) const {
|
|||
}
|
||||
if (cid == kNeverCid && unwrapped_type.IsNonNullable()) {
|
||||
ObjectStore* object_store = Isolate::Current()->object_store();
|
||||
if (object_store->non_nullable_future_never_type() == Type::null()) {
|
||||
const Class& cls = Class::Handle(object_store->future_class());
|
||||
ASSERT(!cls.IsNull());
|
||||
const TypeArguments& type_args =
|
||||
TypeArguments::Handle(TypeArguments::New(1));
|
||||
type_args.SetTypeAt(0, Type::Handle(object_store->never_type()));
|
||||
Type& type =
|
||||
Type::Handle(Type::New(cls, type_args, TokenPosition::kNoSource,
|
||||
Nullability::kNonNullable));
|
||||
type.SetIsFinalized();
|
||||
type ^= type.Canonicalize();
|
||||
object_store->set_non_nullable_future_never_type(type);
|
||||
}
|
||||
const Type& future_never_type =
|
||||
Type::Handle(object_store->non_nullable_future_never_type());
|
||||
Type::Handle(zone, object_store->non_nullable_future_never_type());
|
||||
ASSERT(!future_never_type.IsNull());
|
||||
return future_never_type.ToNullability(nullability(), space);
|
||||
}
|
||||
if (cid == kNullCid) {
|
||||
ObjectStore* object_store = Isolate::Current()->object_store();
|
||||
if (object_store->nullable_future_null_type() == Type::null()) {
|
||||
const Class& cls = Class::Handle(object_store->future_class());
|
||||
ASSERT(!cls.IsNull());
|
||||
const TypeArguments& type_args =
|
||||
TypeArguments::Handle(TypeArguments::New(1));
|
||||
Type& type = Type::Handle(object_store->null_type());
|
||||
type_args.SetTypeAt(0, type);
|
||||
type = Type::New(cls, type_args, TokenPosition::kNoSource,
|
||||
Nullability::kNullable);
|
||||
type.SetIsFinalized();
|
||||
type ^= type.Canonicalize();
|
||||
object_store->set_nullable_future_null_type(type);
|
||||
}
|
||||
ASSERT(object_store->nullable_future_null_type() != Type::null());
|
||||
return object_store->nullable_future_null_type();
|
||||
}
|
||||
if (IsNullable() && unwrapped_type.IsNullable()) {
|
||||
|
|
|
@ -103,7 +103,7 @@ ErrorPtr IsolateObjectStore::PreallocateObjects() {
|
|||
|
||||
ObjectStore::ObjectStore() {
|
||||
#define INIT_FIELD(Type, name) name##_ = Type::null();
|
||||
OBJECT_STORE_FIELD_LIST(INIT_FIELD, INIT_FIELD)
|
||||
OBJECT_STORE_FIELD_LIST(INIT_FIELD, INIT_FIELD, INIT_FIELD, INIT_FIELD)
|
||||
#undef INIT_FIELD
|
||||
|
||||
for (ObjectPtr* current = from(); current <= to(); current++) {
|
||||
|
@ -136,7 +136,8 @@ void ObjectStore::PrintToJSONObject(JSONObject* jsobj) {
|
|||
#define PRINT_OBJECT_STORE_FIELD(type, name) \
|
||||
value = name##_; \
|
||||
fields.AddProperty(#name "_", value);
|
||||
OBJECT_STORE_FIELD_LIST(PRINT_OBJECT_STORE_FIELD, PRINT_OBJECT_STORE_FIELD);
|
||||
OBJECT_STORE_FIELD_LIST(PRINT_OBJECT_STORE_FIELD, PRINT_OBJECT_STORE_FIELD,
|
||||
PRINT_OBJECT_STORE_FIELD, PRINT_OBJECT_STORE_FIELD);
|
||||
#undef PRINT_OBJECT_STORE_FIELD
|
||||
}
|
||||
}
|
||||
|
@ -333,4 +334,60 @@ void ObjectStore::InitKnownObjects() {
|
|||
#endif
|
||||
}
|
||||
|
||||
void ObjectStore::LazyInitCoreTypes() {
|
||||
if (non_nullable_list_rare_type_ == Type::null()) {
|
||||
ASSERT(non_nullable_map_rare_type_ == Type::null());
|
||||
Thread* thread = Thread::Current();
|
||||
Zone* zone = thread->zone();
|
||||
const Library& core_lib = Library::Handle(zone, Library::CoreLibrary());
|
||||
Class& cls = Class::Handle(zone, core_lib.LookupClass(Symbols::List()));
|
||||
ASSERT(!cls.IsNull());
|
||||
Type& type = Type::Handle(zone);
|
||||
type ^= cls.RareType();
|
||||
set_non_nullable_list_rare_type(type);
|
||||
cls = core_lib.LookupClass(Symbols::Map());
|
||||
ASSERT(!cls.IsNull());
|
||||
type ^= cls.RareType();
|
||||
set_non_nullable_map_rare_type(type);
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectStore::LazyInitFutureTypes() {
|
||||
if (non_nullable_future_rare_type_ == Type::null()) {
|
||||
ASSERT(non_nullable_future_never_type_ == Type::null() &&
|
||||
nullable_future_null_type_ == Type::null());
|
||||
Thread* thread = Thread::Current();
|
||||
Zone* zone = thread->zone();
|
||||
Class& cls = Class::Handle(zone, future_class());
|
||||
if (cls.IsNull()) {
|
||||
const Library& async_lib = Library::Handle(zone, async_library());
|
||||
ASSERT(!async_lib.IsNull());
|
||||
cls = async_lib.LookupClass(Symbols::Future());
|
||||
ASSERT(!cls.IsNull());
|
||||
}
|
||||
TypeArguments& type_args = TypeArguments::Handle(zone);
|
||||
Type& type = Type::Handle(zone);
|
||||
type = never_type();
|
||||
ASSERT(!type.IsNull());
|
||||
type_args = TypeArguments::New(1);
|
||||
type_args.SetTypeAt(0, type);
|
||||
type = Type::New(cls, type_args, TokenPosition::kNoSource,
|
||||
Nullability::kNonNullable);
|
||||
type.SetIsFinalized();
|
||||
type ^= type.Canonicalize();
|
||||
set_non_nullable_future_never_type(type);
|
||||
type = null_type();
|
||||
ASSERT(!type.IsNull());
|
||||
type_args = TypeArguments::New(1);
|
||||
type_args.SetTypeAt(0, type);
|
||||
type = Type::New(cls, type_args, TokenPosition::kNoSource,
|
||||
Nullability::kNullable);
|
||||
type.SetIsFinalized();
|
||||
type ^= type.Canonicalize();
|
||||
set_nullable_future_null_type(type);
|
||||
type ^= cls.RareType();
|
||||
set_non_nullable_future_rare_type(type);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dart
|
||||
|
|
|
@ -37,7 +37,9 @@ class ObjectPointerVisitor;
|
|||
//
|
||||
// R_ - needs getter only
|
||||
// RW - needs getter and setter
|
||||
#define OBJECT_STORE_FIELD_LIST(R_, RW) \
|
||||
// CW - needs lazy Core init getter and setter
|
||||
// FW - needs lazy Future init getter and setter
|
||||
#define OBJECT_STORE_FIELD_LIST(R_, RW, CW, FW) \
|
||||
RW(Class, object_class) \
|
||||
RW(Type, object_type) \
|
||||
RW(Type, legacy_object_type) \
|
||||
|
@ -80,9 +82,11 @@ class ObjectPointerVisitor;
|
|||
RW(Type, string_type) \
|
||||
RW(Type, legacy_string_type) \
|
||||
RW(Type, non_nullable_string_type) \
|
||||
RW(Type, non_nullable_list_rare_type) /* maybe be null, lazily built */ \
|
||||
RW(Type, non_nullable_map_rare_type) /* maybe be null, lazily built */ \
|
||||
RW(Type, non_nullable_future_rare_type) /* maybe be null, lazily built */ \
|
||||
CW(Type, non_nullable_list_rare_type) /* maybe be null, lazily built */ \
|
||||
CW(Type, non_nullable_map_rare_type) /* maybe be null, lazily built */ \
|
||||
FW(Type, non_nullable_future_rare_type) /* maybe be null, lazily built */ \
|
||||
FW(Type, non_nullable_future_never_type) /* maybe be null, lazily built */ \
|
||||
FW(Type, nullable_future_null_type) /* maybe be null, lazily built */ \
|
||||
RW(TypeArguments, type_argument_int) \
|
||||
RW(TypeArguments, type_argument_legacy_int) \
|
||||
RW(TypeArguments, type_argument_non_nullable_int) \
|
||||
|
@ -103,8 +107,6 @@ class ObjectPointerVisitor;
|
|||
RW(Field, pragma_name) \
|
||||
RW(Field, pragma_options) \
|
||||
RW(Class, future_class) \
|
||||
RW(Type, non_nullable_future_never_type) /* maybe be null, lazily built */ \
|
||||
RW(Type, nullable_future_null_type) /* maybe be null, lazily built */ \
|
||||
RW(Class, completer_class) \
|
||||
RW(Class, symbol_class) \
|
||||
RW(Class, one_byte_string_class) \
|
||||
|
@ -354,9 +356,29 @@ class ObjectStore {
|
|||
#define DECLARE_GETTER_AND_SETTER(Type, name) \
|
||||
DECLARE_GETTER(Type, name) \
|
||||
void set_##name(const Type& value) { name##_ = value.raw(); }
|
||||
OBJECT_STORE_FIELD_LIST(DECLARE_GETTER, DECLARE_GETTER_AND_SETTER)
|
||||
#define DECLARE_LAZY_INIT_GETTER(Type, name, init) \
|
||||
Type##Ptr name() { \
|
||||
if (name##_ == Type::null()) { \
|
||||
init(); \
|
||||
} \
|
||||
return name##_; \
|
||||
} \
|
||||
static intptr_t name##_offset() { return OFFSET_OF(ObjectStore, name##_); }
|
||||
#define DECLARE_LAZY_INIT_CORE_GETTER_AND_SETTER(Type, name) \
|
||||
DECLARE_LAZY_INIT_GETTER(Type, name, LazyInitCoreTypes) \
|
||||
void set_##name(const Type& value) { name##_ = value.raw(); }
|
||||
#define DECLARE_LAZY_INIT_FUTURE_GETTER_AND_SETTER(Type, name) \
|
||||
DECLARE_LAZY_INIT_GETTER(Type, name, LazyInitFutureTypes) \
|
||||
void set_##name(const Type& value) { name##_ = value.raw(); }
|
||||
OBJECT_STORE_FIELD_LIST(DECLARE_GETTER,
|
||||
DECLARE_GETTER_AND_SETTER,
|
||||
DECLARE_LAZY_INIT_CORE_GETTER_AND_SETTER,
|
||||
DECLARE_LAZY_INIT_FUTURE_GETTER_AND_SETTER)
|
||||
#undef DECLARE_GETTER
|
||||
#undef DECLARE_GETTER_AND_SETTER
|
||||
#undef DECLARE_LAZY_INIT_GETTER
|
||||
#undef DECLARE_LAZY_INIT_CORE_GETTER_AND_SETTER
|
||||
#undef DECLARE_LAZY_INIT_FUTURE_GETTER_AND_SETTER
|
||||
|
||||
LibraryPtr bootstrap_library(BootstrapLibraryId index) {
|
||||
switch (index) {
|
||||
|
@ -404,12 +426,17 @@ class ObjectStore {
|
|||
#endif
|
||||
|
||||
private:
|
||||
void LazyInitCoreTypes();
|
||||
void LazyInitFutureTypes();
|
||||
|
||||
// Finds a core library private method in Object.
|
||||
FunctionPtr PrivateObjectLookup(const String& name);
|
||||
|
||||
ObjectPtr* from() { return reinterpret_cast<ObjectPtr*>(&object_class_); }
|
||||
#define DECLARE_OBJECT_STORE_FIELD(type, name) type##Ptr name##_;
|
||||
OBJECT_STORE_FIELD_LIST(DECLARE_OBJECT_STORE_FIELD,
|
||||
DECLARE_OBJECT_STORE_FIELD,
|
||||
DECLARE_OBJECT_STORE_FIELD,
|
||||
DECLARE_OBJECT_STORE_FIELD)
|
||||
#undef DECLARE_OBJECT_STORE_FIELD
|
||||
ObjectPtr* to() {
|
||||
|
|
Loading…
Reference in a new issue