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