From ab16e9ce7963e2bd97f185dc76797fdd73101338 Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Sat, 10 Oct 2026 07:36:31 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20=E7=BC=93=E5=AD=98=20debug=20=E6=A0=A1?= =?UTF-8?q?=E9=AA=8C=E9=80=92=E5=BD=92=E6=AF=94=E5=AD=90=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=EF=BC=8C=E8=B5=8B=E5=80=BC=E7=9B=AE=E6=A0=87=E5=B1=9E=E6=80=A7?= =?UTF-8?q?=E5=90=8D=E6=8C=89=E9=94=AE=E7=B2=92=E5=BA=A6=E8=AE=A1=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 38 ++++++------ Cargo.toml | 2 +- crates/oxide_bytecode/src/module.rs | 6 +- crates/oxide_code_cache/src/lib.rs | 8 ++- .../tests/code_forge_tests.rs | 61 +++++++++++++++++++ crates/oxide_compiler/src/hash/target.rs | 6 +- 6 files changed, 95 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e3cfbdd0..224829dd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1160,7 +1160,7 @@ dependencies = [ [[package]] name = "oxide_builtins" -version = "0.14.5" +version = "0.14.6" dependencies = [ "chrono", "fast-float", @@ -1185,7 +1185,7 @@ dependencies = [ [[package]] name = "oxide_bytecode" -version = "0.14.5" +version = "0.14.6" dependencies = [ "num-bigint", "oxide_log", @@ -1193,7 +1193,7 @@ dependencies = [ [[package]] name = "oxide_cfg" -version = "0.14.5" +version = "0.14.6" dependencies = [ "oxide_bytecode", "oxide_emit", @@ -1204,7 +1204,7 @@ dependencies = [ [[package]] name = "oxide_cli" -version = "0.14.5" +version = "0.14.6" dependencies = [ "ansi_term", "bumpalo", @@ -1226,7 +1226,7 @@ dependencies = [ [[package]] name = "oxide_code_cache" -version = "0.14.5" +version = "0.14.6" dependencies = [ "lru", "oxide_bytecode", @@ -1235,7 +1235,7 @@ dependencies = [ [[package]] name = "oxide_compiler" -version = "0.14.5" +version = "0.14.6" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1255,7 +1255,7 @@ dependencies = [ [[package]] name = "oxide_dce" -version = "0.14.5" +version = "0.14.6" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1269,7 +1269,7 @@ dependencies = [ [[package]] name = "oxide_emit" -version = "0.14.5" +version = "0.14.6" dependencies = [ "num-bigint", "oxc_allocator", @@ -1284,7 +1284,7 @@ dependencies = [ [[package]] name = "oxide_engine" -version = "0.14.5" +version = "0.14.6" dependencies = [ "oxide_bytecode", "oxide_compiler", @@ -1296,7 +1296,7 @@ dependencies = [ [[package]] name = "oxide_ir" -version = "0.14.5" +version = "0.14.6" dependencies = [ "oxide_bytecode", "oxide_log", @@ -1305,7 +1305,7 @@ dependencies = [ [[package]] name = "oxide_kernel" -version = "0.14.5" +version = "0.14.6" dependencies = [ "bumpalo", "dashmap", @@ -1319,7 +1319,7 @@ dependencies = [ [[package]] name = "oxide_liveness" -version = "0.14.5" +version = "0.14.6" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1331,7 +1331,7 @@ dependencies = [ [[package]] name = "oxide_log" -version = "0.14.5" +version = "0.14.6" dependencies = [ "tracing", "tracing-appender", @@ -1340,7 +1340,7 @@ dependencies = [ [[package]] name = "oxide_parser" -version = "0.14.5" +version = "0.14.6" dependencies = [ "oxc_allocator", "oxc_ast", @@ -1355,7 +1355,7 @@ dependencies = [ [[package]] name = "oxide_regalloc" -version = "0.14.5" +version = "0.14.6" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1371,7 +1371,7 @@ dependencies = [ [[package]] name = "oxide_runtime_api" -version = "0.14.5" +version = "0.14.6" dependencies = [ "num-bigint", "num-traits", @@ -1384,7 +1384,7 @@ dependencies = [ [[package]] name = "oxide_test262" -version = "0.14.5" +version = "0.14.6" dependencies = [ "oxide_bytecode", "oxide_compiler", @@ -1402,7 +1402,7 @@ dependencies = [ [[package]] name = "oxide_types" -version = "0.14.5" +version = "0.14.6" dependencies = [ "bumpalo", "dashmap", @@ -1415,7 +1415,7 @@ dependencies = [ [[package]] name = "oxide_vm" -version = "0.14.5" +version = "0.14.6" dependencies = [ "bumpalo", "chrono", diff --git a/Cargo.toml b/Cargo.toml index ea5ef453..2bab266e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ members = [ ] [workspace.package] -version = "0.14.5" +version = "0.14.6" edition = "2021" license = "MIT" rust-version = "1.80" diff --git a/crates/oxide_bytecode/src/module.rs b/crates/oxide_bytecode/src/module.rs index 57157f16..8134ee2a 100644 --- a/crates/oxide_bytecode/src/module.rs +++ b/crates/oxide_bytecode/src/module.rs @@ -30,7 +30,7 @@ pub enum Constant { /// `enclosing_reg` 是外层函数中该变量的寄存器位;`cell_idx` 是父函数 own cell /// 表下标(`parent_uv_idx` 为 None 时)。多级闭包(外层变量本身就是父函数从更 /// 外层捕获的 upvalue)时 `parent_uv_idx` 给出父闭包 `upvalues` 数组下标。 -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub struct UpvalueCapture { pub name: String, pub enclosing_reg: u32, @@ -50,6 +50,10 @@ pub struct UpvalueCapture { /// - `is_arrow` / `captured_this_const_idx` — 箭头函数词法 `this`; /// - `is_class_constructor` / `is_derived_constructor` / `needs_home_object` — 类相关; /// - `upvalue_captures` / `cells_needed` — 闭包捕获描述。 +/// +/// 派生 `PartialEq` 供缓存 debug 重编译校验做整结构比较(递归覆盖子模块树); +/// `Debug` 供校验失败时输出整棵模块树(与 `Display` 反汇编互补)。 +#[derive(Debug, PartialEq)] pub struct CompiledModule { pub bytecode: Arc<[opcode::Instr]>, pub constants: Vec, diff --git a/crates/oxide_code_cache/src/lib.rs b/crates/oxide_code_cache/src/lib.rs index d518fd67..c20aedab 100644 --- a/crates/oxide_code_cache/src/lib.rs +++ b/crates/oxide_code_cache/src/lib.rs @@ -59,7 +59,7 @@ impl CodeForge { } /// 命中返回缓存模块,未命中则调用 `compile` 编译后缓存并返回。 - /// debug 构建下命中时会重编译校验 bytecode,检测结构哈希碰撞。 + /// debug 构建下命中时会重编译校验整模块(含子模块树),检测结构哈希碰撞。 pub fn get_or_insert_with(&self, hash: u64, compile: F) -> Result, String> where F: Fn() -> Result, @@ -73,9 +73,11 @@ impl CodeForge { #[cfg(debug_assertions)] { let fresh = compile()?; + // 整结构比较(递归覆盖子模块树):只比顶层字节码会漏检嵌套 + // 函数体内的同键异码。 debug_assert_eq!( - module.bytecode, fresh.bytecode, - "structural hash collision: cached bytecode differs from recompiled for hash {hash}", + module.as_ref(), &fresh, + "structural hash collision: cached module differs from recompiled for hash {hash}", ); } return Ok(module); diff --git a/crates/oxide_code_cache/tests/code_forge_tests.rs b/crates/oxide_code_cache/tests/code_forge_tests.rs index 9f5293e3..5d2e8319 100644 --- a/crates/oxide_code_cache/tests/code_forge_tests.rs +++ b/crates/oxide_code_cache/tests/code_forge_tests.rs @@ -85,6 +85,67 @@ fn cache_hit_debug_verifies_bytecode() { .unwrap(); } +/// 构造带指定字节码的子模块(嵌套函数体夹具)。 +fn submodule(bytecode: Vec) -> CompiledModule { + let mut m = CompiledModule::new(); + m.bytecode = Arc::from(bytecode); + m +} + +#[test] +fn cache_hit_debug_verifies_nested_submodules_identical() { + let forge = forge(16); + let mut m1 = CompiledModule::new(); + m1.bytecode = Arc::from(vec![1, 2, 3]); + m1.sub_modules = vec![Arc::new(submodule(vec![4, 5, 6]))]; + let cached = forge.insert(7, m1); + let result = forge + .get_or_insert_with(7, || { + let mut m = CompiledModule::new(); + m.bytecode = Arc::from(vec![1, 2, 3]); + m.sub_modules = vec![Arc::new(submodule(vec![4, 5, 6]))]; + Ok(m) + }) + .unwrap(); + assert!(Arc::ptr_eq(&cached, &result)); +} + +#[test] +#[cfg_attr(debug_assertions, should_panic(expected = "structural hash collision"))] +fn cache_hit_debug_verifies_nested_submodule_differs() { + let forge = forge(16); + let mut m1 = CompiledModule::new(); + m1.bytecode = Arc::from(vec![1, 2, 3]); + m1.sub_modules = vec![Arc::new(submodule(vec![4, 5, 6]))]; + forge.insert(8, m1); + let _ = forge + .get_or_insert_with(8, || { + let mut m = CompiledModule::new(); + m.bytecode = Arc::from(vec![1, 2, 3]); + m.sub_modules = vec![Arc::new(submodule(vec![7, 8, 9]))]; + Ok(m) + }) + .unwrap(); +} + +#[test] +#[cfg_attr(debug_assertions, should_panic(expected = "structural hash collision"))] +fn cache_hit_debug_verifies_top_level_differs_keeps_prefix() { + let forge = forge(16); + let mut m1 = CompiledModule::new(); + m1.bytecode = Arc::from(vec![1, 2, 3]); + m1.sub_modules = vec![Arc::new(submodule(vec![4, 5, 6]))]; + forge.insert(9, m1); + let _ = forge + .get_or_insert_with(9, || { + let mut m = CompiledModule::new(); + m.bytecode = Arc::from(vec![9, 8, 7]); + m.sub_modules = vec![Arc::new(submodule(vec![4, 5, 6]))]; + Ok(m) + }) + .unwrap(); +} + #[test] fn cache_hit_returns_cached_not_recompiled() { let forge = forge(16); diff --git a/crates/oxide_compiler/src/hash/target.rs b/crates/oxide_compiler/src/hash/target.rs index 78cf707e..6a3693bd 100644 --- a/crates/oxide_compiler/src/hash/target.rs +++ b/crates/oxide_compiler/src/hash/target.rs @@ -118,14 +118,16 @@ fn hash_assignment_target_maybe_default( } } -/// 哈希对象赋值目标属性:标识符形态计绑定名与默认值(若有), +/// 哈希对象赋值目标属性:标识符形态计绑定名(仅精确键)与默认值(若有), /// 属性形态计键与绑定递归。 fn hash_assignment_target_property( prop: &AssignmentTargetProperty, h: &mut rustc_hash::FxHasher, include_binding_names: bool, ) { match prop { AssignmentTargetProperty::AssignmentTargetPropertyIdentifier(id) => { - id.binding.name.as_str().hash(h); + if include_binding_names { + id.binding.name.as_str().hash(h); + } if let Some(init) = &id.init { expression::hash_expression(init, h, include_binding_names); }