From c5eb666bcf78800a20f1bcdbf118eb643912a8bc Mon Sep 17 00:00:00 2001 From: Clement Skau Date: Thu, 3 Dec 2020 08:03:11 +0000 Subject: [PATCH] Revert "[vm] Track metadata by identity instead of name." This reverts commit bfd382820f949051388bba604467a6bfcdf3f389. Reason for revert: Breaks several lib_2/mirrors/ tests Original change's description: > [vm] Track metadata by identity instead of name. > > Remove the use of Fields, which have since the metadata mechanism was introduced come to require global registration. > > TEST=ci > Change-Id: Ic2e0c4408557514507fd732e0cb19b022b2539c7 > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/161631 > Commit-Queue: Ryan Macnak > Reviewed-by: Martin Kustermann TBR=kustermann@google.com,aam@google.com,rmacnak@google.com Change-Id: Icf75e91872d9c85ce9be29a9a178d72ca024c98b No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/174920 Reviewed-by: Clement Skau Commit-Queue: Clement Skau --- runtime/lib/mirrors.cc | 5 +- runtime/vm/canonical_tables.h | 32 --- runtime/vm/clustered_snapshot.cc | 9 +- runtime/vm/compiler/aot/precompiler.cc | 40 +++- runtime/vm/dart_api_impl.cc | 2 +- runtime/vm/isolate_reload.cc | 6 +- runtime/vm/kernel.cc | 14 +- runtime/vm/kernel.h | 3 +- runtime/vm/kernel_loader.cc | 24 +- runtime/vm/object.cc | 307 ++++++++++++++++++++----- runtime/vm/object.h | 43 +++- runtime/vm/object_service.cc | 6 +- runtime/vm/raw_object.h | 13 +- runtime/vm/raw_object_fields.cc | 4 +- 14 files changed, 365 insertions(+), 143 deletions(-) diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc index eddf299312a..a82995750c8 100644 --- a/runtime/lib/mirrors.cc +++ b/runtime/lib/mirrors.cc @@ -435,12 +435,11 @@ static InstancePtr CreateLibraryDependencyMirror(Thread* thread, const LibraryPrefix& prefix, const bool is_import, const bool is_deferred) { - const Library& importee = Library::Handle(ns.target()); + const Library& importee = Library::Handle(ns.library()); const Array& show_names = Array::Handle(ns.show_names()); const Array& hide_names = Array::Handle(ns.hide_names()); - const Library& owner = Library::Handle(ns.owner()); - Object& metadata = Object::Handle(owner.GetMetadata(ns)); + Object& metadata = Object::Handle(ns.GetMetadata()); if (metadata.IsError()) { Exceptions::PropagateError(Error::Cast(metadata)); UNREACHABLE(); diff --git a/runtime/vm/canonical_tables.h b/runtime/vm/canonical_tables.h index 3fd3f24f3e6..69b79eb399d 100644 --- a/runtime/vm/canonical_tables.h +++ b/runtime/vm/canonical_tables.h @@ -254,38 +254,6 @@ class CanonicalTypeArgumentsTraits { typedef UnorderedHashSet CanonicalTypeArgumentsSet; -class MetadataMapTraits { - public: - static const char* Name() { return "MetadataMapTraits"; } - static bool ReportStats() { return false; } - static bool IsMatch(const Object& key, const Object& candidate) { - return key.raw() == candidate.raw(); - } - static uword Hash(const Object& key) { -#if !defined(DART_PRECOMPILED_RUNTIME) - if (key.IsLibrary()) { - return String::Hash(Library::Cast(key).url()); - } else if (key.IsClass()) { - return String::Hash(Class::Cast(key).Name()); - } else if (key.IsPatchClass()) { - return Hash(Object::Handle(PatchClass::Cast(key).patched_class())); - } else if (key.IsFunction()) { - return CombineHashes(String::Hash(Function::Cast(key).name()), - Hash(Object::Handle(Function::Cast(key).Owner()))); - } else if (key.IsField()) { - return CombineHashes(String::Hash(Field::Cast(key).name()), - Hash(Object::Handle(Field::Cast(key).Owner()))); - } else if (key.IsTypeParameter()) { - return TypeParameter::Cast(key).Hash(); - } else if (key.IsNamespace()) { - return Hash(Library::Handle(Namespace::Cast(key).target())); - } -#endif - UNREACHABLE(); - } -}; -typedef UnorderedHashMap MetadataMap; - } // namespace dart #endif // RUNTIME_VM_CANONICAL_TABLES_H_ diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc index 4070944eba1..70d7a0d6a77 100644 --- a/runtime/vm/clustered_snapshot.cc +++ b/runtime/vm/clustered_snapshot.cc @@ -5836,12 +5836,7 @@ ZoneGrowableArray* Serializer::Serialize(SerializationRoots* roots) { WriteUnsigned(num_objects); WriteUnsigned(canonical_clusters.length()); WriteUnsigned(clusters.length()); - // TODO(dartbug.com/36097): Not every snapshot carries the field table. - if (current_loading_unit_id_ <= LoadingUnit::kRootId) { - WriteUnsigned(initial_field_table_->NumFieldIds()); - } else { - WriteUnsigned(0); - } + WriteUnsigned(initial_field_table_->NumFieldIds()); for (SerializationCluster* cluster : canonical_clusters) { cluster->WriteAndMeasureAlloc(this); @@ -6577,8 +6572,8 @@ void Deserializer::Deserialize(DeserializationRoots* roots) { refs_ = Array::New(num_objects_ + kFirstReference, Heap::kOld); if (initial_field_table_len > 0) { initial_field_table_->AllocateIndex(initial_field_table_len - 1); - ASSERT_EQUAL(initial_field_table_->NumFieldIds(), initial_field_table_len); } + ASSERT_EQUAL(initial_field_table_->NumFieldIds(), initial_field_table_len); { NoSafepointScope no_safepoint; diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc index 06e7c4ce451..ea2fc4a5a0a 100644 --- a/runtime/vm/compiler/aot/precompiler.cc +++ b/runtime/vm/compiler/aot/precompiler.cc @@ -2117,9 +2117,47 @@ void Precompiler::TraceTypesFromRetainedClasses() { void Precompiler::DropMetadata() { Library& lib = Library::Handle(Z); + const GrowableObjectArray& null_growable_list = + GrowableObjectArray::Handle(Z); + Array& dependencies = Array::Handle(Z); + Namespace& ns = Namespace::Handle(Z); + const Field& null_field = Field::Handle(Z); + GrowableObjectArray& metadata = GrowableObjectArray::Handle(Z); + Field& metadata_field = Field::Handle(Z); + for (intptr_t i = 0; i < libraries_.Length(); i++) { lib ^= libraries_.At(i); - lib.set_metadata(Array::null_array()); + metadata ^= lib.metadata(); + for (intptr_t j = 0; j < metadata.Length(); j++) { + metadata_field ^= metadata.At(j); + if (metadata_field.is_static()) { + // Although this field will become garbage after clearing the list + // below, we also need to clear its value from the field table. + // The value may be an instance of an otherwise dead class, and if + // it remains in the field table we can get an instance on the heap + // with a deleted class. + metadata_field.SetStaticValue(Object::null_instance(), + /*save_initial_value=*/true); + } + } + + lib.set_metadata(null_growable_list); + + dependencies = lib.imports(); + for (intptr_t j = 0; j < dependencies.Length(); j++) { + ns ^= dependencies.At(j); + if (!ns.IsNull()) { + ns.set_metadata_field(null_field); + } + } + + dependencies = lib.exports(); + for (intptr_t j = 0; j < dependencies.Length(); j++) { + ns ^= dependencies.At(j); + if (!ns.IsNull()) { + ns.set_metadata_field(null_field); + } + } } } diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc index f8c16ec0013..6f83c62d87b 100644 --- a/runtime/vm/dart_api_impl.cc +++ b/runtime/vm/dart_api_impl.cc @@ -6007,7 +6007,7 @@ DART_EXPORT Dart_Handle Dart_GetImportsOfScheme(Dart_Handle scheme) { for (intptr_t j = 0; j < imports.Length(); j++) { ns ^= imports.At(j); if (ns.IsNull()) continue; - importee = ns.target(); + importee = ns.library(); importee_uri = importee.url(); if (importee_uri.StartsWith(scheme_vm)) { result.Add(importer); diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc index 8e586b351ae..a9e660f9aea 100644 --- a/runtime/vm/isolate_reload.cc +++ b/runtime/vm/isolate_reload.cc @@ -961,7 +961,7 @@ void IsolateGroupReloadContext::BuildModifiedLibrariesClosure( for (intptr_t import_idx = 0; import_idx < ports.Length(); import_idx++) { ns ^= ports.At(import_idx); if (!ns.IsNull()) { - target = ns.target(); + target = ns.library(); target_url = target.url(); if (!target_url.StartsWith(Symbols::DartExtensionScheme())) { (*imported_by)[target.index()]->Add(lib.index()); @@ -974,7 +974,7 @@ void IsolateGroupReloadContext::BuildModifiedLibrariesClosure( for (intptr_t export_idx = 0; export_idx < ports.Length(); export_idx++) { ns ^= ports.At(export_idx); if (!ns.IsNull()) { - target = ns.target(); + target = ns.library(); (*imported_by)[target.index()]->Add(lib.index()); } } @@ -992,7 +992,7 @@ void IsolateGroupReloadContext::BuildModifiedLibrariesClosure( import_idx++) { ns ^= ports.At(import_idx); if (!ns.IsNull()) { - target = ns.target(); + target = ns.library(); (*imported_by)[target.index()]->Add(lib.index()); } } diff --git a/runtime/vm/kernel.cc b/runtime/vm/kernel.cc index 952e41a6597..7c53e7203be 100644 --- a/runtime/vm/kernel.cc +++ b/runtime/vm/kernel.cc @@ -430,28 +430,26 @@ class MetadataEvaluator : public KernelReaderHelper { DISALLOW_COPY_AND_ASSIGN(MetadataEvaluator); }; -ObjectPtr EvaluateMetadata(const Library& library, - intptr_t kernel_offset, +ObjectPtr EvaluateMetadata(const Field& metadata_field, bool is_annotations_offset) { LongJumpScope jump; if (setjmp(*jump.Set()) == 0) { Thread* thread = Thread::Current(); Zone* zone = thread->zone(); TranslationHelper helper(thread); - Script& script = Script::Handle( - zone, Class::Handle(zone, library.toplevel_class()).script()); + Script& script = Script::Handle(zone, metadata_field.Script()); helper.InitFromScript(script); - const Class& owner_class = Class::Handle(zone, library.toplevel_class()); + const Class& owner_class = Class::Handle(zone, metadata_field.Owner()); ActiveClass active_class; ActiveClassScope active_class_scope(&active_class, &owner_class); MetadataEvaluator metadata_evaluator( zone, &helper, script, - ExternalTypedData::Handle(zone, library.kernel_data()), - library.kernel_offset(), &active_class); + ExternalTypedData::Handle(zone, metadata_field.KernelData()), + metadata_field.KernelDataProgramOffset(), &active_class); - return metadata_evaluator.EvaluateMetadata(kernel_offset, + return metadata_evaluator.EvaluateMetadata(metadata_field.kernel_offset(), is_annotations_offset); } else { diff --git a/runtime/vm/kernel.h b/runtime/vm/kernel.h index ed66e256ec2..9b0d8de98c8 100644 --- a/runtime/vm/kernel.h +++ b/runtime/vm/kernel.h @@ -196,8 +196,7 @@ class KernelLineStartsReader { void CollectTokenPositionsFor(const Script& script); ObjectPtr EvaluateStaticConstFieldInitializer(const Field& field); -ObjectPtr EvaluateMetadata(const Library& library, - intptr_t kernel_offset, +ObjectPtr EvaluateMetadata(const Field& metadata_field, bool is_annotations_offset); ObjectPtr BuildParameterDescriptor(const Function& function); diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc index 4dbcfb6769d..e37f3257dd7 100644 --- a/runtime/vm/kernel_loader.cc +++ b/runtime/vm/kernel_loader.cc @@ -694,7 +694,7 @@ void KernelLoader::LoadNativeExtensionLibraries() { // Dart_GetImportsOfScheme('dart-ext'). const auto& native_library = Library::Handle(Library::New(uri_path)); library.AddImport(Namespace::Handle(Namespace::New( - native_library, Array::null_array(), Array::null_array(), library))); + native_library, Array::null_array(), Array::null_array()))); } } } @@ -1122,7 +1122,8 @@ LibraryPtr KernelLoader::LoadLibrary(intptr_t index) { if (FLAG_enable_mirrors && annotation_count > 0) { ASSERT(annotations_kernel_offset > 0); - library.AddMetadata(library, annotations_kernel_offset); + library.AddLibraryMetadata(toplevel_class, TokenPosition::kNoSource, + annotations_kernel_offset); } if (register_class) { @@ -1247,7 +1248,7 @@ void KernelLoader::FinishTopLevelClassLoading( if ((FLAG_enable_mirrors || has_pragma_annotation) && annotation_count > 0) { - library.AddMetadata(field, field_offset); + library.AddFieldMetadata(field, TokenPosition::kNoSource, field_offset); } fields_.Add(&field); } @@ -1365,7 +1366,7 @@ void KernelLoader::LoadLibraryImportsAndExports(Library* library, "import of dart:ffi is not supported in the current Dart runtime"); } String& prefix = H.DartSymbolPlain(dependency_helper.name_index_); - ns = Namespace::New(target_library, show_names, hide_names, *library); + ns = Namespace::New(target_library, show_names, hide_names); if ((dependency_helper.flags_ & LibraryDependencyHelper::Export) != 0) { library->AddExport(ns); } else { @@ -1388,7 +1389,8 @@ void KernelLoader::LoadLibraryImportsAndExports(Library* library, if (FLAG_enable_mirrors && dependency_helper.annotation_count_ > 0) { ASSERT(annotations_kernel_offset > 0); - library->AddMetadata(ns, annotations_kernel_offset); + ns.AddMetadata(toplevel_class, TokenPosition::kNoSource, + annotations_kernel_offset); } if (prefix.IsNull()) { @@ -1509,7 +1511,9 @@ void KernelLoader::LoadClass(const Library& library, } if ((FLAG_enable_mirrors || has_pragma_annotation) && annotation_count > 0) { - library.AddMetadata(*out_class, class_offset - correction_offset_); + library.AddClassMetadata(*out_class, toplevel_class, + TokenPosition::kNoSource, + class_offset - correction_offset_); } // We do not register expression evaluation classes with the VM: @@ -1621,7 +1625,7 @@ void KernelLoader::FinishClassLoading(const Class& klass, } if ((FLAG_enable_mirrors || has_pragma_annotation) && annotation_count > 0) { - library.AddMetadata(field, field_offset); + library.AddFieldMetadata(field, TokenPosition::kNoSource, field_offset); } fields_.Add(&field); } @@ -1720,7 +1724,8 @@ void KernelLoader::FinishClassLoading(const Class& klass, if ((FLAG_enable_mirrors || has_pragma_annotation) && annotation_count > 0) { - library.AddMetadata(function, constructor_offset); + library.AddFunctionMetadata(function, TokenPosition::kNoSource, + constructor_offset); } } @@ -2044,7 +2049,8 @@ void KernelLoader::LoadProcedure(const Library& library, helper_.SetOffset(procedure_end); if (annotation_count > 0) { - library.AddMetadata(function, procedure_offset); + library.AddFunctionMetadata(function, TokenPosition::kNoSource, + procedure_offset); } if (has_pragma_annotation) { diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index 5fa7d0edce8..87ca73bc958 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -11586,25 +11586,175 @@ void Library::SetLoaded() const { StoreNonPointer(&raw_ptr()->load_state_, LibraryLayout::kLoaded); } -void Library::AddMetadata(const Object& declaration, +static StringPtr MakeClassMetaName(Thread* thread, + Zone* zone, + const Class& cls) { + return Symbols::FromConcat(thread, Symbols::At(), + String::Handle(zone, cls.Name())); +} + +static StringPtr MakeFieldMetaName(Thread* thread, + Zone* zone, + const Field& field) { + const String& cname = String::Handle( + zone, + MakeClassMetaName(thread, zone, Class::Handle(zone, field.Origin()))); + GrowableHandlePtrArray pieces(zone, 3); + pieces.Add(cname); + pieces.Add(Symbols::At()); + pieces.Add(String::Handle(zone, field.name())); + return Symbols::FromConcatAll(thread, pieces); +} + +static StringPtr MakeFunctionMetaName(Thread* thread, + Zone* zone, + const Function& func) { + const String& cname = String::Handle( + zone, + MakeClassMetaName(thread, zone, Class::Handle(zone, func.origin()))); + GrowableHandlePtrArray pieces(zone, 3); + pieces.Add(cname); + pieces.Add(Symbols::At()); + pieces.Add(String::Handle(zone, func.name())); + return Symbols::FromConcatAll(thread, pieces); +} + +static StringPtr MakeTypeParameterMetaName(Thread* thread, + Zone* zone, + const TypeParameter& param) { + const String& cname = String::Handle( + zone, + MakeClassMetaName(thread, zone, + Class::Handle(zone, param.parameterized_class()))); + GrowableHandlePtrArray pieces(zone, 3); + pieces.Add(cname); + pieces.Add(Symbols::At()); + pieces.Add(String::Handle(zone, param.name())); + return Symbols::FromConcatAll(thread, pieces); +} + +void Library::AddMetadata(const Object& owner, + const String& name, + TokenPosition token_pos, intptr_t kernel_offset) const { #if defined(DART_PRECOMPILED_RUNTIME) UNREACHABLE(); #else - MetadataMap map(metadata()); - map.UpdateOrInsert(declaration, Smi::Handle(Smi::New(kernel_offset))); - set_metadata(map.Release()); + Thread* thread = Thread::Current(); + ASSERT(thread->IsMutatorThread()); + Zone* zone = thread->zone(); + const String& metaname = String::Handle(zone, Symbols::New(thread, name)); + const Field& field = + Field::Handle(zone, Field::NewTopLevel(metaname, + false, // is_final + false, // is_const + false, // is_late + owner, token_pos, token_pos)); + field.SetFieldType(Object::dynamic_type()); + field.set_is_reflectable(false); + field.set_kernel_offset(kernel_offset); + thread->isolate_group()->RegisterStaticField(field, Array::empty_array()); + + GrowableObjectArray& metadata = + GrowableObjectArray::Handle(zone, this->metadata()); + metadata.Add(field, Heap::kOld); #endif // defined(DART_PRECOMPILED_RUNTIME) } -ObjectPtr Library::GetMetadata(const Object& declaration) const { +void Library::AddClassMetadata(const Class& cls, + const Object& tl_owner, + TokenPosition token_pos, + intptr_t kernel_offset) const { + Thread* thread = Thread::Current(); + Zone* zone = thread->zone(); + // We use the toplevel class as the owner of a class's metadata field because + // a class's metadata is in scope of the library, not the class. + AddMetadata(tl_owner, + String::Handle(zone, MakeClassMetaName(thread, zone, cls)), + token_pos, kernel_offset); +} + +void Library::AddFieldMetadata(const Field& field, + TokenPosition token_pos, + intptr_t kernel_offset) const { + Thread* thread = Thread::Current(); + Zone* zone = thread->zone(); + const auto& owner = Object::Handle(zone, field.RawOwner()); + const auto& name = + String::Handle(zone, MakeFieldMetaName(thread, zone, field)); + AddMetadata(owner, name, token_pos, kernel_offset); +} + +void Library::AddFunctionMetadata(const Function& func, + TokenPosition token_pos, + intptr_t kernel_offset) const { + Thread* thread = Thread::Current(); + Zone* zone = thread->zone(); + const auto& owner = Object::Handle(zone, func.RawOwner()); + const auto& name = + String::Handle(zone, MakeFunctionMetaName(thread, zone, func)); + AddMetadata(owner, name, token_pos, kernel_offset); +} + +void Library::AddTypeParameterMetadata(const TypeParameter& param, + TokenPosition token_pos) const { + Thread* thread = Thread::Current(); + Zone* zone = thread->zone(); + const auto& owner = Class::Handle(zone, param.parameterized_class()); + const auto& name = + String::Handle(zone, MakeTypeParameterMetaName(thread, zone, param)); + AddMetadata(owner, name, token_pos, 0); +} + +void Library::AddLibraryMetadata(const Object& tl_owner, + TokenPosition token_pos, + intptr_t kernel_offset) const { + AddMetadata(tl_owner, Symbols::TopLevel(), token_pos, kernel_offset); +} + +StringPtr Library::MakeMetadataName(const Object& obj) const { + Thread* thread = Thread::Current(); + Zone* zone = thread->zone(); + if (obj.IsClass()) { + return MakeClassMetaName(thread, zone, Class::Cast(obj)); + } else if (obj.IsField()) { + return MakeFieldMetaName(thread, zone, Field::Cast(obj)); + } else if (obj.IsFunction()) { + return MakeFunctionMetaName(thread, zone, Function::Cast(obj)); + } else if (obj.IsLibrary()) { + return Symbols::TopLevel().raw(); + } else if (obj.IsTypeParameter()) { + return MakeTypeParameterMetaName(thread, zone, TypeParameter::Cast(obj)); + } + UNIMPLEMENTED(); + return String::null(); +} + +FieldPtr Library::GetMetadataField(const String& metaname) const { + const GrowableObjectArray& metadata = + GrowableObjectArray::Handle(this->metadata()); + Field& entry = Field::Handle(); + String& entryname = String::Handle(); + intptr_t num_entries = metadata.Length(); + for (intptr_t i = 0; i < num_entries; i++) { + entry ^= metadata.At(i); + entryname = entry.name(); + if (entryname.Equals(metaname)) { + return entry.raw(); + } + } + return Field::null(); +} + +ObjectPtr Library::GetMetadata(const Object& obj) const { #if defined(DART_PRECOMPILED_RUNTIME) return Object::empty_array().raw(); #else - RELEASE_ASSERT(declaration.IsClass() || declaration.IsField() || - declaration.IsFunction() || declaration.IsLibrary() || - declaration.IsTypeParameter() || declaration.IsNamespace()); - if (declaration.IsLibrary()) { + if (!obj.IsClass() && !obj.IsField() && !obj.IsFunction() && + !obj.IsLibrary() && !obj.IsTypeParameter()) { + UNREACHABLE(); + } + if (obj.IsLibrary()) { // Ensure top-level class is loaded as it may contain annotations of // a library. const auto& cls = Class::Handle(toplevel_class()); @@ -11612,36 +11762,31 @@ ObjectPtr Library::GetMetadata(const Object& declaration) const { cls.EnsureDeclarationLoaded(); } } - Object& value = Object::Handle(); - { - MetadataMap map(metadata()); - value = map.GetOrNull(declaration); - set_metadata(map.Release()); - } - if (value.IsNull()) { + const String& metaname = String::Handle(MakeMetadataName(obj)); + Field& field = Field::Handle(GetMetadataField(metaname)); + if (field.IsNull()) { // There is no metadata for this object. return Object::empty_array().raw(); } - if (!value.IsSmi()) { - // Metadata is already evaluated. - ASSERT(value.IsArray()); - return value.raw(); - } - intptr_t kernel_offset = Smi::Cast(value).Value(); - ASSERT(kernel_offset > 0); - value = kernel::EvaluateMetadata( - *this, kernel_offset, - /* is_annotations_offset = */ declaration.IsLibrary() || - declaration.IsNamespace()); - if (value.IsArray() || value.IsNull()) { - ASSERT(value.raw() != Object::empty_array().raw()); - if (!Compiler::IsBackgroundCompilation()) { - MetadataMap map(metadata()); - map.UpdateOrInsert(declaration, value); - set_metadata(map.Release()); + Object& metadata = Object::Handle(field.StaticValue()); + if (metadata.raw() == Object::empty_array().raw()) { + ASSERT(field.kernel_offset() > 0); + metadata = kernel::EvaluateMetadata( + field, /* is_annotations_offset = */ obj.IsLibrary()); + if (metadata.IsArray() || metadata.IsNull()) { + ASSERT(metadata.raw() != Object::empty_array().raw()); + if (!Compiler::IsBackgroundCompilation()) { + field.SetStaticValue( + metadata.IsNull() ? Object::null_array() : Array::Cast(metadata), + true); + } } } - return value.raw(); + if (metadata.IsNull()) { + // Metadata field exists in order to reference extended metadata. + return Object::empty_array().raw(); + } + return metadata.raw(); #endif // defined(DART_PRECOMPILED_RUNTIME) } @@ -12188,7 +12333,7 @@ ObjectPtr Library::LookupImportedObject(const String& name) const { import = ImportAt(i); obj = import.Lookup(name); if (!obj.IsNull()) { - import_lib = import.target(); + import_lib = import.library(); import_lib_url = import_lib.url(); if (found_obj.raw() != obj.raw()) { if (first_import_lib_url.IsNull() || @@ -12312,7 +12457,7 @@ void Library::set_dependencies(const Array& deps) const { raw_ptr()->set_dependencies(deps.raw()); } -void Library::set_metadata(const Array& value) const { +void Library::set_metadata(const GrowableObjectArray& value) const { raw_ptr()->set_metadata(value.raw()); } @@ -12321,7 +12466,7 @@ LibraryPtr Library::ImportLibraryAt(intptr_t index) const { if (import.IsNull()) { return Library::null(); } - return import.target(); + return import.library(); } NamespacePtr Library::ImportAt(intptr_t index) const { @@ -12343,7 +12488,7 @@ void Library::DropDependenciesAndCaches() const { for (int i = 0; i < imports.Length(); ++i) { ns = Namespace::RawCast(imports.At(i)); if (ns.IsNull()) continue; - lib = ns.target(); + lib = ns.library(); url = lib.url(); if (url.StartsWith(Symbols::DartExtensionScheme())) { native_import_count++; @@ -12354,7 +12499,7 @@ void Library::DropDependenciesAndCaches() const { for (int i = 0, j = 0; i < imports.Length(); ++i) { ns = Namespace::RawCast(imports.At(i)); if (ns.IsNull()) continue; - lib = ns.target(); + lib = ns.library(); url = lib.url(); if (url.StartsWith(Symbols::DartExtensionScheme())) { new_imports.SetAt(j++, ns); @@ -12472,11 +12617,10 @@ LibraryPtr Library::NewLibraryHelper(const String& url, bool import_core_lib) { result.raw_ptr()->set_resolved_names(Array::null()); result.raw_ptr()->set_exported_names(Array::null()); result.raw_ptr()->set_dictionary(Object::empty_array().raw()); - Array& array = Array::Handle(zone); - array = HashTables::New(4, Heap::kOld); - result.raw_ptr()->set_metadata(array.raw()); - result.raw_ptr()->set_toplevel_class(Class::null()); GrowableObjectArray& list = GrowableObjectArray::Handle(zone); + list = GrowableObjectArray::New(4, Heap::kOld); + result.raw_ptr()->set_metadata(list.raw()); + result.raw_ptr()->set_toplevel_class(Class::null()); list = GrowableObjectArray::New(Object::empty_array(), Heap::kOld); result.raw_ptr()->set_used_scripts(list.raw()); result.raw_ptr()->set_imports(Object::empty_array().raw()); @@ -12506,9 +12650,9 @@ LibraryPtr Library::NewLibraryHelper(const String& url, bool import_core_lib) { if (import_core_lib) { const Library& core_lib = Library::Handle(zone, Library::CoreLibrary()); ASSERT(!core_lib.IsNull()); - const Namespace& ns = - Namespace::Handle(zone, Namespace::New(core_lib, Object::null_array(), - Object::null_array(), result)); + const Namespace& ns = Namespace::Handle( + zone, + Namespace::New(core_lib, Object::null_array(), Object::null_array())); result.AddImport(ns); } return result.raw(); @@ -13133,7 +13277,7 @@ LibraryPtr LibraryPrefix::GetLibrary(int index) const { const Array& imports = Array::Handle(this->imports()); Namespace& import = Namespace::Handle(); import ^= imports.At(index); - return import.target(); + return import.library(); } return Library::null(); } @@ -13203,8 +13347,59 @@ const char* LibraryPrefix::ToCString() const { return prefix.ToCString(); } +void Namespace::set_metadata_field(const Field& value) const { + raw_ptr()->set_metadata_field(value.raw()); +} + +void Namespace::AddMetadata(const Object& owner, + TokenPosition token_pos, + intptr_t kernel_offset) { + auto thread = Thread::Current(); + auto zone = thread->zone(); + auto isolate_group = thread->isolate_group(); + ASSERT(Field::Handle(zone, metadata_field()).IsNull()); + Field& field = + Field::Handle(zone, Field::NewTopLevel(Symbols::TopLevel(), + false, // is_final + false, // is_const + false, // is_late + owner, token_pos, token_pos)); + field.set_is_reflectable(false); + field.SetFieldType(Object::dynamic_type()); + field.set_kernel_offset(kernel_offset); + isolate_group->RegisterStaticField(field, Array::empty_array()); + set_metadata_field(field); +} + +ObjectPtr Namespace::GetMetadata() const { +#if defined(DART_PRECOMPILED_RUNTIME) + return Object::empty_array().raw(); +#else + Field& field = Field::Handle(metadata_field()); + if (field.IsNull()) { + // There is no metadata for this object. + return Object::empty_array().raw(); + } + Object& metadata = Object::Handle(); + metadata = field.StaticValue(); + if (field.StaticValue() == Object::empty_array().raw()) { + if (field.kernel_offset() > 0) { + metadata = + kernel::EvaluateMetadata(field, /* is_annotations_offset = */ true); + } else { + UNREACHABLE(); + } + if (metadata.IsArray()) { + ASSERT(Array::Cast(metadata).raw() != Object::empty_array().raw()); + field.SetStaticValue(Array::Cast(metadata), true); + } + } + return metadata.raw(); +#endif // defined(DART_PRECOMPILED_RUNTIME) +} + const char* Namespace::ToCString() const { - const Library& lib = Library::Handle(target()); + const Library& lib = Library::Handle(library()); return OS::SCreate(Thread::Current()->zone(), "Namespace for library '%s'", lib.ToCString()); } @@ -13258,7 +13453,7 @@ bool Namespace::HidesName(const String& name) const { ObjectPtr Namespace::Lookup(const String& name, ZoneGrowableArray* trail) const { Zone* zone = Thread::Current()->zone(); - const Library& lib = Library::Handle(zone, target()); + const Library& lib = Library::Handle(zone, library()); if (trail != NULL) { // Look for cycle in reexport graph. @@ -13319,17 +13514,15 @@ NamespacePtr Namespace::New() { return static_cast(raw); } -NamespacePtr Namespace::New(const Library& target, +NamespacePtr Namespace::New(const Library& library, const Array& show_names, - const Array& hide_names, - const Library& owner) { + const Array& hide_names) { ASSERT(show_names.IsNull() || (show_names.Length() > 0)); ASSERT(hide_names.IsNull() || (hide_names.Length() > 0)); const Namespace& result = Namespace::Handle(Namespace::New()); - result.raw_ptr()->set_target(target.raw()); + result.raw_ptr()->set_library(library.raw()); result.raw_ptr()->set_show_names(show_names.raw()); result.raw_ptr()->set_hide_names(hide_names.raw()); - result.raw_ptr()->set_owner(owner.raw()); return result.raw(); } @@ -24875,13 +25068,9 @@ ErrorPtr Function::VerifyClosurizedEntryPoint() const { const Library& lib = Library::Handle(cls.library()); switch (kind()) { case FunctionLayout::kRegularFunction: + case FunctionLayout::kImplicitClosureFunction: return dart::VerifyEntryPoint(lib, *this, *this, {EntryPointPragma::kGetterOnly}); - case FunctionLayout::kImplicitClosureFunction: { - const Function& parent = Function::Handle(parent_function()); - return dart::VerifyEntryPoint(lib, parent, parent, - {EntryPointPragma::kGetterOnly}); - } default: UNREACHABLE(); } diff --git a/runtime/vm/object.h b/runtime/vm/object.h index ac00550942a..59377ebcbc3 100644 --- a/runtime/vm/object.h +++ b/runtime/vm/object.h @@ -4738,8 +4738,22 @@ class Library : public Object { void AddExport(const Namespace& ns) const; - void AddMetadata(const Object& declaration, intptr_t kernel_offset) const; - ObjectPtr GetMetadata(const Object& declaration) const; + void AddClassMetadata(const Class& cls, + const Object& tl_owner, + TokenPosition token_pos, + intptr_t kernel_offset) const; + void AddFieldMetadata(const Field& field, + TokenPosition token_pos, + intptr_t kernel_offset) const; + void AddFunctionMetadata(const Function& func, + TokenPosition token_pos, + intptr_t kernel_offset) const; + void AddLibraryMetadata(const Object& tl_owner, + TokenPosition token_pos, + intptr_t kernel_offset) const; + void AddTypeParameterMetadata(const TypeParameter& param, + TokenPosition token_pos) const; + ObjectPtr GetMetadata(const Object& obj) const; // Tries to finds a @pragma annotation on [object]. // @@ -4964,8 +4978,8 @@ class Library : public Object { void set_flags(uint8_t flags) const; bool HasExports() const; ArrayPtr loaded_scripts() const { return raw_ptr()->loaded_scripts(); } - ArrayPtr metadata() const { return raw_ptr()->metadata(); } - void set_metadata(const Array& value) const; + GrowableObjectArrayPtr metadata() const { return raw_ptr()->metadata(); } + void set_metadata(const GrowableObjectArray& value) const; ArrayPtr dictionary() const { return raw_ptr()->dictionary(); } void InitClassDictionary() const; @@ -4993,6 +5007,13 @@ class Library : public Object { void AllocatePrivateKey() const; + StringPtr MakeMetadataName(const Object& obj) const; + FieldPtr GetMetadataField(const String& metaname) const; + void AddMetadata(const Object& owner, + const String& name, + TokenPosition token_pos, + intptr_t kernel_offset) const; + FINAL_HEAP_OBJECT_IMPLEMENTATION(Library, Object); friend class Bootstrap; @@ -5010,10 +5031,14 @@ class Library : public Object { // the show/hide combinators. class Namespace : public Object { public: - LibraryPtr target() const { return raw_ptr()->target(); } + LibraryPtr library() const { return raw_ptr()->library(); } ArrayPtr show_names() const { return raw_ptr()->show_names(); } ArrayPtr hide_names() const { return raw_ptr()->hide_names(); } - LibraryPtr owner() const { return raw_ptr()->owner(); } + + void AddMetadata(const Object& owner, + TokenPosition token_pos, + intptr_t kernel_offset = 0); + ObjectPtr GetMetadata() const; static intptr_t InstanceSize() { return RoundedAllocationSize(sizeof(NamespaceLayout)); @@ -5025,12 +5050,14 @@ class Namespace : public Object { static NamespacePtr New(const Library& library, const Array& show_names, - const Array& hide_names, - const Library& owner); + const Array& hide_names); private: static NamespacePtr New(); + FieldPtr metadata_field() const { return raw_ptr()->metadata_field(); } + void set_metadata_field(const Field& value) const; + FINAL_HEAP_OBJECT_IMPLEMENTATION(Namespace, Object); friend class Class; friend class Precompiler; diff --git a/runtime/vm/object_service.cc b/runtime/vm/object_service.cc index 1dfe634810e..08bfa2391ee 100644 --- a/runtime/vm/object_service.cc +++ b/runtime/vm/object_service.cc @@ -519,7 +519,7 @@ void Library::PrintJSONImpl(JSONStream* stream, bool ref) const { jsdep.AddProperty("isDeferred", false); jsdep.AddProperty("isExport", false); jsdep.AddProperty("isImport", true); - target = ns.target(); + target = ns.library(); jsdep.AddProperty("target", target); } @@ -533,7 +533,7 @@ void Library::PrintJSONImpl(JSONStream* stream, bool ref) const { jsdep.AddProperty("isDeferred", false); jsdep.AddProperty("isExport", true); jsdep.AddProperty("isImport", false); - target = ns.target(); + target = ns.library(); jsdep.AddProperty("target", target); } @@ -559,7 +559,7 @@ void Library::PrintJSONImpl(JSONStream* stream, bool ref) const { prefix_name = prefix.name(); ASSERT(!prefix_name.IsNull()); jsdep.AddProperty("prefix", prefix_name.ToCString()); - target = ns.target(); + target = ns.library(); jsdep.AddProperty("target", target); } } diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h index f5ff2067f7b..0f9c283f41e 100644 --- a/runtime/vm/raw_object.h +++ b/runtime/vm/raw_object.h @@ -1409,7 +1409,8 @@ class LibraryLayout : public ObjectLayout { POINTER_FIELD(StringPtr, url) POINTER_FIELD(StringPtr, private_key) POINTER_FIELD(ArrayPtr, dictionary) // Top-level names in this library. - POINTER_FIELD(ArrayPtr, metadata) // Metadata on classes, methods etc. + POINTER_FIELD(GrowableObjectArrayPtr, + metadata) // Metadata on classes, methods etc. POINTER_FIELD(ClassPtr, toplevel_class) // Class containing top-level elements. POINTER_FIELD(GrowableObjectArrayPtr, used_scripts) @@ -1461,12 +1462,14 @@ class LibraryLayout : public ObjectLayout { class NamespaceLayout : public ObjectLayout { RAW_HEAP_OBJECT_IMPLEMENTATION(Namespace); - VISIT_FROM(ObjectPtr, target) - POINTER_FIELD(LibraryPtr, target) // library with name dictionary. + VISIT_FROM(ObjectPtr, library) + POINTER_FIELD(LibraryPtr, library) // library with name dictionary. POINTER_FIELD(ArrayPtr, show_names) // list of names that are exported. POINTER_FIELD(ArrayPtr, hide_names) // list of names that are hidden. - POINTER_FIELD(LibraryPtr, owner) - VISIT_TO(ObjectPtr, owner) + POINTER_FIELD(FieldPtr, + metadata_field) // remembers the token pos of metadata if any, + // and the metadata values if computed. + VISIT_TO(ObjectPtr, metadata_field) ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); } }; diff --git a/runtime/vm/raw_object_fields.cc b/runtime/vm/raw_object_fields.cc index 103611e12e8..cf5625ba949 100644 --- a/runtime/vm/raw_object_fields.cc +++ b/runtime/vm/raw_object_fields.cc @@ -75,10 +75,10 @@ namespace dart { F(Library, resolved_names_) \ F(Library, exported_names_) \ F(Library, loaded_scripts_) \ - F(Namespace, target_) \ + F(Namespace, library_) \ F(Namespace, show_names_) \ F(Namespace, hide_names_) \ - F(Namespace, owner_) \ + F(Namespace, metadata_field_) \ F(KernelProgramInfo, string_offsets_) \ F(KernelProgramInfo, string_data_) \ F(KernelProgramInfo, canonical_names_) \