Version 2.12.0-111.0.dev

Merge commit 'a9d212b94aa73472824f4218a567a8e004575112' into 'dev'
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index 9ecfe27..207e58c 100644
--- a/.dart_tool/package_config.json
+++ b/.dart_tool/package_config.json
@@ -11,7 +11,7 @@
     "constraint, update this by running tools/generate_package_config.dart."
   ],
   "configVersion": 2,
-  "generated": "2020-11-30T16:23:50.740805",
+  "generated": "2020-11-15T14:18:10.587065",
   "generator": "tools/generate_package_config.dart",
   "packages": [
     {
@@ -101,7 +101,7 @@
       "name": "args",
       "rootUri": "../third_party/pkg/args",
       "packageUri": "lib/",
-      "languageVersion": "2.12"
+      "languageVersion": "2.3"
     },
     {
       "name": "async",
diff --git a/DEPS b/DEPS
index 7ca29d6..a5eac9a 100644
--- a/DEPS
+++ b/DEPS
@@ -68,7 +68,7 @@
   "gperftools_revision": "180bfa10d7cb38e8b3784d60943d50e8fcef0dcb",
 
   # Revisions of /third_party/* dependencies.
-  "args_rev": "139140125126661fac88c9aa5882165936d01c91",
+  "args_tag": "1.6.0",
   "async_rev": "695b3ac280f107c84adf7488743abfdfaaeea68f",
   "bazel_worker_rev": "060c55a933d39798681a4f533b161b81dc48d77e",
   "benchmark_harness_rev": "ec6b646f5443faa871e126ac1ba248c94ca06257",
@@ -301,7 +301,7 @@
       "@" + Var("gperftools_revision"),
 
   Var("dart_root") + "/third_party/pkg/args":
-      Var("dart_git") + "args.git" + "@" + Var("args_rev"),
+      Var("dart_git") + "args.git" + "@" + Var("args_tag"),
   Var("dart_root") + "/third_party/pkg/async":
       Var("dart_git") + "async.git" + "@" + Var("async_rev"),
   Var("dart_root") + "/third_party/pkg/bazel_worker":
diff --git a/pkg/native_stack_traces/bin/decode.dart b/pkg/native_stack_traces/bin/decode.dart
index 4ced1ca..9a7aee0 100644
--- a/pkg/native_stack_traces/bin/decode.dart
+++ b/pkg/native_stack_traces/bin/decode.dart
@@ -300,12 +300,12 @@
   if (options['help']) return print(_usages[options.command?.name]);
   if (options.command == null) return errorWithUsage('no command provided');
 
-  switch (options.command!.name) {
+  switch (options.command.name) {
     case 'help':
-      return help(options.command!);
+      return help(options.command);
     case 'find':
-      return find(options.command!);
+      return find(options.command);
     case 'translate':
-      return await translate(options.command!);
+      return await translate(options.command);
   }
 }
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index eddf299..a829957 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -435,12 +435,11 @@
                                                  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 3fd3f24..69b79eb 100644
--- a/runtime/vm/canonical_tables.h
+++ b/runtime/vm/canonical_tables.h
@@ -254,38 +254,6 @@
 typedef UnorderedHashSet<CanonicalTypeArgumentsTraits>
     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<MetadataMapTraits> MetadataMap;
-
 }  // namespace dart
 
 #endif  // RUNTIME_VM_CANONICAL_TABLES_H_
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 4070944..70d7a0d 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -5836,12 +5836,7 @@
   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 @@
   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 06e7c4c..ea2fc4a 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -2117,9 +2117,47 @@
 
 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 f8c16ec..6f83c62 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -6007,7 +6007,7 @@
     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 8e586b3..a9e660f 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -961,7 +961,7 @@
     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 @@
     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 @@
              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 952e41a..7c53e72 100644
--- a/runtime/vm/kernel.cc
+++ b/runtime/vm/kernel.cc
@@ -430,28 +430,26 @@
   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 ed66e25..9b0d8de 100644
--- a/runtime/vm/kernel.h
+++ b/runtime/vm/kernel.h
@@ -196,8 +196,7 @@
 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 4dbcfb6..e37f325 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -694,7 +694,7 @@
       // 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 @@
 
   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 @@
 
     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 @@
           "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 @@
 
     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 @@
   }
 
   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 @@
       }
       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 @@
 
     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 @@
   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 5fa7d0e..87ca73b 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -11586,25 +11586,175 @@
   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<const String> 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<const String> 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<const String> 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 @@
       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 @@
     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 @@
   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 @@
   if (import.IsNull()) {
     return Library::null();
   }
-  return import.target();
+  return import.library();
 }
 
 NamespacePtr Library::ImportAt(intptr_t index) const {
@@ -12343,7 +12488,7 @@
   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 @@
   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 @@
   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<MetadataMap>(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 @@
   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 @@
     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 @@
   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 @@
 ObjectPtr Namespace::Lookup(const String& name,
                             ZoneGrowableArray<intptr_t>* 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 @@
   return static_cast<NamespacePtr>(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 @@
   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 ac00550..59377eb 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -4738,8 +4738,22 @@
 
   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 @@
   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 @@
 
   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 @@
 // 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 @@
 
   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 1dfe634..08bfa23 100644
--- a/runtime/vm/object_service.cc
+++ b/runtime/vm/object_service.cc
@@ -519,7 +519,7 @@
       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 @@
       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 @@
             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 f5ff206..0f9c283 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -1409,7 +1409,8 @@
   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 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 103611e..cf5625b 100644
--- a/runtime/vm/raw_object_fields.cc
+++ b/runtime/vm/raw_object_fields.cc
@@ -75,10 +75,10 @@
   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_)                                       \
diff --git a/tools/VERSION b/tools/VERSION
index a477cf6..c3af410 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 12
 PATCH 0
-PRERELEASE 110
+PRERELEASE 111
 PRERELEASE_PATCH 0
\ No newline at end of file