diff --git a/Cargo.lock b/Cargo.lock
index 06152b16..f5be0bd3 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1160,7 +1160,7 @@ dependencies = [
[[package]]
name = "oxide_builtins"
-version = "0.13.16"
+version = "0.13.17"
dependencies = [
"chrono",
"fast-float",
@@ -1185,7 +1185,7 @@ dependencies = [
[[package]]
name = "oxide_bytecode"
-version = "0.13.16"
+version = "0.13.17"
dependencies = [
"num-bigint",
"oxide_log",
@@ -1193,7 +1193,7 @@ dependencies = [
[[package]]
name = "oxide_cfg"
-version = "0.13.16"
+version = "0.13.17"
dependencies = [
"oxide_bytecode",
"oxide_emit",
@@ -1204,7 +1204,7 @@ dependencies = [
[[package]]
name = "oxide_cli"
-version = "0.13.16"
+version = "0.13.17"
dependencies = [
"ansi_term",
"bumpalo",
@@ -1226,7 +1226,7 @@ dependencies = [
[[package]]
name = "oxide_code_cache"
-version = "0.13.16"
+version = "0.13.17"
dependencies = [
"lru",
"oxide_bytecode",
@@ -1235,7 +1235,7 @@ dependencies = [
[[package]]
name = "oxide_compiler"
-version = "0.13.16"
+version = "0.13.17"
dependencies = [
"oxide_bytecode",
"oxide_cfg",
@@ -1255,7 +1255,7 @@ dependencies = [
[[package]]
name = "oxide_dce"
-version = "0.13.16"
+version = "0.13.17"
dependencies = [
"oxide_bytecode",
"oxide_cfg",
@@ -1269,7 +1269,7 @@ dependencies = [
[[package]]
name = "oxide_emit"
-version = "0.13.16"
+version = "0.13.17"
dependencies = [
"num-bigint",
"oxc_allocator",
@@ -1284,7 +1284,7 @@ dependencies = [
[[package]]
name = "oxide_engine"
-version = "0.13.16"
+version = "0.13.17"
dependencies = [
"oxide_bytecode",
"oxide_compiler",
@@ -1296,7 +1296,7 @@ dependencies = [
[[package]]
name = "oxide_ir"
-version = "0.13.16"
+version = "0.13.17"
dependencies = [
"oxide_bytecode",
"oxide_log",
@@ -1305,7 +1305,7 @@ dependencies = [
[[package]]
name = "oxide_kernel"
-version = "0.13.16"
+version = "0.13.17"
dependencies = [
"bumpalo",
"dashmap",
@@ -1319,7 +1319,7 @@ dependencies = [
[[package]]
name = "oxide_liveness"
-version = "0.13.16"
+version = "0.13.17"
dependencies = [
"oxide_bytecode",
"oxide_cfg",
@@ -1331,7 +1331,7 @@ dependencies = [
[[package]]
name = "oxide_log"
-version = "0.13.16"
+version = "0.13.17"
dependencies = [
"tracing",
"tracing-appender",
@@ -1340,7 +1340,7 @@ dependencies = [
[[package]]
name = "oxide_parser"
-version = "0.13.16"
+version = "0.13.17"
dependencies = [
"oxc_allocator",
"oxc_ast",
@@ -1355,7 +1355,7 @@ dependencies = [
[[package]]
name = "oxide_regalloc"
-version = "0.13.16"
+version = "0.13.17"
dependencies = [
"oxide_bytecode",
"oxide_cfg",
@@ -1371,7 +1371,7 @@ dependencies = [
[[package]]
name = "oxide_runtime_api"
-version = "0.13.16"
+version = "0.13.17"
dependencies = [
"num-bigint",
"num-traits",
@@ -1384,7 +1384,7 @@ dependencies = [
[[package]]
name = "oxide_test262"
-version = "0.13.16"
+version = "0.13.17"
dependencies = [
"oxide_bytecode",
"oxide_compiler",
@@ -1402,7 +1402,7 @@ dependencies = [
[[package]]
name = "oxide_types"
-version = "0.13.16"
+version = "0.13.17"
dependencies = [
"bumpalo",
"dashmap",
@@ -1415,7 +1415,7 @@ dependencies = [
[[package]]
name = "oxide_vm"
-version = "0.13.16"
+version = "0.13.17"
dependencies = [
"bumpalo",
"chrono",
diff --git a/Cargo.toml b/Cargo.toml
index 04f208b3..a0d454d8 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -23,7 +23,7 @@ members = [
]
[workspace.package]
-version = "0.13.16"
+version = "0.13.17"
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 f39c8e60..f554e094 100644
--- a/crates/oxide_bytecode/src/module.rs
+++ b/crates/oxide_bytecode/src/module.rs
@@ -347,7 +347,7 @@ mod tests {
use super::*;
/// 手工构造反汇编夹具:顶层 5 条指令(NEW_OBJECT 1 字键表、CALL 1 ext 字、
- /// IC_GET_PROP 8 ext 字),子模块 1 个(3 条指令,RETURN 带 1 个逃出计数 ext 字)。
+ /// IC_GET_PROP 8 ext 字),子模块 1 个(3 条指令,RETURN 带 2 个逃出计数 ext 字)。
fn fixture() -> CompiledModule {
let sub = CompiledModule {
function_name: Some("f".into()),
@@ -357,7 +357,8 @@ mod tests {
bytecode: Arc::from([
opcode::encode(OpCode::LOAD_CONST, 1, 0, 0),
opcode::encode(OpCode::RETURN, 1, 0, 0),
- 0, // RETURN 逃出计数 ext 字
+ 0, // RETURN 迭代器打包 ext 字
+ 0, // RETURN dispose_count ext 字
opcode::encode(OpCode::HALT, 0, 0, 0),
]),
..Default::default()
@@ -404,7 +405,7 @@ mod tests {
" 0014 HALT r0",
" 0000 LOAD_CONST r1, const[0]",
" 0001 RETURN r1",
- " 0003 HALT r0",
+ " 0004 HALT r0",
];
for line in &expected {
assert!(lines.contains(line), "missing line: {line}\n{text}");
diff --git a/crates/oxide_bytecode/src/opcode.rs b/crates/oxide_bytecode/src/opcode.rs
index 37702d06..8e7f33c3 100644
--- a/crates/oxide_bytecode/src/opcode.rs
+++ b/crates/oxide_bytecode/src/opcode.rs
@@ -824,10 +824,11 @@ pub fn ext_word_count(bytecode: &[Instr], pc: usize) -> usize {
| OpCode::GET_PRIVATE
| OpCode::SET_PRIVATE
| OpCode::PRIVATE_BRAND_IN => 2,
- // 逃出计数 ext:BREAK/CONTINUE/RETURN 恒带 1 个 pack_escape_counts 字
- // (for-of/for-in 逃出层数打包);lower 对这三条无条件落 ext 字,
- // dispatch 经 read_escape_counts 消费,扫描必须同步跳过以免错位。
- OpCode::BREAK | OpCode::CONTINUE | OpCode::RETURN => 1,
+ // 逃出计数 ext:BREAK/CONTINUE/RETURN 恒带 2 个字——第一字
+ // pack_escape_counts(for-of/for-in 逃出层数打包),第二字 dispose_count
+ // (逃出资源条数);lower 对这三条无条件落 ext 字,dispatch 经
+ // read_escape_counts 消费,扫描必须同步跳过以免错位。
+ OpCode::BREAK | OpCode::CONTINUE | OpCode::RETURN => 2,
OpCode::CALL_SPREAD | OpCode::NEW_EXPRESSION_SPREAD | OpCode::SUPER_CALL_SPREAD => {
let header = bytecode.get(pc + 1).copied().unwrap_or(0);
1 + (header & 0xFF) as usize + ((header >> 8) & 0xFF) as usize
@@ -972,11 +973,11 @@ mod tests {
// IC 族固定 8 字。
let ic = [encode(OpCode::IC_GET_PROP, 0, 0, 0); IC_EXT_WORDS + 1];
assert_eq!(ext_word_count(&ic, 0), IC_EXT_WORDS);
- // 1 字族(含 BREAK/CONTINUE/RETURN 逃出计数)。
+ // 1 字族。
assert_eq!(ext_word_count(&[encode(OpCode::CALL, 0, 0, 0), 3], 0), 1);
- assert_eq!(ext_word_count(&[encode(OpCode::BREAK, 0, 0, 0), 1], 0), 1);
- assert_eq!(ext_word_count(&[encode(OpCode::RETURN, 0, 0, 0), 1], 0), 1);
- // 2 字族。
+ // 2 字族(含 BREAK/CONTINUE/RETURN 逃出计数:迭代器打包字 + dispose_count 字)。
+ assert_eq!(ext_word_count(&[encode(OpCode::BREAK, 0, 0, 0), 1, 2], 0), 2);
+ assert_eq!(ext_word_count(&[encode(OpCode::RETURN, 0, 0, 0), 1, 2], 0), 2);
assert_eq!(ext_word_count(&[encode(OpCode::GET_PRIVATE, 0, 0, 0), 1, 2], 0), 2);
// 变长族:spread 首字 nstatic|nspread、TEMPLATE_STR 段数、GET_TEMPLATE_OBJECT 2+2n、
// CONCAT_N=n、NEW_OBJECT=a 槽属性数。
diff --git a/crates/oxide_emit/src/class/emit.rs b/crates/oxide_emit/src/class/emit.rs
index bf3cbc3d..369b6fc2 100644
--- a/crates/oxide_emit/src/class/emit.rs
+++ b/crates/oxide_emit/src/class/emit.rs
@@ -316,7 +316,7 @@ impl Emitter {
module.insts.extend(field_ctx.insts);
module.constants = field_ctx.constants;
module.n_registers = field_ctx.max_regs.max(1);
- module.insts.push(Inst::ret(Operand::Reg(undef_reg), 0, 0));
+ module.insts.push(Inst::ret(Operand::Reg(undef_reg), 0, 0, 0));
}
module
};
diff --git a/crates/oxide_emit/src/emit_ctx.rs b/crates/oxide_emit/src/emit_ctx.rs
index 2d79917d..0394a787 100644
--- a/crates/oxide_emit/src/emit_ctx.rs
+++ b/crates/oxide_emit/src/emit_ctx.rs
@@ -50,7 +50,6 @@ pub(crate) struct LoopEntry {
pub(crate) v_reg: u32,
/// 循环打开时已打开的释放作用域数(break/continue/return 逃出时据此
/// 计算需穿越释放的作用域层数)。
- #[allow(dead_code)]
pub(crate) dispose_depth_at_open: usize,
}
@@ -88,7 +87,6 @@ pub struct LabelScope {
/// 标签打开时已打开的 for-in 循环数。
pub(crate) for_in_depth_at_open: usize,
/// 标签打开时已打开的释放作用域数(break 逃出时据此计算需穿越释放的层数)。
- #[allow(dead_code)]
pub(crate) dispose_depth_at_open: usize,
/// 标签目标出口结果寄存器:迭代标签取所包裹循环的 `v_reg`;非迭代标签仅当
/// 体含指向本标签的 break 时分配(体正常完成回写、break 携值写入)。
@@ -104,7 +102,6 @@ pub(crate) struct SwitchEntry {
pub(crate) for_of_depth_at_open: usize,
pub(crate) for_in_depth_at_open: usize,
/// switch 打开时已打开的释放作用域数(switch 内 break 逃出时据此计算穿越层数)。
- #[allow(dead_code)]
pub(crate) dispose_depth_at_open: usize,
pub(crate) result_reg: u32,
}
diff --git a/crates/oxide_emit/src/function_body.rs b/crates/oxide_emit/src/function_body.rs
index 5143e19a..21cf816f 100644
--- a/crates/oxide_emit/src/function_body.rs
+++ b/crates/oxide_emit/src/function_body.rs
@@ -509,18 +509,18 @@ impl Emitter {
}
if is_expression_body {
if let Some(reg) = last_result_reg {
- ctx.inst(Inst::ret(Operand::Reg(reg), 0, 0));
+ ctx.inst(Inst::ret(Operand::Reg(reg), 0, 0, 0));
} else {
let undef_idx = ctx.add_constant(Constant::Undefined);
let undef_reg = ctx.alloc_reg();
ctx.inst(Inst::load_const(Operand::Reg(undef_reg), undef_idx));
- ctx.inst(Inst::ret(Operand::Reg(undef_reg), 0, 0));
+ ctx.inst(Inst::ret(Operand::Reg(undef_reg), 0, 0, 0));
}
} else {
let undef_idx = ctx.add_constant(Constant::Undefined);
let undef_reg = ctx.alloc_reg();
ctx.inst(Inst::load_const(Operand::Reg(undef_reg), undef_idx));
- ctx.inst(Inst::ret(Operand::Reg(undef_reg), 0, 0));
+ ctx.inst(Inst::ret(Operand::Reg(undef_reg), 0, 0, 0));
}
// 调用契约参数段只含固定形参:rest 是函数体内普通变量,不在 VM 实参传递区。
diff --git a/crates/oxide_emit/src/module.rs b/crates/oxide_emit/src/module.rs
index ba695081..7b57a148 100644
--- a/crates/oxide_emit/src/module.rs
+++ b/crates/oxide_emit/src/module.rs
@@ -938,9 +938,9 @@ impl Emitter {
let undef_idx = ctx.add_constant(Constant::Undefined);
let r = ctx.alloc_reg();
ctx.inst(Inst::load_const(Operand::Reg(r), undef_idx));
- ctx.inst(Inst::ret(Operand::Reg(r), 0, 0));
+ ctx.inst(Inst::ret(Operand::Reg(r), 0, 0, 0));
} else {
- ctx.inst(Inst::ret(Operand::Reg(ns_reg), 0, 0));
+ ctx.inst(Inst::ret(Operand::Reg(ns_reg), 0, 0, 0));
}
Ok(())
}
@@ -1003,7 +1003,7 @@ impl Emitter {
let kind_reg = self.load_string_const(kind, &mut ctx);
let content_reg = self.load_string_const(content, &mut ctx);
let val_reg = self.emit_module_call(&mut ctx, "__moduleData", &[kind_reg, content_reg])?;
- ctx.inst(Inst::ret(Operand::Reg(val_reg), 0, 0));
+ ctx.inst(Inst::ret(Operand::Reg(val_reg), 0, 0, 0));
Ok(ctx.assemble_ir(ParamLayout { base: 0, count: 0 }, None))
}
diff --git a/crates/oxide_emit/src/stmt/basic/break_continue.rs b/crates/oxide_emit/src/stmt/basic/break_continue.rs
index 51dd5e48..ee800478 100644
--- a/crates/oxide_emit/src/stmt/basic/break_continue.rs
+++ b/crates/oxide_emit/src/stmt/basic/break_continue.rs
@@ -33,46 +33,51 @@ impl Emitter {
pub(crate) fn emit_break_statement(
&self, stmt: &oxide_parser::BreakStatement, ctx: &mut CompileCtx,
) -> Result