mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
fix: 闭包 upvalue cell 占位稳定化修复错读调用方表
This commit is contained in:
+1
-1
@@ -57,7 +57,7 @@ lru = "0.18"
|
|||||||
smallvec = { version = "1", features = ["union"] }
|
smallvec = { version = "1", features = ["union"] }
|
||||||
chrono = { version = "0.4", default-features = false, features = ["clock"] }
|
chrono = { version = "0.4", default-features = false, features = ["clock"] }
|
||||||
unicode-normalization = "0.1"
|
unicode-normalization = "0.1"
|
||||||
tracing = { version = "0.1.44", features = ["max_level_trace", "release_max_level_info"] }
|
tracing = { version = "0.1.44", features = ["max_level_trace", "release_max_level_debug"] }
|
||||||
tracing-subscriber = { version = "0.3.23", features = ["env-filter", "registry"] }
|
tracing-subscriber = { version = "0.3.23", features = ["env-filter", "registry"] }
|
||||||
tracing-appender = "0.2.5"
|
tracing-appender = "0.2.5"
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,6 @@ rust-version.workspace = true
|
|||||||
description = "OxideJS - Structured logging subsystem (tracing-based)"
|
description = "OxideJS - Structured logging subsystem (tracing-based)"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tracing = { workspace = true, features = ["max_level_trace", "release_max_level_info"] }
|
tracing = { workspace = true, features = ["max_level_trace", "release_max_level_debug"] }
|
||||||
tracing-subscriber = { workspace = true, features = ["env-filter", "registry"] }
|
tracing-subscriber = { workspace = true, features = ["env-filter", "registry"] }
|
||||||
tracing-appender = "0.2.5"
|
tracing-appender = "0.2.5"
|
||||||
|
|||||||
@@ -85,7 +85,8 @@ pub fn init(config: &LogConfig) {
|
|||||||
}
|
}
|
||||||
SUBSYSTEM.set(filter.clone()).ok();
|
SUBSYSTEM.set(filter.clone()).ok();
|
||||||
|
|
||||||
let env_filter = EnvFilter::try_from_env("OXIDE_LOG").unwrap_or_else(|_| EnvFilter::new("oxide=off"));
|
let env_filter = EnvFilter::try_from_env("OXIDE_LOG")
|
||||||
|
.unwrap_or_else(|_| EnvFilter::new("oxide=trace"));
|
||||||
|
|
||||||
subsystem::apply_env_levels();
|
subsystem::apply_env_levels();
|
||||||
|
|
||||||
|
|||||||
@@ -1135,9 +1135,16 @@ fn run_tests() -> bool {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut log_level = Level::Info;
|
||||||
|
if let Ok(s) = std::env::var("OXIDE_TEST262_LOG_LEVEL") {
|
||||||
|
if let Some(l) = oxide_log::subsystem::parse_level(&s) {
|
||||||
|
log_level = l;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
eprintln!("[LOG] level={log_level:?}");
|
||||||
oxide_log::init(&LogConfig {
|
oxide_log::init(&LogConfig {
|
||||||
output: Output::Stderr,
|
output: Output::Stderr,
|
||||||
levels: [Level::Info; SUBSYSTEM_COUNT],
|
levels: [log_level; SUBSYSTEM_COUNT],
|
||||||
});
|
});
|
||||||
|
|
||||||
let test262_root = if let Some(root) = config.test262_root.clone() {
|
let test262_root = if let Some(root) = config.test262_root.clone() {
|
||||||
|
|||||||
@@ -133,15 +133,21 @@ impl Vm {
|
|||||||
let name_val = function_name.as_deref().map(|n| self.new_string(n)).unwrap_or_else(|| self.new_string(""));
|
let name_val = function_name.as_deref().map(|n| self.new_string(n)).unwrap_or_else(|| self.new_string(""));
|
||||||
self.set_or_create_prop_value(func_obj, name_si, name_val);
|
self.set_or_create_prop_value(func_obj, name_si, name_val);
|
||||||
if !upvalue_captures.is_empty() {
|
if !upvalue_captures.is_empty() {
|
||||||
if let Some(current_cells) = self.cell_stack.last() {
|
if let Some(current_cells) = self.cell_stack.last_mut() {
|
||||||
let mut upvals = Box::new(Vec::with_capacity(upvalue_captures.len()));
|
let mut upvals = Box::new(Vec::with_capacity(upvalue_captures.len()));
|
||||||
for capture in &upvalue_captures {
|
for capture in &upvalue_captures {
|
||||||
let cell_ptr = if (capture.cell_idx as usize) < current_cells.len() {
|
let cell_idx = capture.cell_idx as usize;
|
||||||
current_cells[capture.cell_idx as usize]
|
if cell_idx >= current_cells.len() {
|
||||||
} else {
|
current_cells.resize(cell_idx + 1, std::ptr::null_mut());
|
||||||
std::ptr::null_mut()
|
}
|
||||||
};
|
// cell 可能尚未 MAKE_CELL(hoisting 顺序:CREATE_CLOSURE 先于
|
||||||
upvals.push(cell_ptr);
|
// MAKE_CELL)——建占位 Cell,后续 MAKE_CELL 更新同一 Cell 的值,
|
||||||
|
// 保证 upvalue 始终指向定义方表里的稳定 cell(而非调用方表)。
|
||||||
|
if current_cells[cell_idx].is_null() {
|
||||||
|
let cell = self.gc_state.session_epoch.alloc(Cell::new(JsValue::undefined(), true));
|
||||||
|
current_cells[cell_idx] = cell as *mut Cell;
|
||||||
|
}
|
||||||
|
upvals.push(current_cells[cell_idx]);
|
||||||
}
|
}
|
||||||
let func_obj = unsafe { &mut *result.as_js_object_ptr() };
|
let func_obj = unsafe { &mut *result.as_js_object_ptr() };
|
||||||
func_obj.set_upvalues(upvals);
|
func_obj.set_upvalues(upvals);
|
||||||
@@ -155,13 +161,21 @@ impl Vm {
|
|||||||
pub(crate) fn dispatch_make_cell(&mut self, rd: usize, instr: u32) -> Result<(), String> {
|
pub(crate) fn dispatch_make_cell(&mut self, rd: usize, instr: u32) -> Result<(), String> {
|
||||||
let cell_idx = opcode::imm16(instr) as usize;
|
let cell_idx = opcode::imm16(instr) as usize;
|
||||||
let value = self.regs[rd];
|
let value = self.regs[rd];
|
||||||
let cell = self.gc_state.session_epoch.alloc(Cell::new(value, true));
|
|
||||||
let cell_ptr = cell as *mut Cell;
|
|
||||||
let current = self.cell_stack.last_mut().unwrap();
|
let current = self.cell_stack.last_mut().unwrap();
|
||||||
while current.len() <= cell_idx {
|
while current.len() <= cell_idx {
|
||||||
current.push(std::ptr::null_mut());
|
current.push(std::ptr::null_mut());
|
||||||
}
|
}
|
||||||
current[cell_idx] = cell_ptr;
|
if current[cell_idx].is_null() {
|
||||||
|
// 无占位 cell:新建。
|
||||||
|
let cell = self.gc_state.session_epoch.alloc(Cell::new(value, true));
|
||||||
|
current[cell_idx] = cell as *mut Cell;
|
||||||
|
} else {
|
||||||
|
// 更新占位 cell(CREATE_CLOSURE 已建),使闭包 upvalue 指向的
|
||||||
|
// cell 值跟随初始化。
|
||||||
|
unsafe {
|
||||||
|
(*current[cell_idx]).value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -856,6 +856,34 @@ impl Vm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if self.pc >= self.bytecode.len() {
|
if self.pc >= self.bytecode.len() {
|
||||||
|
let tail: Vec<String> = self
|
||||||
|
.bytecode
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.rev()
|
||||||
|
.take(5)
|
||||||
|
.map(|(i, &instr)| format!("{i}:{:?}", opcode::opcode(instr)))
|
||||||
|
.collect();
|
||||||
|
let fn_names: Vec<String> = self
|
||||||
|
.frames
|
||||||
|
.iter()
|
||||||
|
.map(|f| {
|
||||||
|
self.kernel_core
|
||||||
|
.perm_interner()
|
||||||
|
.lookup(f.function_name)
|
||||||
|
.map(|s| s.to_string())
|
||||||
|
.unwrap_or_else(|| "?".into())
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
vm_error!(
|
||||||
|
"dispatch: program counter out of bounds pc={} len={} frames={} cell_stack={} tail={:?} fns={:?}",
|
||||||
|
self.pc,
|
||||||
|
self.bytecode.len(),
|
||||||
|
self.frames.len(),
|
||||||
|
self.cell_stack.len(),
|
||||||
|
tail,
|
||||||
|
fn_names
|
||||||
|
);
|
||||||
vm_error!("dispatch: program counter out of bounds pc={} len={}", self.pc, self.bytecode.len());
|
vm_error!("dispatch: program counter out of bounds pc={} len={}", self.pc, self.bytecode.len());
|
||||||
self.profiling.instruction_count = steps;
|
self.profiling.instruction_count = steps;
|
||||||
return Err("program counter out of bounds".into());
|
return Err("program counter out of bounds".into());
|
||||||
|
|||||||
@@ -149,6 +149,16 @@ impl Vm {
|
|||||||
if let Some(saved_bc) = self.saved_bytecode_stack.pop() {
|
if let Some(saved_bc) = self.saved_bytecode_stack.pop() {
|
||||||
self.bytecode = saved_bc;
|
self.bytecode = saved_bc;
|
||||||
}
|
}
|
||||||
|
vm_debug!(
|
||||||
|
"restore_frame: return_addr={} bc_len={} saved_stack={} fn={:?}",
|
||||||
|
frame.return_addr,
|
||||||
|
self.bytecode.len(),
|
||||||
|
self.saved_bytecode_stack.len(),
|
||||||
|
self.kernel_core
|
||||||
|
.perm_interner()
|
||||||
|
.lookup(frame.function_name)
|
||||||
|
.map(|s| s.to_string())
|
||||||
|
);
|
||||||
if let Some(saved_imm) = self.saved_immutables_stack.pop() {
|
if let Some(saved_imm) = self.saved_immutables_stack.pop() {
|
||||||
self.active_immutables = saved_imm;
|
self.active_immutables = saved_imm;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user