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": {