Version 2.14.0-297.0.dev

Merge commit '359fcac96d745053d0edfd54400cc868d8c6e25a' into 'dev'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 07b09a7..ed952c4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,49 @@
 ## 2.14.0
 
+### Language
+
+- Add an unsigned shift right operator `>>>`. Pad with zeroes, ignoring the sign
+  bit. On the web platform `int.>>>` shifts the low 32 bits interpreted as an
+  unsigned integer, so `a >>> b` gives the same result as
+  `a.toUnsigned(32) >>> b` on the VM.
+
+- Prior to Dart 2.14, metadata (annotations) were not permitted to be specified
+  with generic type arguments. This restriction is lifted in Dart Dart 2.14.
+
+  ```dart
+  class C<T> {
+    const C();
+  }
+  @C();      // Previously permitted.
+  @C<int>(); // Previously an error, now permitted.
+  ```
+
+- Prior to Dart 2.14, generic function types were not permitted as arguments to
+  generic classes or functions, nor to be used as generic bounds. This
+  restriction is lifted in Dart 2.14.
+
+  ```dart
+  T wrapWithLogging<T>(T f) {
+    if (f is void Function<T>(T x)) {
+      return <S>(S x) {
+        print("Call: f<$S>($x)");
+        var r = f<S>(x);
+        print("Return: $x");
+        return r;
+      } as T;
+    } // More cases here
+    return f;
+  }
+  void foo<T>(T x) {
+    print("Foo!");
+  }
+  void main() {
+    // Previously an error, now permitted.
+    var f = wrapWithLogging<void Function<T>(T)>(foo);
+    f<int>(3);
+  }
+  ```
+
 ### Core libraries
 
 #### `dart:async`
@@ -107,11 +151,11 @@
 
 #### dart format
 
-*   Simplify and optimize cascade formatting.
-    See: https://github.com/dart-lang/dart_style/pull/1033
-*   Don't unnecessarily split argument lists with `/* */` comments.
-*   Return correct exit code from `FormatCommand` when formatting stdin.
-*   Split empty catch blocks with finally clauses or catches after them.
+- Simplify and optimize cascade formatting. See:
+  https://github.com/dart-lang/dart_style/pull/1033
+- Don't unnecessarily split argument lists with `/* */` comments.
+- Return correct exit code from `FormatCommand` when formatting stdin.
+- Split empty catch blocks with finally clauses or catches after them.
 
 #### Linter
 
@@ -190,50 +234,6 @@
 - Incremental compilation is now used for compilation of executables from
   dependencies when using `dart run <package>:<command>`.
 
-### Language
-
-- Add an unsigned shift right operator `>>>`. Pad with zeroes, ignoring the sign
-  bit. On the web platform `int.>>>` shifts the low 32 bits interpreted as an
-  unsigned integer, so `a >>> b` gives the same result as
-  `a.toUnsigned(32) >>> b` on the VM.
-
-- Prior to Dart 2.14, metadata (annotations) were not permitted to be specified
-  with generic type arguments. This restriction is lifted in Dart Dart 2.14.
-
-  ```dart
-  class C<T> {
-    const C();
-  }
-  @C();      // Previously permitted.
-  @C<int>(); // Previously an error, now permitted.
-  ```
-
-- Prior to Dart 2.14, generic function types were not permitted as arguments to
-  generic classes or functions, nor to be used as generic bounds. This
-  restriction is lifted in Dart 2.14.
-
-  ```dart
-  T wrapWithLogging<T>(T f) {
-    if (f is void Function<T>(T x)) {
-      return <S>(S x) {
-        print("Call: f<$S>($x)");
-        var r = f<S>(x);
-        print("Return: $x");
-        return r;
-      } as T;
-    } // More cases here
-    return f;
-  }
-  void foo<T>(T x) {
-    print("Foo!");
-  }
-  void main() {
-    // Previously an error, now permitted.
-    var f = wrapWithLogging<void Function<T>(T)>(foo);
-    f<int>(3);
-  }
-  ```
-
 ## 2.13.4 - 2021-06-28
 
 This is a patch release that fixes:
diff --git a/runtime/vm/dwarf.h b/runtime/vm/dwarf.h
index 3fd1255..9990162 100644
--- a/runtime/vm/dwarf.h
+++ b/runtime/vm/dwarf.h
@@ -246,7 +246,7 @@
 
   // Prefixes the content added by body with its length. Returns an
   // appropriately encoded representation of the start of the content added by
-  // the body (_not_ the start of the prefixed length).
+  // the body (including the length prefix).
   //
   // symbol_prefix is used when a local symbol is created for the length.
   virtual EncodedPosition WritePrefixedLength(const char* symbol_prefix,
diff --git a/runtime/vm/elf.cc b/runtime/vm/elf.cc
index a073428..942ed59 100644
--- a/runtime/vm/elf.cc
+++ b/runtime/vm/elf.cc
@@ -478,71 +478,6 @@
   CStringIntMap text_indices_;
 };
 
-class Symbol : public ZoneAllocated {
- public:
-  Symbol(const char* cstr,
-         intptr_t name,
-         intptr_t binding,
-         intptr_t type,
-         intptr_t initial_section_index,
-         intptr_t size)
-      : name_index(name),
-        binding(binding),
-        type(type),
-        size(size),
-        section_index(initial_section_index),
-        cstr_(cstr) {}
-
-  void Finalize(intptr_t final_section_index, intptr_t offset) {
-    ASSERT(!HasBeenFinalized());  // No symbol should be re-finalized.
-    section_index = final_section_index;
-    offset_ = offset;
-  }
-  bool HasBeenFinalized() const { return offset_ != kNotFinalizedMarker; }
-  intptr_t offset() const {
-    ASSERT(HasBeenFinalized());
-    // Only the reserved initial symbol should have an offset of 0.
-    ASSERT_EQUAL(type == elf::STT_NOTYPE, offset_ == 0);
-    return offset_;
-  }
-
-  void Write(ElfWriteStream* stream) const {
-    const intptr_t start = stream->Position();
-    stream->WriteWord(name_index);
-#if defined(TARGET_ARCH_IS_32_BIT)
-    stream->WriteAddr(offset());
-    stream->WriteWord(size);
-    stream->WriteByte(elf::SymbolInfo(binding, type));
-    stream->WriteByte(0);
-    stream->WriteHalf(section_index);
-#else
-    stream->WriteByte(elf::SymbolInfo(binding, type));
-    stream->WriteByte(0);
-    stream->WriteHalf(section_index);
-    stream->WriteAddr(offset());
-    stream->WriteXWord(size);
-#endif
-    ASSERT_EQUAL(stream->Position() - start, sizeof(elf::Symbol));
-  }
-
-  const intptr_t name_index;
-  const intptr_t binding;
-  const intptr_t type;
-  const intptr_t size;
-  // Is set twice: once in Elf::AddSection to the section's initial index into
-  // sections_, and then in Elf::FinalizeSymbols to the section's final index
-  // into sections_ after reordering.
-  intptr_t section_index;
-
- private:
-  static const intptr_t kNotFinalizedMarker = -1;
-
-  const char* const cstr_;
-  intptr_t offset_ = kNotFinalizedMarker;
-
-  friend class SymbolHashTable;  // For cstr_ access.
-};
-
 class SymbolTable : public Section {
  public:
   SymbolTable(Zone* zone, StringTable* table, bool dynamic)
@@ -568,6 +503,71 @@
   intptr_t FileSize() const { return Length() * entry_size; }
   intptr_t MemorySize() const { return dynamic_ ? FileSize() : 0; }
 
+  class Symbol : public ZoneAllocated {
+   public:
+    Symbol(const char* cstr,
+           intptr_t name,
+           intptr_t binding,
+           intptr_t type,
+           intptr_t initial_section_index,
+           intptr_t size)
+        : name_index(name),
+          binding(binding),
+          type(type),
+          size(size),
+          section_index(initial_section_index),
+          cstr_(cstr) {}
+
+    void Finalize(intptr_t final_section_index, intptr_t offset) {
+      ASSERT(!HasBeenFinalized());  // No symbol should be re-finalized.
+      section_index = final_section_index;
+      offset_ = offset;
+    }
+    bool HasBeenFinalized() const { return offset_ != kNotFinalizedMarker; }
+    intptr_t offset() const {
+      ASSERT(HasBeenFinalized());
+      // Only the reserved initial symbol should have an offset of 0.
+      ASSERT_EQUAL(type == elf::STT_NOTYPE, offset_ == 0);
+      return offset_;
+    }
+
+    void Write(ElfWriteStream* stream) const {
+      const intptr_t start = stream->Position();
+      stream->WriteWord(name_index);
+#if defined(TARGET_ARCH_IS_32_BIT)
+      stream->WriteAddr(offset());
+      stream->WriteWord(size);
+      stream->WriteByte(elf::SymbolInfo(binding, type));
+      stream->WriteByte(0);
+      stream->WriteHalf(section_index);
+#else
+      stream->WriteByte(elf::SymbolInfo(binding, type));
+      stream->WriteByte(0);
+      stream->WriteHalf(section_index);
+      stream->WriteAddr(offset());
+      stream->WriteXWord(size);
+#endif
+      ASSERT_EQUAL(stream->Position() - start, sizeof(elf::Symbol));
+    }
+
+    const intptr_t name_index;
+    const intptr_t binding;
+    const intptr_t type;
+    const intptr_t size;
+    // Is set twice: once in Elf::AddSection to the section's initial index into
+    // sections_, and then in Elf::FinalizeSymbols to the section's final index
+    // into sections_ after reordering.
+    intptr_t section_index;
+
+   private:
+    static const intptr_t kNotFinalizedMarker = -1;
+
+    const char* const cstr_;
+    intptr_t offset_ = kNotFinalizedMarker;
+
+    friend class SymbolHashTable;  // For cstr_ access.
+  };
+
   void Write(ElfWriteStream* stream) {
     for (intptr_t i = 0; i < Length(); i++) {
       auto const symbol = At(i);
@@ -875,28 +875,36 @@
       // Null symbols denote that the corresponding offset should be treated
       // as an absolute offset in the ELF memory space.
       if (reloc.source_symbol != nullptr) {
-        const Symbol* const source_symbol = symtab->Find(reloc.source_symbol);
-        ASSERT(source_symbol != nullptr);
-        source_address += source_symbol->offset();
+        if (strcmp(reloc.source_symbol, ".") == 0) {
+          source_address += memory_offset() + reloc.section_offset;
+        } else {
+          auto* const source_symbol = symtab->Find(reloc.source_symbol);
+          ASSERT(source_symbol != nullptr);
+          source_address += source_symbol->offset();
+        }
       }
       if (reloc.target_symbol != nullptr) {
-        const Symbol* const target_symbol = symtab->Find(reloc.target_symbol);
-        if (target_symbol == nullptr) {
-          ASSERT_EQUAL(strcmp(reloc.target_symbol, kSnapshotBuildIdAsmSymbol),
-                       0);
-          ASSERT_EQUAL(reloc.target_offset, 0);
-          ASSERT_EQUAL(reloc.source_offset, 0);
-          ASSERT_EQUAL(reloc.size_in_bytes, compiler::target::kWordSize);
-          // TODO(dartbug.com/43516): Special case for snapshots with deferred
-          // sections that handles the build ID relocation in an
-          // InstructionsSection when there is no build ID.
-          const word to_write = Image::kNoRelocatedAddress;
-          stream->WriteBytes(reinterpret_cast<const uint8_t*>(&to_write),
-                             reloc.size_in_bytes);
-          current_pos = reloc.section_offset + reloc.size_in_bytes;
-          continue;
+        if (strcmp(reloc.target_symbol, ".") == 0) {
+          target_address += memory_offset() + reloc.section_offset;
+        } else {
+          auto* const target_symbol = symtab->Find(reloc.target_symbol);
+          if (target_symbol == nullptr) {
+            ASSERT_EQUAL(strcmp(reloc.target_symbol, kSnapshotBuildIdAsmSymbol),
+                         0);
+            ASSERT_EQUAL(reloc.target_offset, 0);
+            ASSERT_EQUAL(reloc.source_offset, 0);
+            ASSERT_EQUAL(reloc.size_in_bytes, compiler::target::kWordSize);
+            // TODO(dartbug.com/43516): Special case for snapshots with deferred
+            // sections that handles the build ID relocation in an
+            // InstructionsSection when there is no build ID.
+            const word to_write = Image::kNoRelocatedAddress;
+            stream->WriteBytes(reinterpret_cast<const uint8_t*>(&to_write),
+                               reloc.size_in_bytes);
+            current_pos = reloc.section_offset + reloc.size_in_bytes;
+            continue;
+          }
+          target_address += target_symbol->offset();
         }
-        target_address += target_symbol->offset();
       }
       ASSERT(reloc.size_in_bytes <= kWordSize);
       const word to_write = target_address - source_address;
@@ -1074,7 +1082,7 @@
     stream_->SetPosition(fixup);
     u4(end - start);
     stream_->SetPosition(end);
-    return EncodedPosition(start);
+    return EncodedPosition(fixup);
   }
   // Shorthand for when working directly with DwarfElfStreams.
   intptr_t WritePrefixedLength(std::function<void()> body) {
@@ -1088,9 +1096,8 @@
     addr(0);  // Resolved later.
   }
   template <typename T>
-  void SizedOffsetFromSymbol(const char* symbol, intptr_t offset) {
-    relocations_->Add(
-        {sizeof(T), stream_->Position(), nullptr, 0, symbol, offset});
+  void RelativeSymbolOffset(const char* symbol) {
+    relocations_->Add({sizeof(T), stream_->Position(), ".", 0, symbol, 0});
     stream_->WriteFixed<T>(0);  // Resolved later.
   }
   void InitializeAbstractOrigins(intptr_t size) {
@@ -1137,7 +1144,7 @@
 #endif
 
 const Section* Elf::FindSectionBySymbolName(const char* name) const {
-  const Symbol* const symbol = symtab_->Find(name);
+  auto* const symbol = symtab_->Find(name);
   if (symbol == nullptr) return nullptr;
   // Should not be run between OrderSectionsAndCreateSegments (when section
   // indices may change) and FinalizeSymbols() (sets the final section index).
@@ -1212,10 +1219,8 @@
       // Offset to CIE. Note that unlike pcrel this offset is encoded
       // backwards: it will be subtracted from the current position.
       dwarf_stream.u4(stream.Position() - cie_start);
-      // Start address. 4 bytes because DW_EH_PE_sdata4 used in FDE encoding.
-      // Note: If (DW_EH_PE_pcrel | DW_EH_PE_absptr) can be used instead, we
-      // wouldn't need a special version of OffsetForSymbol just for this.
-      dwarf_stream.SizedOffsetFromSymbol<int32_t>(section->symbol_name, 0);
+      // Start address as a PC relative reference.
+      dwarf_stream.RelativeSymbolOffset<int32_t>(section->symbol_name);
       dwarf_stream.u4(section->MemorySize());  // Size.
       dwarf_stream.u1(0);                      // Augmentation Data length.
 
diff --git a/runtime/vm/elf.h b/runtime/vm/elf.h
index 035b487..c98f423 100644
--- a/runtime/vm/elf.h
+++ b/runtime/vm/elf.h
@@ -47,6 +47,8 @@
   // Stores the information needed to appropriately generate a
   // relocation from the target to the source at the given section offset.
   // If a given symbol is nullptr, then the offset is absolute (from 0).
+  // Both source and target symbols could be "." which is pseudosymbol
+  // corresponding to the location of the relocation itself.
   struct Relocation {
     size_t size_in_bytes;
     intptr_t section_offset;
diff --git a/runtime/vm/image_snapshot.cc b/runtime/vm/image_snapshot.cc
index 6be60de..bee78c8 100644
--- a/runtime/vm/image_snapshot.cc
+++ b/runtime/vm/image_snapshot.cc
@@ -914,17 +914,20 @@
   EncodedPosition WritePrefixedLength(const char* prefix,
                                       std::function<void()> body) {
     ASSERT(prefix != nullptr);
-    const char* const start_symbol = OS::SCreate(zone_, ".L%s_start", prefix);
+    const char* const length_prefix_symbol =
+        OS::SCreate(zone_, ".L%s_length_prefix", prefix);
     // Assignment to temp works around buggy Mac assembler.
-    stream_->Printf("L%s_size = .L%s_end - %s\n", prefix, prefix, start_symbol);
+    stream_->Printf("L%s_size = .L%s_end - .L%s_start\n", prefix, prefix,
+                    prefix);
     // We assume DWARF v2 currently, so all sizes are 32-bit.
-    stream_->Printf("%s L%s_size\n", kSizeDirectives[kInt32SizeLog2], prefix);
+    stream_->Printf("%s: %s L%s_size\n", length_prefix_symbol,
+                    kSizeDirectives[kInt32SizeLog2], prefix);
     // All sizes for DWARF sections measure the size of the section data _after_
     // the size value.
-    stream_->Printf("%s:\n", start_symbol);
+    stream_->Printf(".L%s_start:\n", prefix);
     body();
     stream_->Printf(".L%s_end:\n", prefix);
-    return EncodedPosition(start_symbol);
+    return EncodedPosition(length_prefix_symbol);
   }
   void OffsetFromSymbol(const char* symbol, intptr_t offset) {
     if (offset == 0) {
diff --git a/tools/VERSION b/tools/VERSION
index 3a978e0..70affaf 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 296
+PRERELEASE 297
 PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index 764fb58..0120f7e 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -633,8 +633,6 @@
         "csp": true,
         "timeout": 240,
         "dart2js-options": [
-          "--libraries-spec=sdk/lib/libraries.json",
-          "--platform-binaries=out/ReleaseX64/",
           "--merge-fragments-threshold=3",
           "--simple-load-ids"
         ]
@@ -662,8 +660,6 @@
         "timeout": 240,
         "builder-tag": "dart2js-weak",
         "dart2js-options": [
-          "--libraries-spec=sdk/lib/libraries.json",
-          "--platform-binaries=out/ReleaseX64/",
           "--merge-fragments-threshold=3",
           "--simple-load-ids"
         ]
@@ -715,11 +711,7 @@
       "options": {
         "host-checked": true,
         "timeout": 240,
-        "builder-tag": "dart2js-weak",
-        "dart2js-options": [
-          "--libraries-spec=sdk/lib/libraries.json",
-          "--platform-binaries=out/ReleaseX64/"
-        ]
+        "builder-tag": "dart2js-weak"
       }
     },
     "dart2js-hostasserts-weak-max-fragments-(linux|win)-x64-(d8|chrome)": {
@@ -728,8 +720,6 @@
         "timeout": 240,
         "builder-tag": "dart2js-weak",
         "dart2js-options": [
-          "--libraries-spec=sdk/lib/libraries.json",
-          "--platform-binaries=out/ReleaseX64/",
           "--merge-fragments-threshold=3",
           "--simple-load-ids"
         ]
@@ -739,22 +729,14 @@
       "options": {
         "host-checked": true,
         "timeout": 240,
-        "builder-tag": "dart2js-weak",
-        "dart2js-options": [
-          "--libraries-spec=sdk/lib/libraries.json",
-          "--platform-binaries=xcodebuild/ReleaseX64/"
-        ]
+        "builder-tag": "dart2js-weak"
       }
     },
     "dart2js-hostasserts-strong-(linux|win)-x64-(d8|chrome)": {
       "options": {
         "host-checked": true,
         "timeout": 240,
-        "builder-tag": "dart2js-strong",
-        "dart2js-options": [
-          "--libraries-spec=sdk/lib/libraries.json",
-          "--platform-binaries=out/ReleaseX64/"
-        ]
+        "builder-tag": "dart2js-strong"
       }
     },
     "dart2js-hostasserts-strong-max-fragments-(linux|win)-x64-(d8|chrome)": {
@@ -763,8 +745,6 @@
         "timeout": 240,
         "builder-tag": "dart2js-strong",
         "dart2js-options": [
-          "--libraries-spec=sdk/lib/libraries.json",
-          "--platform-binaries=out/ReleaseX64/",
           "--merge-fragments-threshold=3",
           "--simple-load-ids"
         ]
@@ -774,11 +754,7 @@
       "options": {
         "host-checked": true,
         "timeout": 240,
-        "builder-tag": "dart2js-strong",
-        "dart2js-options": [
-          "--libraries-spec=sdk/lib/libraries.json",
-          "--platform-binaries=xcodebuild/ReleaseX64/"
-        ]
+        "builder-tag": "dart2js-strong"
       }
     },
     "dartkp-android-(debug|product|release)-arm_x64": {