fix: Function.prototype.apply 解除实参上限,native 大实参集走 spill 溢出区
apply 曾把实参数组静默截断到 55 个(寄存器窗口限制),导致 String.fromCodePoint.apply(null, codePoints) 这类大参数集调用只取前 55 个。 改为直接物化全部实参经 TailCall 下发:字节码目标走帧参数区(spill 栈)任意 个数;native 目标新增 spill 溢出区通道,寄存器窗口(253)之外的实参转存 spill 栈(GC 根、嵌套安全),builtin 经 VmHost::native_arg_count/native_arg_at 读取,String.fromCodePoint 迁移为新接口。大实参集不再静默截断。
This commit is contained in:
@@ -116,6 +116,43 @@ fn function_apply_returns_object_stays_valid() {
|
||||
assert_num(result, 10.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn function_apply_passes_large_arg_array_to_bytecode_target() {
|
||||
// 回归:apply 曾把实参数组静默截断到 55 个;大参数集必须完整到达目标函数。
|
||||
let mut vm = Vm::new();
|
||||
let result = eval(
|
||||
&mut vm,
|
||||
"var a = []; for (var i = 0; i < 1000; i++) { a[i] = i; } (function(){ return arguments.length; }).apply(null, a)",
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(result, JsValue::int(1000));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn function_apply_large_args_reach_last_element() {
|
||||
// 大参数集经 spill 溢出区送达后,末位实参可被目标读取(不止计数正确)。
|
||||
let mut vm = Vm::new();
|
||||
let result = eval(
|
||||
&mut vm,
|
||||
"var a = []; for (var i = 0; i < 300; i++) { a[i] = i; } (function(){ return arguments[299]; }).apply(null, a)",
|
||||
)
|
||||
.unwrap();
|
||||
assert_num(result, 299.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn function_apply_large_args_to_native_from_code_point() {
|
||||
// native 目标(String.fromCodePoint)接收大实参集:整串完整拼接,验证
|
||||
// harness `String.fromCodePoint.apply(null, codePoints)` 不再截断。
|
||||
let mut vm = Vm::new();
|
||||
let result = eval(
|
||||
&mut vm,
|
||||
"var a = []; for (var i = 0; i < 1000; i++) { a[i] = 65 + (i % 26); } String.fromCodePoint.apply(null, a).length",
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(result, JsValue::int(1000));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn getter_returns_object_stays_valid() {
|
||||
// 同类 bug:字节码 accessor 经 ordinary_get 同步路径(target_reg=None)在子 VM
|
||||
|
||||
Reference in New Issue
Block a user