diff --git a/runtime/tests/vm/dart/flutter_regress_106510_test.dart b/runtime/tests/vm/dart/flutter_regress_106510_test.dart new file mode 100644 index 00000000000..7c41c20d793 --- /dev/null +++ b/runtime/tests/vm/dart/flutter_regress_106510_test.dart @@ -0,0 +1,49 @@ +// 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. + +// VMOptions=--use_slow_path --stress_write_barrier_elimination + +// Test that array allocation in noSuchMethod dispatcher is preserving the +// length register correctly. + +import 'dart:async'; + +import 'package:expect/expect.dart'; + +final List list = []; + +final List invocations = []; + +abstract class B { + void someMethod(int v); +} + +class A { + noSuchMethod(Invocation i) { + Expect.equals(#someMethod, i.memberName); + invocations.add(i.positionalArguments[0] as int); + } +} + +class C implements B { + void someMethod(int v) { + invocations.add(v); + } +} + +void main() { + for (var i = 0; i < 10; i++) { + list.add(A()); + list.add(C()); + } + + for (var i = 0; i < list.length; i++) { + list[i].someMethod(i); + } + + Expect.equals(list.length, invocations.length); + for (var i = 0; i < list.length; i++) { + Expect.equals(i, invocations[i]); + } +} diff --git a/runtime/tests/vm/dart_2/flutter_regress_106510_test.dart b/runtime/tests/vm/dart_2/flutter_regress_106510_test.dart new file mode 100644 index 00000000000..5139e5783e8 --- /dev/null +++ b/runtime/tests/vm/dart_2/flutter_regress_106510_test.dart @@ -0,0 +1,50 @@ +// 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. +// @dart=2.9 + +// VMOptions=--use_slow_path --stress_write_barrier_elimination + +// Test that array allocation in noSuchMethod dispatcher is preserving the +// length register correctly. + +import 'dart:async'; + +import 'package:expect/expect.dart'; + +final List list = []; + +final List invocations = []; + +abstract class B { + void someMethod(int v); +} + +class A { + noSuchMethod(Invocation i) { + Expect.equals(#someMethod, i.memberName); + invocations.add(i.positionalArguments[0] as int); + } +} + +class C implements B { + void someMethod(int v) { + invocations.add(v); + } +} + +void main() { + for (var i = 0; i < 10; i++) { + list.add(A()); + list.add(C()); + } + + for (var i = 0; i < list.length; i++) { + list[i].someMethod(i); + } + + Expect.equals(list.length, invocations.length); + for (var i = 0; i < list.length; i++) { + Expect.equals(i, invocations[i]); + } +} diff --git a/runtime/vm/compiler/stub_code_compiler_arm.cc b/runtime/vm/compiler/stub_code_compiler_arm.cc index fc6b0ea553e..6f624566f02 100644 --- a/runtime/vm/compiler/stub_code_compiler_arm.cc +++ b/runtime/vm/compiler/stub_code_compiler_arm.cc @@ -46,7 +46,7 @@ void StubCodeCompiler::EnsureIsNewOrRemembered(Assembler* assembler, { LeafRuntimeScope rt(assembler, /*frame_size=*/0, - /*preserve_registers=*/false); + /*preserve_registers=*/preserve_registers); // [R0] already contains first argument. __ mov(R1, Operand(THR)); rt.Call(kEnsureRememberedAndMarkingDeferredRuntimeEntry, 2);