Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,18 @@ Generational mark-sweep GC in `crates/perry-runtime/src/gc.rs` (default since v0

**Escape hatches**: `PERRY_GEN_GC=0`/`off`/`false` reverts to full mark-sweep (bisection only). `PERRY_GEN_GC_EVACUATE=0`/`off`/`false` disables policy evacuation; `=1`/`on`/`true` is accepted as auto-policy allowed, not unconditional evacuation. `PERRY_GC_FORCE_EVACUATE=1` stress-copies every marked non-pinned nursery object only when generated write barriers are active and policy evacuation is allowed. `PERRY_GC_VERIFY_EVACUATION=1` panics if any mutable live slot still points at a forwarded nursery object after an evacuation/rewrite cycle. `PERRY_WRITE_BARRIERS=0`/`off`/`false` disables codegen-emitted write barriers at compile time and runtime exact helper barriers at runtime for benchmark/debug bisection; unset, `=1`/`on`/`true` keep barriers enabled. `PERRY_GC_DIAG=1` prints per-cycle diagnostics, including evacuation-policy decisions for considered cycles and `barriers_inactive` skips.

### GC knob kill-policy (binding)

**Every GC env knob either has a required CI arm exercising its OFF state, or it is deleted after one release of soak.** At most one diagnostic-only knob may exist at a time, and it must be labelled untested.

This is not tidiness. An unexercised mode is a configuration nobody has verified, and this project has repeatedly paid for that:

- `PERRY_GC_FORCE_EVACUATE` was **inert** for every `gc()`-driven test — it is read only on the minor path, while `gc()` runs a full mark-sweep with a forced conservative scan (#6942/#6946). Months of "passes under evacuation" meant nothing.
- The matrix's `--pressure` knob **disabled the very path it was measuring** — the defer hard cap and the arena-trigger ceiling shared a formula and collapsed together, so the `default` arm ran zero copying minors on all 22 rows (#7024).
- `gc_incremental_enabled`'s doc said "EXPERIMENTAL — default OFF" eight lines above a body comment saying "DEFAULT ON" (#6987). A merge decision was made on the wrong one.

**A mode that still exists is a decision that hasn't been made.** When a knob's off-state stops being exercised, delete the off-state and the branch behind it — the losing mode should stop compiling, not linger as an untested configuration that a future bisect will trust.

## Threading (`perry/thread`)

Single-threaded by default. `perry/thread` provides:
Expand Down
8 changes: 8 additions & 0 deletions changelog.d/7042-lint-fmt-backlog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Applied `cargo fmt` to four files that had drifted out of rustfmt compliance on
`main`: `lower_call/native/mod.rs`, `global_this/install_static.rs`,
`commands/check.rs`, and `commands/deps.rs`.

Pure formatting — line breaking only, no semantic change. These were failing the
`lint` gate's `cargo fmt --all -- --check` step, which sits behind the stale
public-benchmark-baseline step and so was invisible until the baseline failure
was investigated.
5 changes: 1 addition & 4 deletions crates/perry-codegen/src/lower_call/native/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -409,10 +409,7 @@ pub(crate) fn lower_native_method_call(
blk.call(
DOUBLE,
"js_node_submodule_namespace",
&[
(PTR, &submod_label),
(I32, &submod_key.len().to_string()),
],
&[(PTR, &submod_label), (I32, &submod_key.len().to_string())],
)
};
let mut lowered_args: Vec<String> = Vec::with_capacity(args.len());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -899,7 +899,11 @@ pub(crate) fn install_reflect_namespace_members(ns_obj: *mut ObjectHeader) {
1,
),
("set", reflect_set_thunk as *const u8, 3),
("setPrototypeOf", reflect_set_prototype_of_thunk as *const u8, 2),
(
"setPrototypeOf",
reflect_set_prototype_of_thunk as *const u8,
2,
),
];
for (name, func_ptr, arity) in methods {
install_proto_method(ns_obj, name, func_ptr, arity);
Expand Down
6 changes: 5 additions & 1 deletion crates/perry/src/commands/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,10 @@ mod tests {
let mut walked =
collect_ts_files(&dir.path().to_path_buf()).expect("collect from directory input");
walked.sort();
assert_eq!(walked, vec![main, other], "directory input walks all sources");
assert_eq!(
walked,
vec![main, other],
"directory input walks all sources"
);
}
}
5 changes: 1 addition & 4 deletions crates/perry/src/commands/deps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -819,10 +819,7 @@ mod tests {
/// found" because the full specifier was joined as a path).
#[test]
fn package_base_name_splits_scoped_subpath_exports() {
assert_eq!(
package_base_name("@acme/toolkit/fs/safe"),
"@acme/toolkit"
);
assert_eq!(package_base_name("@acme/toolkit/fs/safe"), "@acme/toolkit");
assert_eq!(package_base_name("@acme/toolkit"), "@acme/toolkit");
assert_eq!(package_base_name("@scope/name/a/b/c"), "@scope/name");
assert_eq!(package_base_name("lodash/map"), "lodash");
Expand Down
Loading