Version 2.14.0-286.0.dev

Merge commit '2ea5507fc380bb1bc5b1375e446b84f55aa89538' into 'dev'
diff --git a/pkg/analyzer/test/verify_diagnostics_test.dart b/pkg/analyzer/test/verify_diagnostics_test.dart
index bc22b3b..648fbf0 100644
--- a/pkg/analyzer/test/verify_diagnostics_test.dart
+++ b/pkg/analyzer/test/verify_diagnostics_test.dart
@@ -448,7 +448,6 @@
     }
   }
 
-  @soloTest
   test_published() {
     // Verify that if _any_ error code is marked as having published docs then
     // _all_ codes with the same name are also marked that way.
diff --git a/runtime/platform/utils.h b/runtime/platform/utils.h
index 98f1a1c..a1d6b1b 100644
--- a/runtime/platform/utils.h
+++ b/runtime/platform/utils.h
@@ -229,12 +229,22 @@
     return value <= limit;
   }
 
-  // Check whether the magnitude of value fits in N bits, i.e., whether an
-  // (N+1)-bit sign-magnitude representation can hold value.
+  // Check whether the magnitude of value fits in N bits. This differs from
+  // IsInt(N + 1, value) only in that this returns false for the minimum value
+  // of a N+1 bit two's complement value.
+  //
+  // Primarily used for testing whether a two's complement value can be used in
+  // a place where the sign is replaced with a marker that says whether the
+  // magnitude is added or subtracted, e.g., the U bit (bit 23) in some ARM7
+  // instructions.
   template <typename T>
-  static inline bool IsAbsoluteUint(intptr_t N, T value) {
+  static inline bool MagnitudeIsUint(intptr_t N, T value) {
     ASSERT(N >= 1);
-    return IsInt(N + 1, value);
+    if constexpr (std::is_signed<T>::value) {
+      using Unsigned = typename std::make_unsigned<T>::type;
+      if (value < 0) return IsUint<Unsigned>(N, -value);
+    }
+    return IsUint(N, value);
   }
 
   static inline int32_t Low16Bits(int32_t value) {
diff --git a/runtime/vm/compiler/assembler/assembler_arm.cc b/runtime/vm/compiler/assembler/assembler_arm.cc
index 7cf8272..d285792 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm.cc
@@ -2336,19 +2336,20 @@
     case kUnsignedTwoBytes:
     case kWordPair: {
       *offset_mask = 0xff;
-      return Utils::IsAbsoluteUint(8, offset);  // Addressing mode 3.
+      return Utils::MagnitudeIsUint(8, offset);  // Addressing mode 3.
     }
     case kUnsignedByte:
     case kFourBytes:
     case kUnsignedFourBytes: {
       *offset_mask = 0xfff;
-      return Utils::IsAbsoluteUint(12, offset);  // Addressing mode 2.
+      return Utils::MagnitudeIsUint(12, offset);  // Addressing mode 2.
     }
     case kSWord:
     case kDWord: {
       *offset_mask = 0x3fc;  // Multiple of 4.
       // VFP addressing mode.
-      return (Utils::IsAbsoluteUint(10, offset) && Utils::IsAligned(offset, 4));
+      return (Utils::MagnitudeIsUint(10, offset) &&
+              Utils::IsAligned(offset, 4));
     }
     case kRegList: {
       *offset_mask = 0x0;
@@ -2369,20 +2370,21 @@
     case kUnsignedTwoBytes:
     case kWordPair: {
       *offset_mask = 0xff;
-      return Utils::IsAbsoluteUint(8, offset);  // Addressing mode 3.
+      return Utils::MagnitudeIsUint(8, offset);  // Addressing mode 3.
     }
     case kByte:
     case kUnsignedByte:
     case kFourBytes:
     case kUnsignedFourBytes: {
       *offset_mask = 0xfff;
-      return Utils::IsAbsoluteUint(12, offset);  // Addressing mode 2.
+      return Utils::MagnitudeIsUint(12, offset);  // Addressing mode 2.
     }
     case kSWord:
     case kDWord: {
       *offset_mask = 0x3fc;  // Multiple of 4.
       // VFP addressing mode.
-      return (Utils::IsAbsoluteUint(10, offset) && Utils::IsAligned(offset, 4));
+      return (Utils::MagnitudeIsUint(10, offset) &&
+              Utils::IsAligned(offset, 4));
     }
     case kRegList: {
       *offset_mask = 0x0;
diff --git a/runtime/vm/compiler/assembler/assembler_arm.h b/runtime/vm/compiler/assembler/assembler_arm.h
index 09162f4..c41b62d 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.h
+++ b/runtime/vm/compiler/assembler/assembler_arm.h
@@ -238,7 +238,7 @@
   }
 
   explicit Address(Register rn, int32_t offset = 0, Mode am = Offset) {
-    ASSERT(Utils::IsAbsoluteUint(12, offset));
+    ASSERT(Utils::MagnitudeIsUint(12, offset));
     kind_ = Immediate;
     if (offset < 0) {
       encoding_ = (am ^ (1 << kUShift)) | -offset;  // Flip U to adjust sign.
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
index 979db7e..b71c702 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
@@ -712,7 +712,7 @@
     } else {
       __ add(LR, DISPATCH_TABLE_REG,
              compiler::Operand(cid_reg, LSL, compiler::target::kWordSizeLog2));
-      if (!Utils::IsAbsoluteUint(12, offset)) {
+      if (!Utils::MagnitudeIsUint(12, offset)) {
         const intptr_t adjust = offset & -(1 << 12);
         __ AddImmediate(LR, LR, adjust);
         offset -= adjust;
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index 80aaa47..0c07ad2 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -1855,7 +1855,7 @@
   const intptr_t base_offset =
       (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag));
   const int64_t offset = index * scale + base_offset;
-  if (!Utils::IsAbsoluteUint(12, offset)) {
+  if (!Utils::MagnitudeIsUint(12, offset)) {
     return false;
   }
   if (compiler::Address::CanHoldImmediateOffset(is_load, cid, offset)) {
diff --git a/runtime/vm/datastream.cc b/runtime/vm/datastream.cc
index 6d398fe..8236bf2 100644
--- a/runtime/vm/datastream.cc
+++ b/runtime/vm/datastream.cc
@@ -10,8 +10,7 @@
 namespace dart {
 
 void BaseWriteStream::WriteTargetWord(word value) {
-  ASSERT(compiler::target::kBitsPerWord == kBitsPerWord ||
-         Utils::IsAbsoluteUint(compiler::target::kBitsPerWord, value));
+  ASSERT(Utils::IsInt(compiler::target::kBitsPerWord, value));
   WriteFixed(static_cast<compiler::target::word>(value));
 }
 
diff --git a/runtime/vm/image_snapshot.cc b/runtime/vm/image_snapshot.cc
index 658892b..715bd93 100644
--- a/runtime/vm/image_snapshot.cc
+++ b/runtime/vm/image_snapshot.cc
@@ -1207,8 +1207,7 @@
 }
 
 intptr_t AssemblyImageWriter::WriteTargetWord(word value) {
-  ASSERT(compiler::target::kBitsPerWord == kBitsPerWord ||
-         Utils::IsAbsoluteUint(compiler::target::kBitsPerWord, value));
+  ASSERT(Utils::IsInt(compiler::target::kBitsPerWord, value));
   // Padding is helpful for comparing the .S with --disassemble.
   assembly_stream_->Printf("%s 0x%.*" Px "\n", kWordDirective,
                            2 * compiler::target::kWordSize, value);
diff --git a/runtime/vm/utils_test.cc b/runtime/vm/utils_test.cc
index ba4e296..2b0369f 100644
--- a/runtime/vm/utils_test.cc
+++ b/runtime/vm/utils_test.cc
@@ -290,22 +290,26 @@
   EXPECT(!Utils::IsUint(32, 4294967296LL));
 }
 
-VM_UNIT_TEST_CASE(IsAbsoluteUint) {
-  EXPECT(Utils::IsAbsoluteUint(8, 16));
-  EXPECT(Utils::IsAbsoluteUint(8, 0));
-  EXPECT(Utils::IsAbsoluteUint(8, -128));
-  EXPECT(Utils::IsAbsoluteUint(8, 255));
-  EXPECT(!Utils::IsAbsoluteUint(8, 256));
-  EXPECT(Utils::IsAbsoluteUint(16, 16));
-  EXPECT(Utils::IsAbsoluteUint(16, 0));
-  EXPECT(Utils::IsAbsoluteUint(16, 65535));
-  EXPECT(Utils::IsAbsoluteUint(16, -32768));
-  EXPECT(!Utils::IsAbsoluteUint(16, 65536));
-  EXPECT(Utils::IsAbsoluteUint(32, 16LL));
-  EXPECT(Utils::IsAbsoluteUint(32, 0LL));
-  EXPECT(Utils::IsAbsoluteUint(32, -2147483648LL));
-  EXPECT(Utils::IsAbsoluteUint(32, 4294967295LL));
-  EXPECT(!Utils::IsAbsoluteUint(32, 4294967296LL));
+VM_UNIT_TEST_CASE(MagnitudeIsUint) {
+  EXPECT(Utils::MagnitudeIsUint(8, 16));
+  EXPECT(Utils::MagnitudeIsUint(8, 0));
+  EXPECT(Utils::MagnitudeIsUint(8, -128));
+  EXPECT(Utils::MagnitudeIsUint(8, 255));
+  EXPECT(!Utils::MagnitudeIsUint(8, 256));
+  EXPECT(Utils::MagnitudeIsUint(12, 4095));
+  EXPECT(Utils::MagnitudeIsUint(12, -4095));
+  EXPECT(!Utils::MagnitudeIsUint(12, 4096));
+  EXPECT(!Utils::MagnitudeIsUint(12, -4096));
+  EXPECT(Utils::MagnitudeIsUint(16, 16));
+  EXPECT(Utils::MagnitudeIsUint(16, 0));
+  EXPECT(Utils::MagnitudeIsUint(16, 65535));
+  EXPECT(Utils::MagnitudeIsUint(16, -32768));
+  EXPECT(!Utils::MagnitudeIsUint(16, 65536));
+  EXPECT(Utils::MagnitudeIsUint(32, 16LL));
+  EXPECT(Utils::MagnitudeIsUint(32, 0LL));
+  EXPECT(Utils::MagnitudeIsUint(32, -2147483648LL));
+  EXPECT(Utils::MagnitudeIsUint(32, 4294967295LL));
+  EXPECT(!Utils::MagnitudeIsUint(32, 4294967296LL));
 }
 
 VM_UNIT_TEST_CASE(LowBits) {
diff --git a/tools/VERSION b/tools/VERSION
index 51acfad..ef1b556 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 285
+PRERELEASE 286
 PRERELEASE_PATCH 0
\ No newline at end of file