feat: arguments 对象绑定(CREATE_ARGUMENTS + 帧实参 spill 区)

This commit is contained in:
2026-08-08 00:01:22 +08:00
parent bfc2312f6c
commit bfcf132d73
12 changed files with 267 additions and 7 deletions
+11 -1
View File
@@ -238,7 +238,7 @@ impl Vm {
/// 当前执行函数的闭包对象:普通路径取 frames 栈顶帧,inline(sync 回调)路径
/// frames 被隔离为空,取 `inline_callee`。
fn current_callee(&self) -> Option<JsValue> {
pub(crate) fn current_callee(&self) -> Option<JsValue> {
self.frames.last().map(|f| f.callee).or(self.inline_callee)
}
@@ -465,6 +465,14 @@ impl Vm {
let saved_this = self.regs[254];
let saved_new_target = self.regs[255];
// 完整实参写入 spill 栈实参区(在帧的 spill 区之前),供 CREATE_ARGUMENTS 使用。
let args_base = self.spill_stack.len() as u32;
for i in 0..arg_count {
let src_reg = first_arg_reg.wrapping_add(i as u8) as usize;
self.spill_stack.push(self.regs[src_reg]);
}
let args_count = arg_count.min(u16::MAX as usize) as u16;
for i in 0..sub_n_args {
let src_reg = first_arg_reg.wrapping_add(i as u8) as usize;
self.regs[sub_param_base + i] = self.regs[src_reg];
@@ -487,6 +495,8 @@ impl Vm {
caller_reg_limit,
saved_reg_offset,
spill_offset: self.spill_stack.len() as u32,
arguments_base: args_base,
arguments_count: args_count,
saved_this,
saved_new_target,
callee: super_ctor,
+37 -1
View File
@@ -2,7 +2,7 @@ use crate::vm::Vm;
use crate::{vm_error, vm_trace};
use oxide_bytecode::opcode;
use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
use oxide_types::object::JsObject;
use oxide_types::object::{JsObject, PropAttributes};
use oxide_types::value::JsValue;
impl Vm {
@@ -132,6 +132,42 @@ impl Vm {
self.regs[rd] = JsValue::object(obj as *mut u8);
}
/// 创建 arguments 对象:索引属性取当前帧(或 inline 同步调用)的完整实参,
/// 附 length / callee 属性。第一版为 unmapped(非严格)语义,索引与形参不同步。
///
/// # 边界与前提
/// - 实参区由 `push_bytecode_frame` / `dispatch_super_call` / `dispatch_new_expression`
/// 在推帧时写入 spill 栈;frames 为空(inline 同步调用)时读 `inline_args_*`。
/// - 索引属性用 shape 槽存储(普通对象),length/callee 为不可枚举数据属性。
pub(crate) fn dispatch_create_arguments(&mut self, rd: usize) -> Result<(), String> {
let (base, count) = match self.frames.last() {
Some(frame) => (frame.arguments_base, frame.arguments_count),
None => (self.inline_args_base, self.inline_args_count),
};
let proto_ptr = &*self.object_prototype as *const JsObject 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 };
// 索引属性:按实参下标写入 shape 槽,属性描述符为默认(可写/可枚举/可配置)。
for i in 0..count as usize {
let si = self.kernel_core.perm_interner().intern(&i.to_string()).0;
let val = self.spill_stack.get(base as usize + i).copied().unwrap_or(JsValue::undefined());
self.set_or_create_prop_value(obj, si, val);
}
// length:实参个数,可写、不可枚举、可配置。
let length_si = self.kernel_core.perm_interner().intern("length").0;
self.define_data_property(obj, length_si, JsValue::int(count as i32), PropAttributes::new(true, false, true))?;
// callee:当前执行函数,可写、不可枚举、可配置(严格模式应抛 TypeError,未支持)。
let callee_si = self.kernel_core.perm_interner().intern("callee").0;
let callee = self.current_callee().unwrap_or(JsValue::undefined());
self.define_data_property(obj, callee_si, callee, PropAttributes::new(true, false, true))?;
self.regs[rd] = JsValue::from_js_object(obj_ptr);
Ok(())
}
#[inline(always)]
pub(crate) fn dispatch_new_array(&mut self, rd: usize, instr: u32) {
let n = opcode::imm16(instr) as usize;