diff --git a/runtime/tests/vm/dart/gc/chunked_binary_trees_async_test.dart b/runtime/tests/vm/dart/gc/chunked_binary_trees_async_test.dart new file mode 100644 index 00000000000..d7b288422bf --- /dev/null +++ b/runtime/tests/vm/dart/gc/chunked_binary_trees_async_test.dart @@ -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 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); + } +} diff --git a/runtime/tests/vm/dart/gc/chunked_binary_trees_sync_star_test.dart b/runtime/tests/vm/dart/gc/chunked_binary_trees_sync_star_test.dart new file mode 100644 index 00000000000..b5781077530 --- /dev/null +++ b/runtime/tests/vm/dart/gc/chunked_binary_trees_sync_star_test.dart @@ -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 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); + } +}