mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 16:41:07 +00:00
[vm] Add tests for missing write barriers in SuspendState suspend and clone.
Bug: https://github.com/dart-lang/sdk/issues/54410 Change-Id: I86f105fcba7ab95f4d526ab0b468822f50b4e62b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/345568 Reviewed-by: Alexander Markov <alexmarkov@google.com> Commit-Queue: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
parent
78e5a3dd92
commit
a6edfb5904
125
runtime/tests/vm/dart/gc/chunked_binary_trees_async_test.dart
Normal file
125
runtime/tests/vm/dart/gc/chunked_binary_trees_async_test.dart
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
// Copyright (c) 2024, 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=
|
||||||
|
// VMOptions=--verify_store_buffer
|
||||||
|
// VMOptions=--verify_after_marking
|
||||||
|
// VMOptions=--runtime_allocate_old
|
||||||
|
// VMOptions=--runtime_allocate_spill_tlab
|
||||||
|
// VMOptions=--no_inline_alloc --runtime_allocate_spill_tlab
|
||||||
|
// VMOptions=--no_inline_alloc
|
||||||
|
|
||||||
|
// Stress test for write barrier elimination in SuspendState suspend.
|
||||||
|
|
||||||
|
class Node {
|
||||||
|
Node? left, right;
|
||||||
|
int depth;
|
||||||
|
Node(this.depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTopDown(Node n, int depth) async {
|
||||||
|
if (depth == 0) return;
|
||||||
|
|
||||||
|
Node l = new Node(depth);
|
||||||
|
Node ll = new Node(depth);
|
||||||
|
Node lr = new Node(depth);
|
||||||
|
Node r = new Node(depth);
|
||||||
|
Node rl = new Node(depth);
|
||||||
|
Node rr = new Node(depth);
|
||||||
|
n.left = l; // barrier
|
||||||
|
n.right = r; // barrier
|
||||||
|
l.left = ll; // no-barrier
|
||||||
|
l.right = lr; // no-barrier
|
||||||
|
r.left = rl; // no-barrier
|
||||||
|
r.right = rr; // no-barrier
|
||||||
|
|
||||||
|
var f1 = buildTopDown(ll, depth - 1);
|
||||||
|
var f2 = buildTopDown(lr, depth - 1);
|
||||||
|
await f1;
|
||||||
|
await f2;
|
||||||
|
var f3 = buildTopDown(rl, depth - 1);
|
||||||
|
var f4 = buildTopDown(rr, depth - 1);
|
||||||
|
await f3;
|
||||||
|
await f4;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkTopDown(Node n, int depth) async {
|
||||||
|
if (depth == 0) {
|
||||||
|
if (n.left != null) throw "Bad";
|
||||||
|
if (n.right != null) throw "Bad";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n.left!.depth != depth) throw "Bad";
|
||||||
|
if (n.left!.left!.depth != depth) throw "Bad";
|
||||||
|
if (n.left!.right!.depth != depth) throw "Bad";
|
||||||
|
if (n.right!.depth != depth) throw "Bad";
|
||||||
|
if (n.right!.right!.depth != depth) throw "Bad";
|
||||||
|
await checkTopDown(n.left!.left!, depth - 1);
|
||||||
|
await checkTopDown(n.left!.right!, depth - 1);
|
||||||
|
await checkTopDown(n.right!.left!, depth - 1);
|
||||||
|
await checkTopDown(n.right!.right!, depth - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
runTopDown(int depth) async {
|
||||||
|
Node n = new Node(depth);
|
||||||
|
await buildTopDown(n, depth);
|
||||||
|
await checkTopDown(n, depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Node> buildBottomUp(int depth) async {
|
||||||
|
if (depth == 0) {
|
||||||
|
return new Node(depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
var f1 = buildBottomUp(depth - 1);
|
||||||
|
var f2 = buildBottomUp(depth - 1);
|
||||||
|
Node ll = await f1;
|
||||||
|
Node lr = await f2;
|
||||||
|
var f3 = buildBottomUp(depth - 1);
|
||||||
|
var f4 = buildBottomUp(depth - 1);
|
||||||
|
Node rl = await f3;
|
||||||
|
Node rr = await f4;
|
||||||
|
|
||||||
|
Node l = new Node(depth);
|
||||||
|
Node r = new Node(depth);
|
||||||
|
Node n = new Node(depth);
|
||||||
|
|
||||||
|
n.left = l; // no-barrier
|
||||||
|
n.right = r; // no-barrier
|
||||||
|
l.left = ll; // no-barrier
|
||||||
|
l.right = lr; // no-barrier
|
||||||
|
r.left = rl; // no-barrier
|
||||||
|
r.right = rr; // no-barrier
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkButtomUp(Node n, int depth) async {
|
||||||
|
if (depth == 0) {
|
||||||
|
if (n.left != null) throw "Bad";
|
||||||
|
if (n.right != null) throw "Bad";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n.depth != depth) throw "Bad";
|
||||||
|
if (n.left!.depth != depth) throw "Bad";
|
||||||
|
if (n.right!.depth != depth) throw "Bad";
|
||||||
|
await checkButtomUp(n.left!.left!, depth - 1);
|
||||||
|
await checkButtomUp(n.left!.right!, depth - 1);
|
||||||
|
await checkButtomUp(n.right!.left!, depth - 1);
|
||||||
|
await checkButtomUp(n.right!.right!, depth - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
runBottomUp(int depth) async {
|
||||||
|
Node n = await buildBottomUp(depth);
|
||||||
|
await checkButtomUp(n, depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
main() async {
|
||||||
|
for (var i = 0; i < 5; i++) {
|
||||||
|
await runTopDown(10);
|
||||||
|
await runBottomUp(10);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
// Copyright (c) 2024, 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=
|
||||||
|
// VMOptions=--verify_store_buffer
|
||||||
|
// VMOptions=--verify_after_marking
|
||||||
|
// VMOptions=--runtime_allocate_old
|
||||||
|
// VMOptions=--runtime_allocate_spill_tlab
|
||||||
|
// VMOptions=--no_inline_alloc --runtime_allocate_spill_tlab
|
||||||
|
// VMOptions=--no_inline_alloc
|
||||||
|
|
||||||
|
// Stress test for write barrier elimination in SuspendState clone.
|
||||||
|
|
||||||
|
class Node {
|
||||||
|
Node? left, right;
|
||||||
|
int depth;
|
||||||
|
var retain;
|
||||||
|
Node(this.depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterable<Node> buildBottomUp(int depth) sync* {
|
||||||
|
for (;;) {
|
||||||
|
if (depth == 0) {
|
||||||
|
yield new Node(depth);
|
||||||
|
} else {
|
||||||
|
var i = buildBottomUp(depth - 1);
|
||||||
|
var i1 = i.iterator; // SuspendState.clone
|
||||||
|
i1.moveNext();
|
||||||
|
Node ll = i1.current;
|
||||||
|
var i2 = i.iterator; // SuspendState.clone
|
||||||
|
i2.moveNext();
|
||||||
|
Node lr = i2.current;
|
||||||
|
var i3 = i.iterator; // SuspendState.clone
|
||||||
|
i3.moveNext();
|
||||||
|
Node rl = i3.current;
|
||||||
|
var i4 = i.iterator; // SuspendState.clone
|
||||||
|
i4.moveNext();
|
||||||
|
Node rr = i4.current;
|
||||||
|
|
||||||
|
Node l = new Node(depth);
|
||||||
|
Node r = new Node(depth);
|
||||||
|
Node n = new Node(depth);
|
||||||
|
|
||||||
|
n.left = l; // no-barrier
|
||||||
|
n.right = r; // no-barrier
|
||||||
|
l.left = ll; // no-barrier
|
||||||
|
l.right = lr; // no-barrier
|
||||||
|
r.left = rl; // no-barrier
|
||||||
|
r.right = rr; // no-barrier
|
||||||
|
|
||||||
|
n.retain = i;
|
||||||
|
l.retain = i1;
|
||||||
|
r.retain = i2;
|
||||||
|
|
||||||
|
yield n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkButtomUp(Node n, int depth) {
|
||||||
|
if (depth == 0) {
|
||||||
|
if (n.left != null) throw "Bad";
|
||||||
|
if (n.right != null) throw "Bad";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n.depth != depth) throw "Bad";
|
||||||
|
if (n.left!.depth != depth) throw "Bad";
|
||||||
|
if (n.right!.depth != depth) throw "Bad";
|
||||||
|
checkButtomUp(n.left!.left!, depth - 1);
|
||||||
|
checkButtomUp(n.left!.right!, depth - 1);
|
||||||
|
checkButtomUp(n.right!.left!, depth - 1);
|
||||||
|
checkButtomUp(n.right!.right!, depth - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
runBottomUp(int depth) {
|
||||||
|
var i = buildBottomUp(depth).iterator;
|
||||||
|
i.moveNext();
|
||||||
|
Node n = i.current;
|
||||||
|
checkButtomUp(n, depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
for (var i = 0; i < 10; i++) {
|
||||||
|
runBottomUp(9);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue