mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
feat: 捕获 cell 按绑定身份换键
This commit is contained in:
Generated
+18
-18
@@ -1095,7 +1095,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_builtins"
|
name = "oxide_builtins"
|
||||||
version = "0.8.7"
|
version = "0.8.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"fast-float",
|
"fast-float",
|
||||||
@@ -1120,7 +1120,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_bytecode"
|
name = "oxide_bytecode"
|
||||||
version = "0.8.7"
|
version = "0.8.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
"oxide_log",
|
"oxide_log",
|
||||||
@@ -1128,7 +1128,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_cfg"
|
name = "oxide_cfg"
|
||||||
version = "0.8.7"
|
version = "0.8.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_emit",
|
"oxide_emit",
|
||||||
@@ -1139,7 +1139,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_cli"
|
name = "oxide_cli"
|
||||||
version = "0.8.7"
|
version = "0.8.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term",
|
"ansi_term",
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
@@ -1159,7 +1159,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_code_cache"
|
name = "oxide_code_cache"
|
||||||
version = "0.8.7"
|
version = "0.8.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lru",
|
"lru",
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
@@ -1168,7 +1168,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_compiler"
|
name = "oxide_compiler"
|
||||||
version = "0.8.7"
|
version = "0.8.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_cfg",
|
"oxide_cfg",
|
||||||
@@ -1187,7 +1187,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_dce"
|
name = "oxide_dce"
|
||||||
version = "0.8.7"
|
version = "0.8.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_cfg",
|
"oxide_cfg",
|
||||||
@@ -1201,7 +1201,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_emit"
|
name = "oxide_emit"
|
||||||
version = "0.8.7"
|
version = "0.8.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
"oxc_allocator",
|
"oxc_allocator",
|
||||||
@@ -1216,7 +1216,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_ir"
|
name = "oxide_ir"
|
||||||
version = "0.8.7"
|
version = "0.8.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_log",
|
"oxide_log",
|
||||||
@@ -1225,7 +1225,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_kernel"
|
name = "oxide_kernel"
|
||||||
version = "0.8.7"
|
version = "0.8.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"dashmap",
|
"dashmap",
|
||||||
@@ -1240,7 +1240,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_liveness"
|
name = "oxide_liveness"
|
||||||
version = "0.8.7"
|
version = "0.8.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_cfg",
|
"oxide_cfg",
|
||||||
@@ -1252,7 +1252,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_log"
|
name = "oxide_log"
|
||||||
version = "0.8.7"
|
version = "0.8.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-appender",
|
"tracing-appender",
|
||||||
@@ -1261,7 +1261,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_parser"
|
name = "oxide_parser"
|
||||||
version = "0.8.7"
|
version = "0.8.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxc_allocator",
|
"oxc_allocator",
|
||||||
"oxc_ast",
|
"oxc_ast",
|
||||||
@@ -1276,7 +1276,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_regalloc"
|
name = "oxide_regalloc"
|
||||||
version = "0.8.7"
|
version = "0.8.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_cfg",
|
"oxide_cfg",
|
||||||
@@ -1292,7 +1292,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_runtime_api"
|
name = "oxide_runtime_api"
|
||||||
version = "0.8.7"
|
version = "0.8.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
@@ -1304,7 +1304,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_test262"
|
name = "oxide_test262"
|
||||||
version = "0.8.7"
|
version = "0.8.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_compiler",
|
"oxide_compiler",
|
||||||
@@ -1321,7 +1321,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_types"
|
name = "oxide_types"
|
||||||
version = "0.8.7"
|
version = "0.8.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"hashbrown 0.14.5",
|
"hashbrown 0.14.5",
|
||||||
@@ -1333,7 +1333,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_vm"
|
name = "oxide_vm"
|
||||||
version = "0.8.7"
|
version = "0.8.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
|||||||
+1
-1
@@ -22,7 +22,7 @@ members = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.8.7"
|
version = "0.8.8"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
rust-version = "1.80"
|
rust-version = "1.80"
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ mod upvalues;
|
|||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
pub(crate) use captured::collect_captured_bindings;
|
pub(crate) use captured::collect_captured_bindings;
|
||||||
|
pub(crate) use names::collect_block_level_decl_names;
|
||||||
pub(crate) use names::collect_direct_lexical_names;
|
pub(crate) use names::collect_direct_lexical_names;
|
||||||
pub(crate) use names::collect_own_binding_names;
|
pub(crate) use names::collect_own_binding_names;
|
||||||
pub(crate) use names::collect_top_level_function_names;
|
pub(crate) use names::collect_top_level_function_names;
|
||||||
|
|||||||
@@ -181,6 +181,116 @@ pub(crate) fn collect_direct_lexical_names(stmts: &[Statement]) -> HashSet<Strin
|
|||||||
names
|
names
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 收集块级声明名(块内 let/const/class、catch 参数、for 头 let/const):
|
||||||
|
/// 这些名字是块作用域绑定,遮蔽同名顶层 tier 名时,tier 名须保留在捕获集,
|
||||||
|
/// 块级绑定才能追加新索引供闭包捕获。顶层直接子级 let/const/class 是顶层
|
||||||
|
/// 词法绑定,不纳;var 声明不纳(var 是函数/全局作用域)。
|
||||||
|
pub(crate) fn collect_block_level_decl_names(stmts: &[Statement]) -> HashSet<String> {
|
||||||
|
let mut names = HashSet::new();
|
||||||
|
collect_block_level_names_stmt(stmts, &mut names, true);
|
||||||
|
names
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 递归遍历语句树收集块级声明名。`top` 标记当前层是否为顶层(顶层直接子级
|
||||||
|
/// let/const/class 是顶层词法绑定,非块级)。
|
||||||
|
fn collect_block_level_names_stmt(stmts: &[Statement], out: &mut HashSet<String>, top: bool) {
|
||||||
|
for stmt in stmts {
|
||||||
|
match stmt {
|
||||||
|
Statement::VariableDeclaration(vd) => {
|
||||||
|
if matches!(vd.kind, VariableDeclarationKind::Var) || top {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for d in &vd.declarations {
|
||||||
|
collect_binding_pattern_names(&d.id, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Statement::ClassDeclaration(cd) => {
|
||||||
|
if !top {
|
||||||
|
if let Some(id) = &cd.id {
|
||||||
|
out.insert(id.name.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Statement::BlockStatement(b) => collect_block_level_names_stmt(&b.body, out, false),
|
||||||
|
Statement::IfStatement(is) => {
|
||||||
|
collect_block_level_names_stmt(std::slice::from_ref(&is.consequent), out, false);
|
||||||
|
if let Some(alt) = &is.alternate {
|
||||||
|
collect_block_level_names_stmt(std::slice::from_ref(alt), out, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Statement::WhileStatement(w) => collect_block_level_names_stmt(std::slice::from_ref(&w.body), out, false),
|
||||||
|
Statement::DoWhileStatement(d) => collect_block_level_names_stmt(std::slice::from_ref(&d.body), out, false),
|
||||||
|
Statement::ForStatement(f) => {
|
||||||
|
if let Some(oxide_parser::ForStatementInit::VariableDeclaration(vd)) = &f.init {
|
||||||
|
if !matches!(vd.kind, VariableDeclarationKind::Var) {
|
||||||
|
for d in &vd.declarations {
|
||||||
|
collect_binding_pattern_names(&d.id, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
collect_block_level_names_stmt(std::slice::from_ref(&f.body), out, false);
|
||||||
|
}
|
||||||
|
Statement::ForInStatement(fi) => {
|
||||||
|
if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = &fi.left {
|
||||||
|
if !matches!(vd.kind, VariableDeclarationKind::Var) {
|
||||||
|
collect_for_left_decl_names(&fi.left, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
collect_block_level_names_stmt(std::slice::from_ref(&fi.body), out, false);
|
||||||
|
}
|
||||||
|
Statement::ForOfStatement(fo) => {
|
||||||
|
if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = &fo.left {
|
||||||
|
if !matches!(vd.kind, VariableDeclarationKind::Var) {
|
||||||
|
collect_for_left_decl_names(&fo.left, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
collect_block_level_names_stmt(std::slice::from_ref(&fo.body), out, false);
|
||||||
|
}
|
||||||
|
Statement::SwitchStatement(sw) => {
|
||||||
|
for case in &sw.cases {
|
||||||
|
collect_block_level_names_stmt(&case.consequent, out, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Statement::TryStatement(ts) => {
|
||||||
|
collect_block_level_names_stmt(&ts.block.body, out, false);
|
||||||
|
if let Some(h) = &ts.handler {
|
||||||
|
if let Some(param) = &h.param {
|
||||||
|
collect_binding_pattern_names(¶m.pattern, out);
|
||||||
|
}
|
||||||
|
collect_block_level_names_stmt(&h.body.body, out, false);
|
||||||
|
}
|
||||||
|
if let Some(f) = &ts.finalizer {
|
||||||
|
collect_block_level_names_stmt(&f.body, out, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Statement::LabeledStatement(ls) => {
|
||||||
|
collect_block_level_names_stmt(std::slice::from_ref(&ls.body), out, false)
|
||||||
|
}
|
||||||
|
Statement::WithStatement(ws) => collect_block_level_names_stmt(std::slice::from_ref(&ws.body), out, false),
|
||||||
|
Statement::ExportNamedDeclaration(exp) => {
|
||||||
|
if let Some(decl) = &exp.declaration {
|
||||||
|
match decl {
|
||||||
|
oxide_parser::Declaration::VariableDeclaration(vd) => {
|
||||||
|
if !matches!(vd.kind, VariableDeclarationKind::Var) && !top {
|
||||||
|
for d in &vd.declarations {
|
||||||
|
collect_binding_pattern_names(&d.id, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
oxide_parser::Declaration::ClassDeclaration(cd) if !top => {
|
||||||
|
if let Some(id) = &cd.id {
|
||||||
|
out.insert(id.name.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// 收集当前函数作用域声明的绑定名(参数 + 变量/函数声明,含嵌套 block,不含嵌套函数体)。
|
/// 收集当前函数作用域声明的绑定名(参数 + 变量/函数声明,含嵌套 block,不含嵌套函数体)。
|
||||||
pub(crate) fn collect_own_binding_names(param_names: &[&str], stmts: &[Statement]) -> HashSet<String> {
|
pub(crate) fn collect_own_binding_names(param_names: &[&str], stmts: &[Statement]) -> HashSet<String> {
|
||||||
let mut names = HashSet::new();
|
let mut names = HashSet::new();
|
||||||
|
|||||||
@@ -95,9 +95,13 @@ pub struct CompileCtx {
|
|||||||
/// 消除符号表时序依赖与 cell 索引错位。
|
/// 消除符号表时序依赖与 cell 索引错位。
|
||||||
pub(crate) captured_bindings: BTreeMap<String, u8>,
|
pub(crate) captured_bindings: BTreeMap<String, u8>,
|
||||||
/// 下一可用 cell 索引(计数器):捕获分析后初始化为名字集大小(函数级索引
|
/// 下一可用 cell 索引(计数器):捕获分析后初始化为名字集大小(函数级索引
|
||||||
/// 0..n-1 占满),块级遮蔽绑定预声明追加与合成 cell 经 `alloc_cell_idx`
|
/// 0..n-1 占满),块级遮蔽绑定预声明追加、catch 参数就地声明与合成 cell 经
|
||||||
/// 递增取号,保证与函数级名字排序索引及历次追加互不碰撞。
|
/// `alloc_cell_idx` 递增取号,保证与函数级名字排序索引及历次追加互不碰撞。
|
||||||
pub(crate) next_cell_idx: u8,
|
pub(crate) next_cell_idx: u8,
|
||||||
|
/// 词法循环头(C-for / for-in / for-of)名集:头名索引由 ForHeadEnv 覆盖
|
||||||
|
/// 捕获映射分配(TDZ 占位与体区 fresh cell),声明点据此走映射回退而非
|
||||||
|
/// 就地追加新索引。begin 时并入、restore 时移除,嵌套循环成对。
|
||||||
|
pub(crate) for_head_env_names: HashSet<String>,
|
||||||
/// 正在发射的 C 风格 for 头 let/const 声明名(含解构叶)。头名不像块级
|
/// 正在发射的 C 风格 for 头 let/const 声明名(含解构叶)。头名不像块级
|
||||||
/// let/const 那样在块入口预声明,init 表达式内创建的嵌套函数引用同头尚未
|
/// let/const 那样在块入口预声明,init 表达式内创建的嵌套函数引用同头尚未
|
||||||
/// declare 的前向名时,父捕获可见性过滤据此放行;init 发射完毕后移除,
|
/// declare 的前向名时,父捕获可见性过滤据此放行;init 发射完毕后移除,
|
||||||
@@ -253,6 +257,7 @@ impl CompileCtx {
|
|||||||
block_fn_entry_mats: Vec::new(),
|
block_fn_entry_mats: Vec::new(),
|
||||||
captured_bindings: BTreeMap::new(),
|
captured_bindings: BTreeMap::new(),
|
||||||
next_cell_idx: 0,
|
next_cell_idx: 0,
|
||||||
|
for_head_env_names: HashSet::new(),
|
||||||
pending_for_head_names: HashSet::new(),
|
pending_for_head_names: HashSet::new(),
|
||||||
global_tier_names: HashSet::new(),
|
global_tier_names: HashSet::new(),
|
||||||
upvalue_const_flags: HashSet::new(),
|
upvalue_const_flags: HashSet::new(),
|
||||||
@@ -426,13 +431,27 @@ impl CompileCtx {
|
|||||||
/// 登记)时返回 (cell_idx, binding_reg)。索引优先取绑定自身字段(函数级
|
/// 登记)时返回 (cell_idx, binding_reg)。索引优先取绑定自身字段(函数级
|
||||||
/// 回填与块级追加的真源),绑定未分配索引时回退捕获映射(for 头覆盖 /
|
/// 回填与块级追加的真源),绑定未分配索引时回退捕获映射(for 头覆盖 /
|
||||||
/// catch 参数等容器面,后续子任务逐面收编)。块级遮蔽绑定在块退出后不可
|
/// catch 参数等容器面,后续子任务逐面收编)。块级遮蔽绑定在块退出后不可
|
||||||
/// 解析,返回 None(落全局解析),不得按名误读已失效 cell。
|
/// 解析,返回 None(落全局解析),不得按名误读已失效 cell。tier 绑定
|
||||||
|
/// (scope 0 顶层 var/函数)的全局对象属性是唯一存储,不建 cell;映射中
|
||||||
|
/// 被同名块级绑定保留的 entry 不属该 tier 绑定,回退不得命中——for 头
|
||||||
|
/// 前向名除外(头绑定未 declare,映射值是 ForHeadEnv 的 TDZ 索引)。
|
||||||
pub(crate) fn visible_cell(&self, name: &str) -> Option<(u8, u32)> {
|
pub(crate) fn visible_cell(&self, name: &str) -> Option<(u8, u32)> {
|
||||||
let (binding, _) = self.scopes.symbols.lookup_any_binding(name)?;
|
let (binding, scope_idx) = self.scopes.symbols.lookup_any_binding(name)?;
|
||||||
if self.is_implicit_global_reg(binding.reg) {
|
if self.is_implicit_global_reg(binding.reg) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let idx = binding.cell_idx.or_else(|| self.captured_bindings.get(name).copied())?;
|
// for 头前向名(C 风格 for 头 pending / for-in/for-of env)读 TDZ cell:
|
||||||
|
// 头绑定未 declare,按名回查命中外层同名 tier 绑定,映射回退须放行以命中
|
||||||
|
// ForHeadEnv 覆盖的 TDZ 索引。
|
||||||
|
let is_for_head = self.pending_for_head_names.contains(name) || self.for_head_env_names.contains(name);
|
||||||
|
let is_tier_binding = scope_idx == 0 && self.global_tier_names.contains(name);
|
||||||
|
let idx = binding.cell_idx.or_else(|| {
|
||||||
|
if is_tier_binding && !is_for_head {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
self.captured_bindings.get(name).copied()
|
||||||
|
}
|
||||||
|
})?;
|
||||||
Some((idx, binding.reg))
|
Some((idx, binding.reg))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -443,15 +462,54 @@ impl CompileCtx {
|
|||||||
self.captured_bindings = map;
|
self.captured_bindings = map;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 分配一个新 cell 索引:取当前计数器值并递增。块级遮蔽绑定预声明追加与
|
/// 分配一个新 cell 索引:取当前计数器值并递增。块级遮蔽绑定预声明追加、
|
||||||
/// 合成 cell 共用,分配序由发射序决定,跨 run 稳定。
|
/// catch 参数就地声明与合成 cell 共用,分配序由发射序决定,跨 run 稳定。
|
||||||
#[allow(dead_code)] // 块级遮蔽绑定预声明追加(后续子任务)消费,本件仅立计数器
|
|
||||||
pub(crate) fn alloc_cell_idx(&mut self) -> u8 {
|
pub(crate) fn alloc_cell_idx(&mut self) -> u8 {
|
||||||
let idx = self.next_cell_idx;
|
let idx = self.next_cell_idx;
|
||||||
self.next_cell_idx = self.next_cell_idx.saturating_add(1);
|
self.next_cell_idx = self.next_cell_idx.saturating_add(1);
|
||||||
idx
|
idx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 声明点 cell 索引解析:索引按绑定实例取(绑定自身字段是真源)。绑定未分配
|
||||||
|
/// 索引时,词法循环头名(ForHeadEnv 覆盖捕获映射)走映射回退;最内层为块
|
||||||
|
/// 作用域的就地声明(catch 参数)现场追加新索引并写回绑定,与函数级同名
|
||||||
|
/// 绑定的名字排序索引区分。名字不可见(隐式全局登记)或不在捕获集时返回
|
||||||
|
/// None,调用方落 with/全局臂。顶层 tier 名(顶层 var/函数)的全局对象属性
|
||||||
|
/// 是唯一存储,不建 cell,返回 None。
|
||||||
|
///
|
||||||
|
/// # 副作用
|
||||||
|
/// - 就地追加臂写回绑定 cell 索引并递增计数器;指令流不改动。
|
||||||
|
pub(crate) fn resolve_bind_cell_idx(&mut self, name: &str) -> Option<u8> {
|
||||||
|
let (existing, is_implicit, block_scope, for_head, is_tier) = {
|
||||||
|
let symbols = &self.scopes.symbols;
|
||||||
|
let (binding, scope_idx) = symbols.lookup_any_binding(name)?;
|
||||||
|
(
|
||||||
|
binding.cell_idx,
|
||||||
|
self.is_implicit_global_reg(binding.reg),
|
||||||
|
symbols.scopes.last().is_some_and(|s| s.kind == ScopeKind::BlockScope),
|
||||||
|
self.for_head_env_names.contains(name),
|
||||||
|
self.is_global_scope && self.global_tier_names.contains(name) && scope_idx == 0,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
if is_implicit {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
if let Some(idx) = existing {
|
||||||
|
return Some(idx);
|
||||||
|
}
|
||||||
|
if is_tier {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let base = *self.captured_bindings.get(name)?;
|
||||||
|
if block_scope && !for_head {
|
||||||
|
let fresh = self.alloc_cell_idx();
|
||||||
|
self.set_binding_cell_idx(name, fresh);
|
||||||
|
Some(fresh)
|
||||||
|
} else {
|
||||||
|
Some(base)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// 给最内层同名可见绑定写入 cell 索引(委托符号表)。
|
/// 给最内层同名可见绑定写入 cell 索引(委托符号表)。
|
||||||
pub(crate) fn set_binding_cell_idx(&mut self, name: &str, idx: u8) {
|
pub(crate) fn set_binding_cell_idx(&mut self, name: &str, idx: u8) {
|
||||||
self.scopes.symbols.set_binding_cell_idx(name, idx);
|
self.scopes.symbols.set_binding_cell_idx(name, idx);
|
||||||
@@ -459,10 +517,15 @@ impl CompileCtx {
|
|||||||
|
|
||||||
/// 函数级绑定 cell 索引回填:捕获集(名字排序分配)的索引写入对应绑定
|
/// 函数级绑定 cell 索引回填:捕获集(名字排序分配)的索引写入对应绑定
|
||||||
/// 实例,使解析点按绑定身份取索引。预声明完成后调用,函数级绑定(参数 /
|
/// 实例,使解析点按绑定身份取索引。预声明完成后调用,函数级绑定(参数 /
|
||||||
/// var / 直接子级词法 / 块级函数外层 var / arguments)此时已齐。
|
/// var / 直接子级词法 / 块级函数外层 var / arguments)此时已齐。顶层 tier
|
||||||
|
/// 名(顶层 var/函数)的全局对象属性是唯一存储,不回填 cell 索引。
|
||||||
pub(crate) fn backfill_captured_cell_idxs(&mut self) {
|
pub(crate) fn backfill_captured_cell_idxs(&mut self) {
|
||||||
let entries: Vec<(String, u8)> =
|
let entries: Vec<(String, u8)> = self
|
||||||
self.captured_bindings.iter().map(|(name, &idx)| (name.clone(), idx)).collect();
|
.captured_bindings
|
||||||
|
.iter()
|
||||||
|
.filter(|(name, _)| !(self.is_global_scope && self.global_tier_names.contains(*name)))
|
||||||
|
.map(|(name, &idx)| (name.clone(), idx))
|
||||||
|
.collect();
|
||||||
for (name, idx) in entries {
|
for (name, idx) in entries {
|
||||||
self.set_binding_cell_idx(&name, idx);
|
self.set_binding_cell_idx(&name, idx);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -655,14 +655,56 @@ impl Emitter {
|
|||||||
// upvalue 代表的祖父绑定在父函数体内恒可见,不参与过滤。
|
// upvalue 代表的祖父绑定在父函数体内恒可见,不参与过滤。
|
||||||
// C 风格 for 头 let/const 名在 init 内尚未 declare,但同头声明会为其
|
// C 风格 for 头 let/const 名在 init 内尚未 declare,但同头声明会为其
|
||||||
// 建 cell,前向捕获须按父捕获集保留(见 `pending_for_head_names`)。
|
// 建 cell,前向捕获须按父捕获集保留(见 `pending_for_head_names`)。
|
||||||
|
// 索引按父可见绑定实例取(块级遮蔽绑定持追加索引);词法循环头名
|
||||||
|
// (for-in/for-of 头绑定在右值区编译时未进符号表,按名回查会误命中
|
||||||
|
// 外层同名绑定)与 for 头前向名无条件取捕获映射值(ForHeadEnv 覆盖
|
||||||
|
// 索引或名字排序索引);绑定未分配索引的其余名(命名空间导入等)
|
||||||
|
// 回退映射值。顶层 tier 名(顶层 var/函数)已在捕获集剔除阶段出集,
|
||||||
|
// 不在此列。
|
||||||
let visible_parent_captured: BTreeMap<String, u8> = parent_ctx
|
let visible_parent_captured: BTreeMap<String, u8> = parent_ctx
|
||||||
.captured_bindings
|
.captured_bindings
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(n, _)| {
|
.filter(|(n, _)| {
|
||||||
|
// for 头前向名(C 风格 for 头 pending / for-in/for-of env):
|
||||||
|
// 头绑定未 declare,按名回查命中外层同名 tier 绑定,映射值是
|
||||||
|
// ForHeadEnv 的 TDZ 索引,须保留为 upvalue。
|
||||||
|
let for_head = parent_ctx.pending_for_head_names.contains(n.as_str())
|
||||||
|
|| parent_ctx.for_head_env_names.contains(n.as_str());
|
||||||
|
// tier 绑定(scope 0 顶层 var/函数):全局对象属性是唯一存储,
|
||||||
|
// 不建 cell;嵌套函数直读全局,不入 upvalue。映射中为同名块级
|
||||||
|
// 绑定保留的 entry 不属该 tier 绑定,不得按名捕获。
|
||||||
|
let tier =
|
||||||
|
!for_head
|
||||||
|
&& parent_ctx.scopes.symbols.lookup_any_binding(n.as_str()).is_some_and(
|
||||||
|
|(_, scope_idx)| scope_idx == 0 && parent_ctx.global_tier_names.contains(n.as_str()),
|
||||||
|
);
|
||||||
|
if tier {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
parent_ctx.visible_binding_reg(n.as_str()).is_some()
|
parent_ctx.visible_binding_reg(n.as_str()).is_some()
|
||||||
|| parent_ctx.pending_for_head_names.contains(n.as_str())
|
|| parent_ctx.pending_for_head_names.contains(n.as_str())
|
||||||
})
|
})
|
||||||
.map(|(n, &i)| (n.clone(), i))
|
.map(|(n, &i)| {
|
||||||
|
let idx = if parent_ctx.for_head_env_names.contains(n.as_str())
|
||||||
|
|| parent_ctx.pending_for_head_names.contains(n.as_str())
|
||||||
|
{
|
||||||
|
// 词法循环头名:头绑定在右值区编译时未进符号表(按名回查
|
||||||
|
// 会误命中外层同名绑定),索引由 ForHeadEnv 覆盖映射分配,
|
||||||
|
// 无条件取映射值。
|
||||||
|
i
|
||||||
|
} else {
|
||||||
|
// 其余名按绑定实例取索引(块级遮蔽绑定持追加索引);
|
||||||
|
// 绑定未分配索引(命名空间导入等绑定点走映射值不写绑定
|
||||||
|
// 字段)回退映射值,与基线按名取索引同口径。
|
||||||
|
parent_ctx
|
||||||
|
.scopes
|
||||||
|
.symbols
|
||||||
|
.lookup_any_binding(n.as_str())
|
||||||
|
.and_then(|(b, _)| b.cell_idx)
|
||||||
|
.unwrap_or(i)
|
||||||
|
};
|
||||||
|
(n.clone(), idx)
|
||||||
|
})
|
||||||
.collect();
|
.collect();
|
||||||
ctx.current_upvalue_captures = collect_upvalue_names(
|
ctx.current_upvalue_captures = collect_upvalue_names(
|
||||||
body_stmts,
|
body_stmts,
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
//! emit 前置 pass,声明预登记:函数/var 声明提升预声明、块级函数声明按 ES2015
|
//! emit 前置 pass,声明预登记:函数/var 声明提升预声明、块级函数声明按 ES2015
|
||||||
//! 块绑定预声明、let/const/class 建 TDZ 占位。
|
//! 块绑定预声明、let/const/class 建 TDZ 占位。
|
||||||
|
|
||||||
|
use crate::symbol_table::ScopeKind;
|
||||||
use crate::{CompileCtx, Emitter};
|
use crate::{CompileCtx, Emitter};
|
||||||
|
use oxide_bytecode::opcode::OpCode;
|
||||||
|
use oxide_ir::inst::Inst;
|
||||||
|
use oxide_ir::operand::Operand;
|
||||||
use oxide_parser::{BindingPattern, Declaration, ExportDefaultDeclarationKind, Statement, VariableDeclarationKind};
|
use oxide_parser::{BindingPattern, Declaration, ExportDefaultDeclarationKind, Statement, VariableDeclarationKind};
|
||||||
|
|
||||||
impl Emitter {
|
impl Emitter {
|
||||||
@@ -395,6 +399,29 @@ impl Emitter {
|
|||||||
},
|
},
|
||||||
is_const,
|
is_const,
|
||||||
);
|
);
|
||||||
|
// 块级遮蔽绑定:名字在捕获集且最内层为块作用域时,追加新 cell
|
||||||
|
// 索引并发未初始化 MAKE_CELL(TDZ 占位)。声明点与闭包捕获据
|
||||||
|
// 绑定字段走新索引,不原位覆写函数级同名绑定的名字排序索引;
|
||||||
|
// 函数作用域调用点(函数体/顶层直接子级)名字排序索引归该
|
||||||
|
// 绑定所有,不追加。
|
||||||
|
if ctx.captured_bindings.contains_key(bi.name.as_str())
|
||||||
|
&& ctx
|
||||||
|
.scopes
|
||||||
|
.symbols
|
||||||
|
.scopes
|
||||||
|
.last()
|
||||||
|
.is_some_and(|s| s.kind == ScopeKind::BlockScope)
|
||||||
|
{
|
||||||
|
let idx = ctx.alloc_cell_idx();
|
||||||
|
ctx.set_binding_cell_idx(bi.name.as_str(), idx);
|
||||||
|
let undef_reg = self.emit_undefined(ctx);
|
||||||
|
ctx.inst(Inst::new(
|
||||||
|
OpCode::MAKE_CELL,
|
||||||
|
Operand::Reg(undef_reg),
|
||||||
|
Operand::Imm(idx as u16 | 0x0100),
|
||||||
|
Operand::None,
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
BindingPattern::ArrayPattern(ap) => {
|
BindingPattern::ArrayPattern(ap) => {
|
||||||
for e in ap.elements.iter().flatten() {
|
for e in ap.elements.iter().flatten() {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ use oxide_ir::IRFunction;
|
|||||||
use oxide_parser::Statement;
|
use oxide_parser::Statement;
|
||||||
|
|
||||||
use crate::capture::{
|
use crate::capture::{
|
||||||
collect_captured_bindings, collect_direct_lexical_names, collect_own_binding_names,
|
collect_block_level_decl_names, collect_captured_bindings, collect_direct_lexical_names, collect_own_binding_names,
|
||||||
collect_top_level_function_names, collect_top_level_function_names_ordered, collect_var_binding_names,
|
collect_top_level_function_names, collect_top_level_function_names_ordered, collect_var_binding_names,
|
||||||
};
|
};
|
||||||
use crate::compile_ctx::CompileCtx;
|
use crate::compile_ctx::CompileCtx;
|
||||||
@@ -350,7 +350,12 @@ impl Emitter {
|
|||||||
}
|
}
|
||||||
ctx.global_tier_names = tier_names;
|
ctx.global_tier_names = tier_names;
|
||||||
ctx.set_captured_bindings(collect_captured_bindings(&program.body, &[], &ctx.own_bindings));
|
ctx.set_captured_bindings(collect_captured_bindings(&program.body, &[], &ctx.own_bindings));
|
||||||
ctx.captured_bindings.retain(|n, _| !ctx.global_tier_names.contains(n));
|
// 顶层 tier 名(顶层 var/函数)的全局对象属性是唯一存储,从捕获集剔除;
|
||||||
|
// 被同名块级绑定(catch 参数 / 块级 let/const)遮蔽时保留,使块级绑定能
|
||||||
|
// 追加新索引供闭包捕获(顶层 var 本身不建 cell,回填与解析点均跳过)。
|
||||||
|
let block_level_names = collect_block_level_decl_names(&program.body);
|
||||||
|
ctx.captured_bindings
|
||||||
|
.retain(|n, _| !ctx.global_tier_names.contains(n) || block_level_names.contains(n));
|
||||||
// 顶层函数级绑定 cell 索引回填:预声明已完成,绑定已齐。
|
// 顶层函数级绑定 cell 索引回填:预声明已完成,绑定已齐。
|
||||||
ctx.backfill_captured_cell_idxs();
|
ctx.backfill_captured_cell_idxs();
|
||||||
|
|
||||||
@@ -358,9 +363,10 @@ impl Emitter {
|
|||||||
// 声明语句执行前创建的闭包读取到 undefined(脚本 GlobalDeclarationInstantiation
|
// 声明语句执行前创建的闭包读取到 undefined(脚本 GlobalDeclarationInstantiation
|
||||||
// 语义),而非占位 cell 的 TDZ 误报。声明语句的 MAKE_CELL 覆盖此初值。
|
// 语义),而非占位 cell 的 TDZ 误报。声明语句的 MAKE_CELL 覆盖此初值。
|
||||||
// 名集保持 var-only:函数声明名从不入捕获集(tier 剔除),无需入口 cell。
|
// 名集保持 var-only:函数声明名从不入捕获集(tier 剔除),无需入口 cell。
|
||||||
|
// tier 名(全局对象属性为唯一存储)不建入口 cell。
|
||||||
let mut var_names: Vec<String> = var_names
|
let mut var_names: Vec<String> = var_names
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|n| ctx.captured_bindings.contains_key(n))
|
.filter(|n| ctx.captured_bindings.contains_key(n) && !ctx.global_tier_names.contains(n))
|
||||||
.collect();
|
.collect();
|
||||||
// HashSet 迭代序带随机种子,排序后入口 MAKE_CELL 发射序跨进程稳定。
|
// HashSet 迭代序带随机种子,排序后入口 MAKE_CELL 发射序跨进程稳定。
|
||||||
var_names.sort();
|
var_names.sort();
|
||||||
|
|||||||
@@ -86,9 +86,10 @@ impl Emitter {
|
|||||||
}
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
// 索引按绑定实例取(`visible_cell` 已含可见性判定):函数级绑定走回填
|
// 索引按绑定实例取(`resolve_bind_cell_idx` 已含可见性判定):函数级
|
||||||
// 索引,绑定未分配索引时回退捕获映射(for 头覆盖等容器面)。
|
// 绑定走回填索引,块级遮蔽绑定走预声明追加索引,catch 参数等块作用域
|
||||||
if let Some((cell_idx, _)) = ctx.visible_cell(name) {
|
// 就地声明现场追加;词法循环头名走捕获映射回退。
|
||||||
|
if let Some(cell_idx) = ctx.resolve_bind_cell_idx(name) {
|
||||||
let op = if fresh_cell { OpCode::MAKE_CELL_FRESH } else { OpCode::MAKE_CELL };
|
let op = if fresh_cell { OpCode::MAKE_CELL_FRESH } else { OpCode::MAKE_CELL };
|
||||||
ctx.inst(Inst::new(op, Operand::Reg(src_reg), Operand::Imm(cell_idx as u16), Operand::None));
|
ctx.inst(Inst::new(op, Operand::Reg(src_reg), Operand::Imm(cell_idx as u16), Operand::None));
|
||||||
// C 风格 for 头绑定:cell 之外补写绑定寄存器——循环体/test/update 读寄存器,
|
// C 风格 for 头绑定:cell 之外补写绑定寄存器——循环体/test/update 读寄存器,
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ impl Emitter {
|
|||||||
};
|
};
|
||||||
(target, false)
|
(target, false)
|
||||||
};
|
};
|
||||||
if let Some(&cell_idx) = ctx.captured_bindings.get(bi.name.as_str()) {
|
if let Some(cell_idx) = ctx.resolve_bind_cell_idx(bi.name.as_str()) {
|
||||||
// 被捕获绑定的 cell 在函数入口已实例化(undefined);声明语句
|
// 被捕获绑定的 cell 在函数入口已实例化(undefined);声明语句
|
||||||
// 不赋值,仅首次声明刷新初值,已绑定的 cell 保留现值。
|
// 不赋值,仅首次声明刷新初值,已绑定的 cell 保留现值。
|
||||||
if !already_bound {
|
if !already_bound {
|
||||||
|
|||||||
@@ -71,8 +71,9 @@ impl Emitter {
|
|||||||
/// 3. 发射未初始化 MAKE_CELL 并覆盖映射。
|
/// 3. 发射未初始化 MAKE_CELL 并覆盖映射。
|
||||||
///
|
///
|
||||||
/// # 副作用
|
/// # 副作用
|
||||||
/// - 捕获映射被改动;须经 `switch_for_head_env_to_body` 与
|
/// - 捕获映射与头名集(`for_head_env_names`)被改动;须经
|
||||||
/// `restore_for_head_env` 成对收尾,防头名泄漏进兄弟语句的捕获映射。
|
/// `switch_for_head_env_to_body` 与 `restore_for_head_env` 成对收尾,
|
||||||
|
/// 防头名泄漏进兄弟语句的捕获判定。
|
||||||
pub(crate) fn begin_for_head_env(&self, names: Vec<String>, ctx: &mut CompileCtx) -> Result<ForHeadEnv, String> {
|
pub(crate) fn begin_for_head_env(&self, names: Vec<String>, ctx: &mut CompileCtx) -> Result<ForHeadEnv, String> {
|
||||||
let mut entries = Vec::with_capacity(names.len());
|
let mut entries = Vec::with_capacity(names.len());
|
||||||
let mut next = ctx.captured_bindings.values().copied().max().map_or(0, |m| m.saturating_add(1));
|
let mut next = ctx.captured_bindings.values().copied().max().map_or(0, |m| m.saturating_add(1));
|
||||||
@@ -81,6 +82,8 @@ impl Emitter {
|
|||||||
let tdz_idx = next;
|
let tdz_idx = next;
|
||||||
next = next.saturating_add(1);
|
next = next.saturating_add(1);
|
||||||
ctx.captured_bindings.insert(name.clone(), tdz_idx);
|
ctx.captured_bindings.insert(name.clone(), tdz_idx);
|
||||||
|
// 头名登记:声明点索引解析据此走映射回退,不就地追加新索引。
|
||||||
|
ctx.for_head_env_names.insert(name.clone());
|
||||||
// MAKE_CELL 的 16 位立即数:低字节是 cell 索引,高字节 bit 0 是
|
// MAKE_CELL 的 16 位立即数:低字节是 cell 索引,高字节 bit 0 是
|
||||||
// 未初始化标记。标志折入立即数高字节(0x0100),dispatch 侧按字节
|
// 未初始化标记。标志折入立即数高字节(0x0100),dispatch 侧按字节
|
||||||
// 拆回两字段。
|
// 拆回两字段。
|
||||||
@@ -93,6 +96,7 @@ impl Emitter {
|
|||||||
));
|
));
|
||||||
entries.push((name, saved, tdz_idx, 0));
|
entries.push((name, saved, tdz_idx, 0));
|
||||||
}
|
}
|
||||||
|
ctx.next_cell_idx = next;
|
||||||
Ok(ForHeadEnv { entries })
|
Ok(ForHeadEnv { entries })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,20 +132,22 @@ impl Emitter {
|
|||||||
Operand::None,
|
Operand::None,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
ctx.next_cell_idx = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 语句收尾恢复捕获映射:旧条目放回(无旧条目则移除),头名不进入后续
|
/// 语句收尾恢复捕获映射:旧条目放回(无旧条目则移除),头名不进入后续
|
||||||
/// 兄弟语句的捕获判定。
|
/// 兄弟语句的捕获判定;头名集同步移除(嵌套循环成对)。
|
||||||
pub(crate) fn restore_for_head_env(&self, env: ForHeadEnv, ctx: &mut CompileCtx) {
|
pub(crate) fn restore_for_head_env(&self, env: ForHeadEnv, ctx: &mut CompileCtx) {
|
||||||
for (name, saved, _, _) in env.entries {
|
for (name, saved, _, _) in env.entries {
|
||||||
match saved {
|
match saved {
|
||||||
Some(old) => {
|
Some(old) => {
|
||||||
ctx.captured_bindings.insert(name, old);
|
ctx.captured_bindings.insert(name.clone(), old);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
ctx.captured_bindings.remove(&name);
|
ctx.captured_bindings.remove(&name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ctx.for_head_env_names.remove(&name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -250,14 +250,15 @@ impl Vm {
|
|||||||
/// 1. 取 a 槽为 cell 下标,按需扩容 `cell_stack` 至可容纳该下标。
|
/// 1. 取 a 槽为 cell 下标,按需扩容 `cell_stack` 至可容纳该下标。
|
||||||
/// 2. b 槽为 0 表示已初始化,非 0 为 TDZ(读写抛 ReferenceError,用于 for-in/for-of
|
/// 2. b 槽为 0 表示已初始化,非 0 为 TDZ(读写抛 ReferenceError,用于 for-in/for-of
|
||||||
/// 词法头环境建模)。
|
/// 词法头环境建模)。
|
||||||
/// 3. 槽位为空时新建 cell;已有 `CREATE_CLOSURE` 建的占位 cell 则原位更新值与标志,
|
/// 3. 槽位为空时新建 cell;TDZ 占位遇已初始化 cell 恒新建替换(循环体每迭代
|
||||||
/// 使闭包 upvalue 指向的同一 cell 跟随初始化。
|
/// 重执行不得把上一迭代已被闭包捕获的 cell 原位翻回未初始化);其余情形
|
||||||
|
/// 原位更新值与标志,使闭包 upvalue 指向的同一 cell 跟随初始化。
|
||||||
///
|
///
|
||||||
/// # 边界与前提
|
/// # 边界与前提
|
||||||
/// - `cell_stack` 为空时 `last_mut()` unwrap 失败;调用前须已压入当前帧环境层。
|
/// - `cell_stack` 为空时 `last_mut()` unwrap 失败;调用前须已压入当前帧环境层。
|
||||||
///
|
///
|
||||||
/// # 副作用
|
/// # 副作用
|
||||||
/// - 写入/更新堆上 `Cell`(可能触发分配),改动闭包 upvalue 可见值。
|
/// - 写入/更新/替换堆上 `Cell`(可能触发分配),改动闭包 upvalue 可见值。
|
||||||
///
|
///
|
||||||
/// # 注意事项
|
/// # 注意事项
|
||||||
/// - 手写 IR 路径保留的指令,常规编译不发射,故标 `#[allow(dead_code)]`。
|
/// - 手写 IR 路径保留的指令,常规编译不发射,故标 `#[allow(dead_code)]`。
|
||||||
@@ -276,12 +277,20 @@ impl Vm {
|
|||||||
// 无占位 cell:新建。
|
// 无占位 cell:新建。
|
||||||
current[cell_idx] = self.gc_state.alloc_cell(value, initialized);
|
current[cell_idx] = self.gc_state.alloc_cell(value, initialized);
|
||||||
} else {
|
} else {
|
||||||
// 更新占位 cell(CREATE_CLOSURE 已建),使闭包 upvalue 指向的
|
let existing_initialized = unsafe { &*current[cell_idx] }.is_initialized();
|
||||||
// cell 值跟随初始化;初始化标志随指令 b 槽。
|
if !initialized && existing_initialized {
|
||||||
unsafe {
|
// TDZ 占位而槽内是已初始化 cell:新建替换。循环体每迭代重执行
|
||||||
let cell = &mut *current[cell_idx];
|
// 的 TDZ 占位不得原位翻新迭代 cell(已被本迭代前闭包捕获);
|
||||||
cell.value = value;
|
// 已初始化 cell 保持身份,闭包 upvalue 保值。
|
||||||
cell.set_initialized(initialized);
|
current[cell_idx] = self.gc_state.alloc_cell(value, initialized);
|
||||||
|
} else {
|
||||||
|
// 更新占位 cell(CREATE_CLOSURE 已建),使闭包 upvalue 指向的
|
||||||
|
// cell 值跟随初始化;初始化标志随指令 b 槽。
|
||||||
|
unsafe {
|
||||||
|
let cell = &mut *current[cell_idx];
|
||||||
|
cell.value = value;
|
||||||
|
cell.set_initialized(initialized);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
Reference in New Issue
Block a user