diff --git a/runtime/tests/vm/dart/regress_50065_test.dart b/runtime/tests/vm/dart/regress_50065_test.dart new file mode 100644 index 00000000000..48730611cd3 --- /dev/null +++ b/runtime/tests/vm/dart/regress_50065_test.dart @@ -0,0 +1,31 @@ +// Copyright (c) 2022, 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. + +// Regression test for https://github.com/dart-lang/sdk/issues/50065. +// Runs tests/language/generic/function_bounds_test.dart in multiple isolates +// in order to stress-test concurrent canonicalization of types. + +import 'dart:isolate'; + +import 'package:expect/expect.dart'; +import '../../../../tests/language/generic/function_bounds_test.dart' + as function_bounds_test; + +const int N = 100; + +void run(dynamic message) { + function_bounds_test.main(); +} + +void main() async { + final List ports = []; + final List isolates = []; + for (int i = 0; i < N; ++i) { + final rp = ReceivePort(); + isolates.add(Isolate.spawn(run, null, onExit: rp.sendPort)); + ports.add(rp); + } + await Future.wait(isolates); + await Future.wait(ports.map((p) => p.first)); +} diff --git a/runtime/tests/vm/dart_2/regress_50065_test.dart b/runtime/tests/vm/dart_2/regress_50065_test.dart new file mode 100644 index 00000000000..1a3514c5e51 --- /dev/null +++ b/runtime/tests/vm/dart_2/regress_50065_test.dart @@ -0,0 +1,33 @@ +// Copyright (c) 2022, 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. + +// Regression test for https://github.com/dart-lang/sdk/issues/50065. +// Runs tests/language_2/generic/function_bounds_test.dart in multiple isolates +// in order to stress-test concurrent canonicalization of types. + +// @dart = 2.9 + +import 'dart:isolate'; + +import 'package:expect/expect.dart'; +import '../../../../tests/language_2/generic/function_bounds_test.dart' + as function_bounds_test; + +const int N = 100; + +void run(dynamic message) { + function_bounds_test.main(); +} + +void main() async { + final List ports = []; + final List isolates = []; + for (int i = 0; i < N; ++i) { + final rp = ReceivePort(); + isolates.add(Isolate.spawn(run, null, onExit: rp.sendPort)); + ports.add(rp); + } + await Future.wait(isolates); + await Future.wait(ports.map((p) => p.first)); +} diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index b77df2f33da..97fb9d454e8 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -22047,7 +22047,11 @@ AbstractTypePtr TypeRef::Canonicalize(Thread* thread, TrailPtr trail) const { AbstractType& ref_type = AbstractType::Handle(type()); ASSERT(!ref_type.IsNull()); ref_type = ref_type.Canonicalize(thread, trail); - set_type(ref_type); + { + SafepointMutexLocker ml( + thread->isolate_group()->type_canonicalization_mutex()); + set_type(ref_type); + } return ptr(); }