diff --git a/changelog.d/9781-census-hot-tls.md b/changelog.d/9781-census-hot-tls.md new file mode 100644 index 0000000000..2d4e53bb33 --- /dev/null +++ b/changelog.d/9781-census-hot-tls.md @@ -0,0 +1,10 @@ +**The GC census thread-locals no longer pay `_tlv_get_addr`.** `gc::census` +is compiled unconditionally, so its two ungated `thread_local!` blocks were +in shipping builds and cost an out-of-line libdyld call per access on Darwin +— including the `ARMED` flag that gates whether the census does anything at +all. Both now use `crate::perry_thread_local!`, the same treatment the four +other recent declarations received; every call site already went through +`.with()`, so nothing else changed. + +This also restores the `self-test-checkers` job, whose thread-local policy +ratchet (#7469) had been failing on main and on every open PR. diff --git a/crates/perry-runtime/src/gc/census.rs b/crates/perry-runtime/src/gc/census.rs index 891035533f..aea37815e6 100644 --- a/crates/perry-runtime/src/gc/census.rs +++ b/crates/perry-runtime/src/gc/census.rs @@ -43,7 +43,7 @@ static SIGNAL_PENDING: AtomicBool = AtomicBool::new(false); static SIGNAL_INSTALLED: AtomicBool = AtomicBool::new(false); static MAIN_THREAD: OnceLock = OnceLock::new(); -thread_local! { +crate::perry_thread_local! { static ARMED: Cell = const { Cell::new(false) }; static SEQ: Cell = const { Cell::new(0) }; static LABEL: RefCell<&'static str> = const { RefCell::new("manual") }; @@ -177,7 +177,7 @@ fn census_service_signal() { super::js_gc_collect(); } -thread_local! { +crate::perry_thread_local! { /// Pass-1 snapshot: sorted header addresses that were marked when mark /// propagation finished (see the module docs). static PASS1_MARKED: RefCell>> = const { RefCell::new(None) };