1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
//! Cross-layer hooks upper tiers install into the value layer.
//!
//! Two consumers need to learn when a var is rebound:
//! - the JIT tier (`cljrs_compiler::jit`) marks the previous definition's
//! compiled native code *stale* and reclaims it at the next stop-the-world
//! safepoint (Phase 10.2 — code unloading);
//! - the IR tier (`cljrs_runtime::tiered`) invalidates cached lowerings of *other*
//! functions that specialized against the old definition (Phase 10.5 —
//! cross-defn region promotion).
//!
//! `cljrs-value` sits far below both in the dependency graph, so the coupling
//! is inverted through callbacks: each consumer registers one via
//! [`set_var_rebind_hook`], and [`Var::bind`](crate::types::Var::bind) invokes
//! all of them (through [`notify_var_rebind`]) whenever it overwrites an
//! existing binding. When no hook is registered the cost is one atomic flag
//! load.
use RwLock;
use ;
use crateValue;
/// Callback signature: `(old_value, new_value)`.
///
/// Called with the value being replaced and the value replacing it, so the
/// implementation can stale only the definitions that are genuinely going away
/// (an arity present in both `old` and `new` — e.g. rebinding a var to the same
/// function object — must not be staled).
type VarRebindHook = ;
static VAR_REBIND_HOOKS: = new;
static ANY_HOOK: AtomicBool = new;
/// Register a var-rebind hook. Multiple hooks may be registered (the JIT's
/// code unloading and the IR tier's cross-defn invalidation); each is called
/// on every rebind, in registration order.
/// Notify the registered hooks that a var holding `old` is being rebound to
/// `new`.
///
/// No-op (one atomic load) when no hook is installed. Called from
/// `Var::bind` only when an existing value is being replaced.
pub