From 20b143ee08f5dd84bf8d07300a89d992273b18b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ralph=20K=C3=BCpper?= Date: Fri, 17 Jul 2026 12:48:39 +0200 Subject: [PATCH] fix(cache): key the object cache on all codegen-affecting env vars (#6394) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The object cache keyed on a curated but incomplete set of codegen env vars. ~16 PERRY_* vars that perry-codegen reads at compile time and that change the emitted .o — typed-feedback site emission, IC and method-dispatch outlining, inline new/ctor, string-init chunking, per-unit -O0/-Os selection, entry-symbol rename, codegen-unit partitioning, volatile-setjmp promotion, and loop GC-poll emission — were absent from the key. Setting any of them against a warm cache silently reused an object built without it: the switch appears to do nothing, and any A/B or bisection built on it is vacuous. Add them to compute_object_cache_key_with_env. Deliberately excluded: runtime-global loads (@PERRY_CLASS_FIELD_INLINE_GUARD_DISABLED / @PERRY_TA_VIEW_GUARD / @PERRY_TA_KIND_CACHE — codegen emits them identically regardless of the compile-time env), diagnostics-only vars, the final-link PERRY_LD, and vars already captured via the resolved target triple (PERRY_WATCHOS_ARM64_32) or the HIR fingerprint (PERRY_GLOBAL_SCRIPT_THIS, PERRY_EVAL_CSP, PERRY_ALLOW_UNIMPLEMENTED). Extends key_changes_with_codegen_env_vars to assert every newly-keyed var (unset vs set vs different value) yields a distinct key. Closes #6394 --- .../src/commands/compile/object_cache.rs | 86 +++++++++++++++++++ .../object_cache/object_cache_tests.rs | 17 ++++ 2 files changed, 103 insertions(+) diff --git a/crates/perry/src/commands/compile/object_cache.rs b/crates/perry/src/commands/compile/object_cache.rs index 76fdb4ead1..cbeee43d1e 100644 --- a/crates/perry/src/commands/compile/object_cache.rs +++ b/crates/perry/src/commands/compile/object_cache.rs @@ -806,6 +806,92 @@ fn compute_object_cache_key_with_env( "env_target_cpu", env_var("PERRY_TARGET_CPU").as_deref().unwrap_or(""), ); + // Codegen tuning/emission toggles (#6394). Each is read by perry-codegen + // at compile time and changes the emitted IR / .o bytes, so a warm cache + // must not serve an object built under a different setting. These are + // process-env reads (`std::env::var`), NOT runtime globals: the class-field + // inline guard, typed-array view guard, and TA kind cache are emitted as + // loads of `@PERRY_*` globals resolved at run time — codegen emits them + // identically regardless of the compile-time environment, so they are + // deliberately absent here. + h.field( + "env_typed_feedback", + env_var("PERRY_TYPED_FEEDBACK").as_deref().unwrap_or(""), + ); + h.field( + "env_typed_feedback_trace", + env_var("PERRY_TYPED_FEEDBACK_TRACE") + .as_deref() + .unwrap_or(""), + ); + h.field( + "env_full_outline_ic", + env_var("PERRY_FULL_OUTLINE_IC").as_deref().unwrap_or(""), + ); + h.field( + "env_full_outline_ic_min_funcs", + env_var("PERRY_FULL_OUTLINE_IC_MIN_FUNCS") + .as_deref() + .unwrap_or(""), + ); + h.field( + "env_outline_method_dispatch", + env_var("PERRY_OUTLINE_METHOD_DISPATCH") + .as_deref() + .unwrap_or(""), + ); + h.field( + "env_inline_new", + env_var("PERRY_INLINE_NEW").as_deref().unwrap_or(""), + ); + h.field( + "env_inline_ctor", + env_var("PERRY_INLINE_CTOR").as_deref().unwrap_or(""), + ); + h.field( + "env_string_init_chunk_size", + env_var("PERRY_STRING_INIT_CHUNK_SIZE") + .as_deref() + .unwrap_or(""), + ); + h.field( + "env_ll_o0_threshold_bytes", + env_var("PERRY_LL_O0_THRESHOLD_BYTES") + .as_deref() + .unwrap_or(""), + ); + h.field( + "env_ll_size_opt", + env_var("PERRY_LL_SIZE_OPT").as_deref().unwrap_or(""), + ); + h.field( + "env_ll_size_opt_max_fn_bytes", + env_var("PERRY_LL_SIZE_OPT_MAX_FN_BYTES") + .as_deref() + .unwrap_or(""), + ); + h.field( + "env_entry_symbol", + env_var("PERRY_ENTRY_SYMBOL").as_deref().unwrap_or(""), + ); + h.field( + "env_codegen_units", + env_var("PERRY_CODEGEN_UNITS").as_deref().unwrap_or(""), + ); + h.field( + "env_codegen_unit_size", + env_var("PERRY_CODEGEN_UNIT_SIZE").as_deref().unwrap_or(""), + ); + h.field( + "env_setjmp_volatile", + env_var("PERRY_SETJMP_VOLATILE").as_deref().unwrap_or(""), + ); + h.field( + "env_gc_moving_loop_polls", + env_var("PERRY_GC_MOVING_LOOP_POLLS") + .as_deref() + .unwrap_or(""), + ); h.finish() } diff --git a/crates/perry/src/commands/compile/object_cache/object_cache_tests.rs b/crates/perry/src/commands/compile/object_cache/object_cache_tests.rs index c5ec6e0f45..24c8ed279d 100644 --- a/crates/perry/src/commands/compile/object_cache/object_cache_tests.rs +++ b/crates/perry/src/commands/compile/object_cache/object_cache_tests.rs @@ -587,6 +587,23 @@ fn key_changes_with_codegen_env_vars() { "PERRY_VERIFY_NATIVE_REGIONS", "PERRY_UNBOXED_OBJECT_FIELDS", "PERRY_TARGET_CPU", + // Codegen tuning/emission toggles (#6394). + "PERRY_TYPED_FEEDBACK", + "PERRY_TYPED_FEEDBACK_TRACE", + "PERRY_FULL_OUTLINE_IC", + "PERRY_FULL_OUTLINE_IC_MIN_FUNCS", + "PERRY_OUTLINE_METHOD_DISPATCH", + "PERRY_INLINE_NEW", + "PERRY_INLINE_CTOR", + "PERRY_STRING_INIT_CHUNK_SIZE", + "PERRY_LL_O0_THRESHOLD_BYTES", + "PERRY_LL_SIZE_OPT", + "PERRY_LL_SIZE_OPT_MAX_FN_BYTES", + "PERRY_ENTRY_SYMBOL", + "PERRY_CODEGEN_UNITS", + "PERRY_CODEGEN_UNIT_SIZE", + "PERRY_SETJMP_VOLATILE", + "PERRY_GC_MOVING_LOOP_POLLS", ] { // Sample state without the var, with the var, and with a different // value — all three keys must be distinct.