refactor: realm 与 Vm 生命周期解耦,Vm 持 Arc<Realm>

This commit is contained in:
2026-10-07 01:35:16 +00:00
parent 14ef287a75
commit c6bc93a076
39 changed files with 796 additions and 676 deletions
+10 -10
View File
@@ -230,7 +230,7 @@ impl Vm {
if current_cells[cell_idx].is_null() {
// 占位 Cell 保持未初始化(TDZ)直到 MAKE_CELL 置位;
// 若绑定为 var 则其初始化 MAKE_CELL 在函数序言先于任何读取执行。
current_cells[cell_idx] = self.realm.gc.alloc_cell(JsValue::undefined(), false);
current_cells[cell_idx] = self.realm.gc.borrow().alloc_cell(JsValue::undefined(), false);
}
current_cells[cell_idx]
};
@@ -275,14 +275,14 @@ impl Vm {
}
if current[cell_idx].is_null() {
// 无占位 cell:新建。
current[cell_idx] = self.realm.gc.alloc_cell(value, initialized);
current[cell_idx] = self.realm.gc.borrow().alloc_cell(value, initialized);
} else {
let existing_initialized = unsafe { &*current[cell_idx] }.is_initialized();
if !initialized && existing_initialized {
// TDZ 占位而槽内是已初始化 cell:新建替换。循环体每迭代重执行
// 的 TDZ 占位不得原位翻新迭代 cell(已被本迭代前闭包捕获);
// 已初始化 cell 保持身份,闭包 upvalue 保值。
current[cell_idx] = self.realm.gc.alloc_cell(value, initialized);
current[cell_idx] = self.realm.gc.borrow().alloc_cell(value, initialized);
} else {
// 更新占位 cell(CREATE_CLOSURE 已建),使闭包 upvalue 指向的
// cell 值跟随初始化;初始化标志随指令 b 槽。
@@ -309,7 +309,7 @@ impl Vm {
while current.len() <= cell_idx {
current.push(std::ptr::null_mut());
}
current[cell_idx] = self.realm.gc.alloc_cell(value, true);
current[cell_idx] = self.realm.gc.borrow().alloc_cell(value, true);
Ok(())
}
@@ -334,7 +334,7 @@ impl Vm {
}
if current[cell_idx].is_null() {
let val = self.regs[a];
current[cell_idx] = self.realm.gc.alloc_cell(val, true);
current[cell_idx] = self.realm.gc.borrow().alloc_cell(val, true);
}
let c = unsafe { &*current[cell_idx] };
if !c.is_initialized() {
@@ -478,7 +478,7 @@ impl Vm {
} else {
self.regs[rd]
};
upvals[uv_idx] = self.realm.gc.alloc_cell(val, true);
upvals[uv_idx] = self.realm.gc.borrow().alloc_cell(val, true);
self.regs[rd] = unsafe { (*upvals[uv_idx]).value };
return Ok(());
}
@@ -532,7 +532,7 @@ impl Vm {
}
vm_debug!("STORE_UPVALUE len={} wrote existing", upvals.len());
} else {
upvals[uv_idx] = self.realm.gc.alloc_cell(src_val, true);
upvals[uv_idx] = self.realm.gc.borrow().alloc_cell(src_val, true);
}
}
Ok(())
@@ -544,7 +544,7 @@ impl Vm {
vm_trace!("CREATE_REGEXP rd={}", rd);
let pat_val = self.regs[a];
let flags_val = self.regs[b];
let ctor_ptr = self.realm.session.builtin_world().regexp_constructor.as_ptr() as *mut JsObject;
let ctor_ptr = self.realm.session.borrow().builtin_world().regexp_constructor.as_ptr() as *mut JsObject;
let ctor = unsafe { &*ctor_ptr };
let Some(native_fn) = ctor.native_fn() else {
self.raise_error_kind("TypeError", "RegExp constructor unavailable")?;
@@ -1004,7 +1004,7 @@ impl Vm {
// bound 包装:解包链后转发到最内层 target([[Construct]] 语义)。
if ctor_obj.type_tag == oxide_types::object::JsObject::OBJ_TYPE_BOUND {
let proto_ptr = &*self.realm.object_prototype as *const JsObject as *mut JsObject;
let proto_ptr = self.realm.object_prototype.borrow().as_ptr() as *mut JsObject;
let new_obj = self.alloc_object(JsObject::new_empty(
oxide_kernel::shape_forge::EMPTY_SHAPE_ID,
JsValue::from_js_object(proto_ptr),
@@ -1012,7 +1012,7 @@ impl Vm {
return self.dispatch_new_bound(rd, constructor, new_obj, args, 0);
}
let proto_ptr = &*self.realm.object_prototype as *const JsObject as *mut JsObject;
let proto_ptr = self.realm.object_prototype.borrow().as_ptr() as *mut JsObject;
let new_obj = self.alloc_object(JsObject::new_empty(
oxide_kernel::shape_forge::EMPTY_SHAPE_ID,
JsValue::from_js_object(proto_ptr),
+14 -10
View File
@@ -39,8 +39,11 @@ impl Vm {
return Err(format!("LOAD_GLOBAL constant index {idx} is not a string key"));
}
let si = self.property_key_si(key_val)?;
let global = self.realm.session.global_object();
if let Some(val) = self.resolve_property(global, si) {
let global = {
let session = self.realm.session.borrow();
session.global_object().clone()
};
if let Some(val) = self.resolve_property(&global, si) {
self.regs[rd] = val;
Ok(false)
} else {
@@ -67,7 +70,8 @@ impl Vm {
return Err(format!("LOAD_GLOBAL_TYPEOF constant index {idx} is not a string key"));
}
let si = self.property_key_si(key_val)?;
let global = self.realm.session.global_object();
let session = self.realm.session.borrow();
let global = session.global_object();
self.regs[rd] = self.resolve_property(global, si).unwrap_or(JsValue::undefined());
Ok(())
}
@@ -215,7 +219,7 @@ impl Vm {
pub(crate) fn dispatch_new_object(&mut self, rd: usize, instr: u32) -> Result<(), String> {
let nprops = opcode::a(instr) as usize;
vm_trace!("NEW_OBJECT rd={} nprops={}", rd, nprops);
let proto_ptr = &*self.realm.object_prototype as *const JsObject as *mut JsObject;
let proto_ptr = self.realm.object_prototype.borrow().as_ptr() as *mut JsObject;
let mut shape_id = EMPTY_SHAPE_ID;
if nprops > 0 {
let key_idxs: Vec<u32> = self.bytecode[self.pc..self.pc + nprops].to_vec();
@@ -258,7 +262,7 @@ impl Vm {
/// - 登记 session 对象表并计入堆账目;回收由 session GC mark/sweep 承担。
pub(crate) fn dispatch_new_session_object(&mut self, rd: usize) -> Result<(), String> {
vm_trace!("NEW_SESSION_OBJECT rd={}", rd);
let proto_ptr = &*self.realm.object_prototype as *const JsObject as *mut JsObject;
let proto_ptr = self.realm.object_prototype.borrow().as_ptr() as *mut JsObject;
let obj = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(proto_ptr));
let obj_ptr = self.alloc_session_object(obj);
self.regs[rd] = JsValue::object(obj_ptr as *mut u8);
@@ -278,7 +282,7 @@ impl Vm {
Some(frame) => (frame.arguments_base, frame.arguments_count),
None => (self.inline_args_base, self.inline_args_count),
};
let proto_ptr = &*self.realm.object_prototype as *const JsObject as *mut JsObject;
let proto_ptr = self.realm.object_prototype.borrow().as_ptr() as *mut JsObject;
let obj_ptr = self.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(proto_ptr)));
let obj = unsafe { &mut *obj_ptr };
obj.type_tag = JsObject::OBJ_TYPE_ARGUMENTS;
@@ -312,7 +316,7 @@ impl Vm {
let simple = self.active_module().is_some_and(|m| m.has_simple_params);
if strict || !simple {
// SAFETY: 指针由绑定层在 session 构造期写入,session 存活期内有效。
let thrower_ptr = self.realm.session.builtin_world().throw_type_error.get();
let thrower_ptr = self.realm.session.borrow().builtin_world().throw_type_error.get();
if thrower_ptr.is_null() {
// 绑定层尚未写入共享对象(正常路径不出现):退化为数据属性保调用可用。
if let Err(msg) =
@@ -367,7 +371,7 @@ impl Vm {
let sym_iter_si = make_well_known_symbol_key(0);
// SAFETY: array_proto 是 perm 层内置对象(BuiltinWorld 持有),地址稳定且
// 跨 epoch/session 存活,本调用期间无 GC 搬移。
let array_proto = self.realm.session.builtin_world().array_proto.as_ptr();
let array_proto = self.realm.session.borrow().builtin_world().array_proto.as_ptr();
let iter_val = match self.ordinary_get(unsafe { &*array_proto }, sym_iter_si, JsValue::undefined()) {
Ok(v) => v,
Err(msg) => return self.raise_error_kind("TypeError", &msg),
@@ -397,7 +401,7 @@ impl Vm {
};
let n = count as usize;
let rest_len = n.saturating_sub(fixed_count);
let proto_ptr = self.realm.session.builtin_world().array_proto.as_ptr() as *mut JsObject;
let proto_ptr = self.realm.session.borrow().builtin_world().array_proto.as_ptr() as *mut JsObject;
let obj_ptr =
self.alloc_object(JsObject::new_array(EMPTY_SHAPE_ID, JsValue::from_js_object(proto_ptr), rest_len));
let obj = unsafe { &mut *obj_ptr };
@@ -417,7 +421,7 @@ impl Vm {
pub(crate) fn dispatch_new_array(&mut self, rd: usize, instr: u32) {
let n = opcode::imm16(instr) as usize;
vm_trace!("NEW_ARRAY rd={} n={}", rd, n);
let proto_ptr = self.realm.session.builtin_world().array_proto.as_ptr() as *mut JsObject;
let proto_ptr = self.realm.session.borrow().builtin_world().array_proto.as_ptr() as *mut JsObject;
let obj = self.alloc_object(JsObject::new_array(EMPTY_SHAPE_ID, JsValue::from_js_object(proto_ptr), n));
self.regs[rd] = JsValue::object(obj as *mut u8);
}
+6 -6
View File
@@ -88,27 +88,27 @@ impl Vm {
}
return Ok(Some(JsValue::undefined()));
}
let proto_ptr = self.realm.session.builtin_world().string_proto.as_ptr() as *mut JsObject;
let proto_ptr = self.realm.session.borrow().builtin_world().string_proto.as_ptr() as *mut JsObject;
let proto = unsafe { &*proto_ptr };
return self.ordinary_get(proto, prop_name_si, val).map(Some);
}
if val.is_int() || val.is_double() {
let proto_ptr = self.realm.session.builtin_world().number_proto.as_ptr() as *mut JsObject;
let proto_ptr = self.realm.session.borrow().builtin_world().number_proto.as_ptr() as *mut JsObject;
let proto = unsafe { &*proto_ptr };
return self.ordinary_get(proto, prop_name_si, val).map(Some);
}
if val.is_bool() {
let proto_ptr = self.realm.session.builtin_world().boolean_proto.as_ptr() as *mut JsObject;
let proto_ptr = self.realm.session.borrow().builtin_world().boolean_proto.as_ptr() as *mut JsObject;
let proto = unsafe { &*proto_ptr };
return self.ordinary_get(proto, prop_name_si, val).map(Some);
}
if val.is_bigint() {
let proto_ptr = self.realm.session.builtin_world().bigint_proto.as_ptr() as *mut JsObject;
let proto_ptr = self.realm.session.borrow().builtin_world().bigint_proto.as_ptr() as *mut JsObject;
let proto = unsafe { &*proto_ptr };
return self.ordinary_get(proto, prop_name_si, val).map(Some);
}
if val.is_symbol() {
let proto_ptr = self.realm.session.builtin_world().symbol_proto.as_ptr() as *mut JsObject;
let proto_ptr = self.realm.session.borrow().builtin_world().symbol_proto.as_ptr() as *mut JsObject;
let proto = unsafe { &*proto_ptr };
return self.ordinary_get(proto, prop_name_si, val).map(Some);
}
@@ -790,7 +790,7 @@ impl Vm {
return Err(format!("DELETE_GLOBAL_PROP_C constant index {idx} is not a string key"));
}
let si = self.property_key_si(key_val)?;
let global_ptr = self.realm.session.global_object().as_ptr() as *mut JsObject;
let global_ptr = self.realm.session.borrow().global_object().as_ptr() as *mut JsObject;
// SAFETY: 全局对象钉在 session 永久区,指针在 VM 生命周期内有效。
let obj = unsafe { &mut *global_ptr };
// 统一走共享删除逻辑(与 Reflect.deleteProperty 同源);不可配置返回