Version 2.12.0-5.0.dev

Merge commit 'f7e678d71d711f175f0ac9cb878a88c46e515747' into 'dev'
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 9d133af..bfaf1df 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -262,47 +262,6 @@
     return []
 
 
-def _CheckTestPlan(input_api, output_api):
-    """Run test plan check.
-
-  Each change that touches specified directories in the checkout are required
-  to have TEST= line explaining how this change was validated.
-  """
-
-    DIRS = [
-        'runtime/vm',
-        'runtime/bin',
-        'runtime/lib',
-        'runtime/include',
-        'runtime/observatory',
-        'runtime/observatory_2',
-        'runtime/platform',
-        'pkg/vm',
-        'sdk/lib/_internal/vm',
-    ]
-
-    # Run only if directory was affected.
-    files = [f.LocalPath() for f in input_api.AffectedFiles()]
-    affected = filter(lambda dir: any(f.startswith(dir) for f in files), DIRS)
-    if len(affected) != 0 and input_api.change.tags.get('TEST', '') == '':
-        return [
-            output_api.PresubmitError('Change is missing TEST= line',
-                                      long_text="""
-When changing files in one of the following directories you
-must include TEST= line at the end of your change description.
-
-    %s
-
-This line is expected to explain in a free form the kind of testing
-that was performed to validate effect of the change. For example,
-it can list newly added tests or already existing tests which are assumed
-to cover the change.
-""" % ('    '.join(affected)))
-        ]
-
-    return []
-
-
 def _CheckClangTidy(input_api, output_api):
     """Run clang-tidy on VM changes."""
 
@@ -374,7 +333,6 @@
     results.extend(_CheckLayering(input_api, output_api))
     results.extend(_CheckClangTidy(input_api, output_api))
     results.extend(_CheckTestMatrixValid(input_api, output_api))
-    results.extend(_CheckTestPlan(input_api, output_api))
     results.extend(
         input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
     return results
diff --git a/pkg/analyzer/lib/src/dart/constant/value.dart b/pkg/analyzer/lib/src/dart/constant/value.dart
index 3b51c9d..c2ae7ca 100644
--- a/pkg/analyzer/lib/src/dart/constant/value.dart
+++ b/pkg/analyzer/lib/src/dart/constant/value.dart
@@ -1048,14 +1048,18 @@
         return IntState.UNKNOWN_VALUE;
       }
       double result = value / rightValue.toDouble();
-      return IntState(result.toInt());
+      if (result.isFinite) {
+        return IntState(result.toInt());
+      }
     } else if (rightOperand is DoubleState) {
       double rightValue = rightOperand.value;
       if (rightValue == null) {
         return IntState.UNKNOWN_VALUE;
       }
       double result = value / rightValue;
-      return IntState(result.toInt());
+      if (result.isFinite) {
+        return IntState(result.toInt());
+      }
     }
     throw EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
   }
@@ -1976,7 +1980,9 @@
         return UNKNOWN_VALUE;
       }
       double result = value.toDouble() / rightValue;
-      return IntState(result.toInt());
+      if (result.isFinite) {
+        return IntState(result.toInt());
+      }
     }
     throw EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
   }
diff --git a/pkg/analyzer/test/src/dart/constant/value_test.dart b/pkg/analyzer/test/src/dart/constant/value_test.dart
index 7c3ae1a..f9aa5a8 100644
--- a/pkg/analyzer/test/src/dart/constant/value_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/value_test.dart
@@ -834,6 +834,18 @@
     _assertIdentical(_boolValue(null), _stringValue(null), _stringValue("def"));
   }
 
+  void test_integerDivide_infinity_knownDouble() {
+    _assertIntegerDivide(
+      null,
+      _doubleValue(double.infinity),
+      _doubleValue(2.0),
+    );
+  }
+
+  void test_integerDivide_infinity_knownInt() {
+    _assertIntegerDivide(null, _doubleValue(double.infinity), _intValue(2));
+  }
+
   void test_integerDivide_knownDouble_knownDouble() {
     _assertIntegerDivide(_intValue(3), _doubleValue(6.0), _doubleValue(2.0));
   }
@@ -851,6 +863,10 @@
     _assertIntegerDivide(_intValue(null), _doubleValue(6.0), _intValue(null));
   }
 
+  void test_integerDivide_knownInt_knownDoubleZero() {
+    _assertIntegerDivide(null, _intValue(6), _doubleValue(0.0));
+  }
+
   void test_integerDivide_knownInt_knownInt() {
     _assertIntegerDivide(_intValue(3), _intValue(6), _intValue(2));
   }
@@ -867,10 +883,38 @@
     _assertIntegerDivide(_intValue(null), _intValue(6), _intValue(null));
   }
 
+  void test_integerDivide_knownInt_zero() {
+    _assertIntegerDivide(null, _intValue(2), _intValue(0));
+  }
+
   void test_integerDivide_knownString_knownInt() {
     _assertIntegerDivide(null, _stringValue("6"), _intValue(2));
   }
 
+  void test_integerDivide_NaN_knownDouble() {
+    _assertIntegerDivide(null, _doubleValue(double.nan), _doubleValue(2.0));
+  }
+
+  void test_integerDivide_NaN_knownInt() {
+    _assertIntegerDivide(null, _doubleValue(double.nan), _intValue(2));
+  }
+
+  void test_integerDivide_negativeInfinity_knownDouble() {
+    _assertIntegerDivide(
+      null,
+      _doubleValue(double.negativeInfinity),
+      _doubleValue(2.0),
+    );
+  }
+
+  void test_integerDivide_negativeInfinity_knownInt() {
+    _assertIntegerDivide(
+      null,
+      _doubleValue(double.negativeInfinity),
+      _intValue(2),
+    );
+  }
+
   void test_integerDivide_unknownDouble_knownDouble() {
     _assertIntegerDivide(
         _intValue(null), _doubleValue(null), _doubleValue(2.0));
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index bcb3306..6ae6804 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -504,7 +504,7 @@
 
   Fragment code;
   code += LoadLocal(async_stack_trace_var);
-  // Call _asyncSetThreadStackTrace
+  // Call _setAsyncThreadStackTrace
   code += StaticCall(TokenPosition::kNoSource, target,
                      /* argument_count = */ 1, ICData::kStatic);
   code += Drop();
diff --git a/runtime/vm/lockers.h b/runtime/vm/lockers.h
index 0090ccc..5d40791 100644
--- a/runtime/vm/lockers.h
+++ b/runtime/vm/lockers.h
@@ -352,7 +352,7 @@
     if (IsCurrentThreadWriter()) {
       return false;
     }
-    while (state_ == -1) {
+    while (state_ < 0) {
       ml.Wait();
     }
 #if defined(DEBUG)
@@ -407,7 +407,7 @@
   Monitor monitor_;
   // [state_] > 0  : The lock is held by multiple readers.
   // [state_] == 0 : The lock is free (no readers/writers).
-  // [state_] == -1: The lock is held by a single writer.
+  // [state_] < 0  : The lock is held by a single writer (possibly nested).
   intptr_t state_ = 0;
 
 #if defined(DEBUG)
diff --git a/runtime/vm/thread_test.cc b/runtime/vm/thread_test.cc
index 4ea5308..048cda9 100644
--- a/runtime/vm/thread_test.cc
+++ b/runtime/vm/thread_test.cc
@@ -1027,4 +1027,65 @@
   EXPECT(!lock.IsCurrentThreadWriter());
 }
 
+struct ReaderThreadState {
+  ThreadJoinId reader_id = OSThread::kInvalidThreadJoinId;
+  SafepointRwLock* rw_lock = nullptr;
+  IsolateGroup* isolate_group = nullptr;
+  intptr_t elapsed_us = 0;
+};
+
+void Helper(uword arg) {
+  auto state = reinterpret_cast<ReaderThreadState*>(arg);
+  state->reader_id = OSThread::GetCurrentThreadJoinId(OSThread::Current());
+
+  const bool kBypassSafepoint = false;
+  Thread::EnterIsolateGroupAsHelper(state->isolate_group, Thread::kUnknownTask,
+                                    kBypassSafepoint);
+  {
+    auto thread = Thread::Current();
+    const auto before_us = OS::GetCurrentMonotonicMicros();
+    intptr_t after_us = before_us;
+    {
+      SafepointReadRwLocker reader(thread, state->rw_lock);
+      after_us = OS::GetCurrentMonotonicMicros();
+    }
+    state->elapsed_us = (after_us - before_us);
+  }
+  Thread::ExitIsolateGroupAsHelper(kBypassSafepoint);
+}
+
+ISOLATE_UNIT_TEST_CASE(SafepointRwLockExclusiveNestedWriter_Regress44000) {
+  auto isolate_group = IsolateGroup::Current();
+
+  SafepointRwLock lock;
+  ReaderThreadState state;
+  state.rw_lock = &lock;
+  state.isolate_group = isolate_group;
+  {
+    // Hold one writer lock.
+    SafepointWriteRwLocker locker(Thread::Current(), &lock);
+    {
+      // Hold another, nested, writer lock.
+      SafepointWriteRwLocker locker2(Thread::Current(), &lock);
+
+      // Start a thread, it will try to acquire read lock but it will have to
+      // wait until we have exited both writer scopes.
+      if (OSThread::Start("DartWorker", &Helper,
+                          reinterpret_cast<uword>(&state)) != 0) {
+        FATAL("Could not start worker thread");
+      }
+      // Give thread a little time to actually start running.
+      OS::Sleep(20);
+
+      OS::Sleep(500);
+    }
+    OS::Sleep(500);
+  }
+  // Join the other thread.
+  OSThread::Join(state.reader_id);
+
+  // Ensure the reader thread had to wait for around 1 second.
+  EXPECT(state.elapsed_us > 2 * 500 * 1000);
+}
+
 }  // namespace dart
diff --git a/tests/dart2js/boolean_conversion_test.dart b/tests/dart2js/boolean_conversion_test.dart
deleted file mode 100644
index 48c1cb6..0000000
--- a/tests/dart2js/boolean_conversion_test.dart
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// dart2jsOptions=--omit-implicit-checks
-
-// Note: --omit-implicit-checks causes Expect.isNull to misbehave, so we use
-// Expect.equals(null, ...) instead.
-
-import 'package:expect/expect.dart';
-
-void main() {
-  conditionalTest();
-  orTest();
-  andTest();
-  ifTest();
-  forTest();
-  whileTest();
-  doTest();
-  notTest();
-  ifElementTest();
-  forElementTest();
-}
-
-void conditionalTest() {
-  bool x = null as dynamic;
-  Expect.isFalse(x ? true : false);
-}
-
-void orTest() {
-  bool x = null as dynamic;
-  Expect.equals(null, x || x);
-  Expect.isFalse(x || false);
-  Expect.isTrue(x || true);
-  Expect.equals(null, false || x);
-  Expect.isTrue(true || x);
-}
-
-void andTest() {
-  bool x = null as dynamic;
-  Expect.isFalse(x && x);
-  Expect.isFalse(x && false);
-  Expect.isFalse(x && true);
-  Expect.isFalse(false && x);
-  Expect.equals(null, true && x);
-}
-
-void ifTest() {
-  bool x = null as dynamic;
-  Expect.isFalse(() {
-    if (x) {
-      return true;
-    } else {
-      return false;
-    }
-  }());
-}
-
-void forTest() {
-  bool x = null as dynamic;
-  Expect.isFalse(() {
-    for (; x;) {
-      return true;
-    }
-    return false;
-  }());
-}
-
-void whileTest() {
-  bool x = null as dynamic;
-  Expect.isFalse(() {
-    while (x) {
-      return true;
-    }
-    return false;
-  }());
-}
-
-void doTest() {
-  bool x = null as dynamic;
-  Expect.equals(1, () {
-    int n = 0;
-    do {
-      n++;
-    } while (x);
-    return n;
-  }());
-}
-
-void notTest() {
-  bool x = null as dynamic;
-  Expect.isTrue(!x);
-}
-
-void ifElementTest() {
-  bool x = null as dynamic;
-  Expect.listEquals([], [if (x) 1]);
-}
-
-void forElementTest() {
-  bool x = null as dynamic;
-  Expect.listEquals([], [for (var i = 0; x; i++) i]);
-}
diff --git a/tests/language/least_upper_bound/least_upper_bound_function_test.dart b/tests/language/least_upper_bound/least_upper_bound_function_test.dart
index a08bfb9..43012cff 100644
--- a/tests/language/least_upper_bound/least_upper_bound_function_test.dart
+++ b/tests/language/least_upper_bound/least_upper_bound_function_test.dart
@@ -37,10 +37,10 @@
 
   void f5(Function Function<Y>([Y y]) x, dynamic y) {
     var z = condition ? x : y;
-    // Check that the type is a top type.
-    z.expectStaticType<Exactly<dynamic>>();
-    // Check that the type is `dynamic`.
-    z.unknownMember;
+    // Check that the type of `z` is `dynamic`.
+    Never n = z; // It is `dynamic` or `Never`.
+    z = 0; // It is a supertype of `int`.
+    z = false; // It is a supertype of `bool`.
   }
 
   void f6(Never x, Never Function() y) {
diff --git a/tests/language/least_upper_bound/least_upper_bound_futureor_test.dart b/tests/language/least_upper_bound/least_upper_bound_futureor_test.dart
index 02569eb..82cace6 100644
--- a/tests/language/least_upper_bound/least_upper_bound_futureor_test.dart
+++ b/tests/language/least_upper_bound/least_upper_bound_futureor_test.dart
@@ -206,16 +206,16 @@
 
   void f20(dynamic a, FutureOr<void> b) {
     var x = condition ? a : b;
-    // Verify that the type of `x` is a top type.
-    x.expectStaticType<Exactly<dynamic>>();
-    // Verify that it is `dynamic`.
-    x.unknownMember();
+    // Verify that the type of `x` is `dynamic`.
+    Never n = x; // It is `dynamic` or `Never`.
+    x = 0; // It is a supertype of `int`.
+    x = false; // It is a supertype of `bool`.
 
     var y = condition ? b : a;
-    // Verify that the type of `y` is a top type.
-    y.expectStaticType<Exactly<dynamic>>();
-    // Verify that it is `dynamic`.
-    y.unknownMember();
+    // Verify that the type of `y` is `dynamic`.
+    n = y;
+    y = 0;
+    y = false;
   }
 
   void f21(A a, B b) {
diff --git a/tools/VERSION b/tools/VERSION
index 7858ce1..0da300e 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 12
 PATCH 0
-PRERELEASE 4
+PRERELEASE 5
 PRERELEASE_PATCH 0
\ No newline at end of file