Skip to content

Commit fd2a9e7

Browse files
committed
Add "GC Zeal" infrastructure for additional, aggressive GC assertions
This initial commit just sets up the initial GC Zeal infrastructure, it doesn't actually start using it anywhere yet. * Adds support for `cfg(gc_zeal)` to `crates/wasmtime/build.rs` and `crates/cranelift/build.rs` * Defines `gc_assert!` macro * Defines `wasmtime_environ::gc::POISON` constant for GC heap poisoning * Adds debug assert that `POISON` doesn't overlap any valid `VMGcKind` discriminant * Adds CI job to run GC-related tests with `cfg(gc_zeal)`
1 parent 7e5d864 commit fd2a9e7

File tree

4 files changed

+71
-1
lines changed

4 files changed

+71
-1
lines changed

.github/workflows/main.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,35 @@ jobs:
663663
- run: cargo fuzz check --dev --fuzz-dir ./cranelift/assembler-x64/fuzz
664664
- run: cargo fuzz check --dev --fuzz-dir ./crates/wizer/fuzz
665665

666+
# Run GC-related tests with `cfg(gc_zeal)` set
667+
gc_zeal:
668+
needs: determine
669+
name: GC Zeal Tests
670+
runs-on: ubuntu-latest
671+
steps:
672+
- uses: actions/checkout@v6
673+
with:
674+
submodules: true
675+
- uses: ./.github/actions/install-rust
676+
- name: Run GC tests with cfg(gc_zeal) enabled
677+
env:
678+
GC_KEYWORDS: "gc drc any eq struct array i31 extern exn ref rec"
679+
RUSTFLAGS: "--cfg gc_zeal"
680+
run: |
681+
set -e
682+
683+
cargo test --test all -- $GC_KEYWORDS
684+
685+
# The wast test runner doesn't support multiple test filters. Instead,
686+
# make a list of all matches, and then run each individually.
687+
tmp=$(mktemp)
688+
for kw in $GC_KEYWORDS; do
689+
cargo test --test wast -- --list $kw | cut -d ':' -f 1 >> $tmp
690+
done
691+
for f in $(cat $tmp | sort -u); do
692+
cargo test --test wast -- $f
693+
done
694+
666695
# Perform all tests of the c-api
667696
test_capi:
668697
needs: determine

crates/cranelift/build.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
fn main() {
2+
println!("cargo:rerun-if-changed=build.rs");
3+
4+
// When enabled, `cfg(gc_zeal)` activates aggressive GC debugging
5+
// assertions.
6+
println!("cargo:rustc-check-cfg=cfg(gc_zeal)");
7+
}

crates/environ/src/gc.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,25 @@ use crate::{
2222
use alloc::sync::Arc;
2323
use core::alloc::Layout;
2424

25+
/// Poison byte written over unallocated GC heap memory when `cfg(gc_zeal)` is
26+
/// enabled.
27+
pub const POISON: u8 = 0xFF;
28+
29+
/// Assert a condition, but only when `gc_zeal` is enabled.
30+
#[macro_export]
31+
macro_rules! gc_assert {
32+
($cond:expr $(,)?) => {
33+
if cfg!(gc_zeal) {
34+
assert!($cond);
35+
}
36+
};
37+
($cond:expr, $($arg:tt)+) => {
38+
if cfg!(gc_zeal) {
39+
assert!($cond, $($arg)+);
40+
}
41+
};
42+
}
43+
2544
/// Discriminant to check whether GC reference is an `i31ref` or not.
2645
pub const I31_DISCRIMINANT: u32 = 1;
2746

@@ -485,15 +504,26 @@ impl VMGcKind {
485504
#[inline]
486505
pub fn from_high_bits_of_u32(val: u32) -> VMGcKind {
487506
let masked = val & Self::MASK;
488-
match masked {
507+
let result = match masked {
489508
x if x == Self::ExternRef.as_u32() => Self::ExternRef,
490509
x if x == Self::AnyRef.as_u32() => Self::AnyRef,
491510
x if x == Self::EqRef.as_u32() => Self::EqRef,
492511
x if x == Self::ArrayRef.as_u32() => Self::ArrayRef,
493512
x if x == Self::StructRef.as_u32() => Self::StructRef,
494513
x if x == Self::ExnRef.as_u32() => Self::ExnRef,
495514
_ => panic!("invalid `VMGcKind`: {masked:#032b}"),
515+
};
516+
517+
#[cfg(debug_assertions)]
518+
{
519+
let poison_kind = u32::from_le_bytes([POISON, POISON, POISON, POISON]) & VMGcKind::MASK;
520+
debug_assert_ne!(
521+
masked, poison_kind,
522+
"No valid `VMGcKind` should overlap with the poison pattern"
523+
);
496524
}
525+
526+
result
497527
}
498528

499529
/// Does this kind match the other kind?

crates/wasmtime/build.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ fn main() {
3535
custom_cfg("has_custom_sync", has_custom_sync);
3636
custom_cfg("has_host_compiler_backend", has_host_compiler_backend);
3737

38+
// When enabled, `cfg(gc_zeal)` activates aggressive GC debugging
39+
// assertions.
40+
println!("cargo:rustc-check-cfg=cfg(gc_zeal)");
41+
3842
// If this OS isn't supported and no debug-builtins or if Cranelift doesn't support
3943
// the host or there's no need to build these helpers.
4044
#[cfg(feature = "runtime")]

0 commit comments

Comments
 (0)