Skip to content

Commit

Permalink
[vm, gc] Add flag to disable write barrier elimination.
Browse files Browse the repository at this point in the history
TEST=ci
Change-Id: Ibf1c8afc21c695c1e959ee7463110dd2c37ed846
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/311822
Reviewed-by: Siva Annamalai <asiva@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
  • Loading branch information
rmacnak-google authored and Commit Queue committed Jul 12, 2023
1 parent d718ab5 commit d486c52
Show file tree
Hide file tree
Showing 15 changed files with 253 additions and 1 deletion.
121 changes: 121 additions & 0 deletions runtime/tests/vm/dart/gc/chunked_binary_trees_array_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
// Copyright (c) 2023, 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=--stress_write_barrier_elimination
// VMOptions=--no_eliminate_write_barriers
// VMOptions=--no_inline_alloc

buildTopDown(List n, int depth) {
if (depth == 0) return;

List l = new List<dynamic>.filled(3, null);
l[2] = depth; // no-barrier
List ll = new List<dynamic>.filled(3, null);
ll[2] = depth; // no-barrier
List lr = new List<dynamic>.filled(3, null);
lr[2] = depth; // no-barrier
List r = new List<dynamic>.filled(3, null);
r[2] = depth; // no-barrier
List rl = new List<dynamic>.filled(3, null);
rl[2] = depth; // no-barrier
List rr = new List<dynamic>.filled(3, null);
rr[2] = depth; // no-barrier

n[0] = l; // barrier
n[1] = r; // barrier
l[0] = ll; // no-barrier
l[1] = lr; // no-barrier
r[0] = rl; // no-barrier
r[1] = rr; // no-barrier

buildTopDown(ll, depth - 1);
buildTopDown(lr, depth - 1);
buildTopDown(rl, depth - 1);
buildTopDown(rr, depth - 1);
}

checkTopDown(List n, int depth) {
if (depth == 0) {
if (n[0] != null) throw "Bad";
if (n[1] != null) throw "Bad";
return;
}

if (n[0][2] != depth) throw "Bad";
if (n[0][0][2] != depth) throw "Bad";
if (n[0][1][2] != depth) throw "Bad";
if (n[1][2] != depth) throw "Bad";
if (n[1][1][2] != depth) throw "Bad";
checkTopDown(n[0][0]!, depth - 1);
checkTopDown(n[0][1]!, depth - 1);
checkTopDown(n[1][0]!, depth - 1);
checkTopDown(n[1][1]!, depth - 1);
}

runTopDown() {
List n = new List<dynamic>.filled(3, null);
n[2] = 10;
buildTopDown(n, 10);
checkTopDown(n, 10);
}

List buildBottomUp(int depth) {
if (depth == 0) {
var n = new List<dynamic>.filled(3, null);
n[2] = depth;
return n;
}

List ll = buildBottomUp(depth - 1);
List lr = buildBottomUp(depth - 1);
List rl = buildBottomUp(depth - 1);
List rr = buildBottomUp(depth - 1);

List l = new List<dynamic>.filled(3, null);
l[2] = depth; // no-barrier
List r = new List<dynamic>.filled(3, null);
r[2] = depth; // no-barrier
List n = new List<dynamic>.filled(3, null);
n[2] = depth; // no-barrier

n[0] = l; // no-barrier
n[1] = r; // no-barrier
l[0] = ll; // no-barrier
l[1] = lr; // no-barrier
r[0] = rl; // no-barrier
r[1] = rr; // no-barrier

return n;
}

checkButtomUp(List n, int depth) {
if (depth == 0) {
if (n[0] != null) throw "Bad";
if (n[1] != null) throw "Bad";
return;
}

if (n[2] != depth) throw "Bad";
if (n[0][2] != depth) throw "Bad";
if (n[1][2] != depth) throw "Bad";
checkButtomUp(n[0][0]!, depth - 1);
checkButtomUp(n[0][1]!, depth - 1);
checkButtomUp(n[1][0]!, depth - 1);
checkButtomUp(n[1][1]!, depth - 1);
}

runBottomUp() {
List n = buildBottomUp(10);
checkButtomUp(n, 10);
}

main() {
for (var i = 0; i < 10; i++) {
runTopDown();
runBottomUp();
}
}
114 changes: 114 additions & 0 deletions runtime/tests/vm/dart/gc/chunked_binary_trees_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// Copyright (c) 2023, 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=--stress_write_barrier_elimination
// VMOptions=--no_eliminate_write_barriers
// VMOptions=--no_inline_alloc

class Node {
Node? left, right;
int depth;
Node(this.depth);
}

buildTopDown(Node n, int depth) {
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

buildTopDown(ll, depth - 1);
buildTopDown(lr, depth - 1);
buildTopDown(rl, depth - 1);
buildTopDown(rr, depth - 1);
}

checkTopDown(Node n, int depth) {
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";
checkTopDown(n.left!.left!, depth - 1);
checkTopDown(n.left!.right!, depth - 1);
checkTopDown(n.right!.left!, depth - 1);
checkTopDown(n.right!.right!, depth - 1);
}

runTopDown() {
Node n = new Node(10);
buildTopDown(n, 10);
checkTopDown(n, 10);
}

Node buildBottomUp(int depth) {
if (depth == 0) {
return new Node(depth);
}

Node ll = buildBottomUp(depth - 1);
Node lr = buildBottomUp(depth - 1);
Node rl = buildBottomUp(depth - 1);
Node rr = buildBottomUp(depth - 1);

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) {
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() {
Node n = buildBottomUp(10);
checkButtomUp(n, 10);
}

main() {
for (var i = 0; i < 10; i++) {
runTopDown();
runBottomUp();
}
}
1 change: 1 addition & 0 deletions runtime/tests/vm/dart/gc/splay_c_finalizer_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
// VMOptions=--verify_store_buffer
// VMOptions=--verify_after_marking
// VMOptions=--stress_write_barrier_elimination
// VMOptions=--no_eliminate_write_barriers
// VMOptions=--no_inline_alloc
// VMOptions=--old_gen_heap_size=150

Expand Down
1 change: 1 addition & 0 deletions runtime/tests/vm/dart/gc/splay_dart_finalizer_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
// VMOptions=--verify_store_buffer
// VMOptions=--verify_after_marking
// VMOptions=--stress_write_barrier_elimination
// VMOptions=--no_eliminate_write_barriers
// VMOptions=--no_inline_alloc
// VMOptions=--old_gen_heap_size=150

Expand Down
1 change: 1 addition & 0 deletions runtime/tests/vm/dart/gc/splay_ephemeron_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
// VMOptions=--verify_store_buffer
// VMOptions=--verify_after_marking
// VMOptions=--stress_write_barrier_elimination
// VMOptions=--no_eliminate_write_barriers
// VMOptions=--no_inline_alloc
// VMOptions=--old_gen_heap_size=150

Expand Down
1 change: 1 addition & 0 deletions runtime/tests/vm/dart/gc/splay_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
// VMOptions=--profiler --verify_store_buffer
// VMOptions=--profiler --verify_after_marking
// VMOptions=--profiler --stress_write_barrier_elimination
// VMOptions=--profiler --no_eliminate_write_barriers
// VMOptions=--profiler --no_inline_alloc
// VMOptions=--profiler --old_gen_heap_size=100
// VMOptions=--profiler --mark_when_idle
Expand Down
1 change: 1 addition & 0 deletions runtime/tests/vm/dart/gc/splay_weak_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
// VMOptions=--verify_store_buffer
// VMOptions=--verify_after_marking
// VMOptions=--stress_write_barrier_elimination
// VMOptions=--no_eliminate_write_barriers
// VMOptions=--no_inline_alloc
// VMOptions=--old_gen_heap_size=150

Expand Down
1 change: 1 addition & 0 deletions runtime/tests/vm/dart_2/gc/splay_c_finalizer_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
// VMOptions=--verify_store_buffer
// VMOptions=--verify_after_marking
// VMOptions=--stress_write_barrier_elimination
// VMOptions=--no_eliminate_write_barriers
// VMOptions=--no_inline_alloc
// VMOptions=--old_gen_heap_size=150

Expand Down
1 change: 1 addition & 0 deletions runtime/tests/vm/dart_2/gc/splay_dart_finalizer_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
// VMOptions=--verify_store_buffer
// VMOptions=--verify_after_marking
// VMOptions=--stress_write_barrier_elimination
// VMOptions=--no_eliminate_write_barriers
// VMOptions=--no_inline_alloc
// VMOptions=--old_gen_heap_size=150

Expand Down
1 change: 1 addition & 0 deletions runtime/tests/vm/dart_2/gc/splay_ephemeron_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
// VMOptions=--verify_store_buffer
// VMOptions=--verify_after_marking
// VMOptions=--stress_write_barrier_elimination
// VMOptions=--no_eliminate_write_barriers
// VMOptions=--no_inline_alloc
// VMOptions=--old_gen_heap_size=150

Expand Down
1 change: 1 addition & 0 deletions runtime/tests/vm/dart_2/gc/splay_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
// VMOptions=--profiler --verify_store_buffer
// VMOptions=--profiler --verify_after_marking
// VMOptions=--profiler --stress_write_barrier_elimination
// VMOptions=--profiler --no_eliminate_write_barriers
// VMOptions=--profiler --no_inline_alloc
// VMOptions=--profiler --old_gen_heap_size=100
// VMOptions=--profiler --mark_when_idle
Expand Down
1 change: 1 addition & 0 deletions runtime/tests/vm/dart_2/gc/splay_weak_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
// VMOptions=--verify_store_buffer
// VMOptions=--verify_after_marking
// VMOptions=--stress_write_barrier_elimination
// VMOptions=--no_eliminate_write_barriers
// VMOptions=--no_inline_alloc
// VMOptions=--old_gen_heap_size=150

Expand Down
6 changes: 5 additions & 1 deletion runtime/vm/compiler/compiler_pass.cc
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,11 @@ COMPILER_PASS(ReorderBlocks, {
}
});

COMPILER_PASS(EliminateWriteBarriers, { EliminateWriteBarriers(flow_graph); });
COMPILER_PASS(EliminateWriteBarriers, {
if (FLAG_eliminate_write_barriers) {
EliminateWriteBarriers(flow_graph);
}
});

COMPILER_PASS(FinalizeGraph, {
// At the end of the pipeline, force recomputing and caching graph
Expand Down
2 changes: 2 additions & 0 deletions runtime/vm/flag_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,8 @@ constexpr bool FLAG_support_il_printer = false;
"Enable magical pragmas for testing purposes. Use at your own risk!") \
R(eliminate_type_checks, true, bool, true, \
"Eliminate type checks when allowed by static type analysis.") \
P(eliminate_write_barriers, bool, true, \
"Eliminate write barriers when allowed by allocation invariants.") \
D(support_rr, bool, false, "Support running within RR.") \
P(verify_entry_points, bool, false, \
"Throw API error on invalid member access through native API. See " \
Expand Down
1 change: 1 addition & 0 deletions runtime/vm/thread.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1023,6 +1023,7 @@ class RestoreWriteBarrierInvariantVisitor : public ObjectPointerVisitor {
void Thread::RestoreWriteBarrierInvariant(RestoreWriteBarrierInvariantOp op) {
ASSERT(IsAtSafepoint() || OwnsGCSafepoint());
ASSERT(IsDartMutatorThread());
if (!FLAG_eliminate_write_barriers) return;

const StackFrameIterator::CrossThreadPolicy cross_thread_policy =
StackFrameIterator::kAllowCrossThreadIteration;
Expand Down

0 comments on commit d486c52

Please sign in to comment.