mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-24 02:31:13 +08:00
refactor: emit 冗余标志参数收敛为内部推导
This commit is contained in:
@@ -55,8 +55,7 @@ impl Emitter {
|
||||
/// - 声明撞全局不可写内置(undefined/NaN/Infinity):sloppy 静默跳过写(槽保留
|
||||
/// 入口预载原值),strict 抛 TypeError;局部遮蔽绑定不受影响。
|
||||
pub(crate) fn emit_bind_target(
|
||||
&self, name: &str, src_reg: u32, kind: VariableDeclarationKind, is_const: bool, fresh_cell: bool,
|
||||
ctx: &mut CompileCtx,
|
||||
&self, name: &str, src_reg: u32, kind: VariableDeclarationKind, fresh_cell: bool, ctx: &mut CompileCtx,
|
||||
) -> Result<(), String> {
|
||||
let target_reg = if matches!(kind, VariableDeclarationKind::Var) {
|
||||
// `var` 名已预声明(hoisting),复用预登记槽位而非新分配,使 n_registers 与 let/const 一致。
|
||||
@@ -64,7 +63,7 @@ impl Emitter {
|
||||
reg
|
||||
} else {
|
||||
let var_reg = ctx.alloc_reg();
|
||||
ctx.declare(name, var_reg, kind, is_const)?;
|
||||
ctx.declare(name, var_reg, kind)?;
|
||||
var_reg
|
||||
}
|
||||
} else {
|
||||
@@ -74,7 +73,7 @@ impl Emitter {
|
||||
reg
|
||||
} else {
|
||||
let var_reg = ctx.alloc_reg();
|
||||
ctx.declare(name, var_reg, kind, is_const)?;
|
||||
ctx.declare(name, var_reg, kind)?;
|
||||
var_reg
|
||||
}
|
||||
};
|
||||
@@ -117,7 +116,7 @@ impl Emitter {
|
||||
} else if !ctx.with_stack.is_empty() && !ctx.is_with_internal_binding(name) {
|
||||
// with 内 var 初始化:对象有该属性则写对象,否则写提升槽(动态解析);
|
||||
// 未声明名经回退臂落隐式全局,与静态写路径同形。
|
||||
self.emit_with_dynamic_write(name, src_reg, 0, ctx)?;
|
||||
self.emit_with_dynamic_write(name, src_reg, ctx)?;
|
||||
} else {
|
||||
// const 声明路径 STORE_VAR 恒 b=0,不查运行时 guard。
|
||||
// guard 读 regs[rd] 判断槽是否已初始化,依赖槽初始为 undefined;
|
||||
@@ -229,15 +228,15 @@ impl Emitter {
|
||||
}
|
||||
|
||||
pub(crate) fn emit_binding_pattern(
|
||||
&self, pattern: &BindingPattern, src_reg: u32, kind: VariableDeclarationKind, is_const: bool, fresh_cell: bool,
|
||||
&self, pattern: &BindingPattern, src_reg: u32, kind: VariableDeclarationKind, fresh_cell: bool,
|
||||
ctx: &mut CompileCtx,
|
||||
) -> Result<(), String> {
|
||||
match pattern {
|
||||
BindingPattern::BindingIdentifier(bi) => {
|
||||
self.emit_bind_target(bi.name.as_str(), src_reg, kind, is_const, fresh_cell, ctx)
|
||||
self.emit_bind_target(bi.name.as_str(), src_reg, kind, fresh_cell, ctx)
|
||||
}
|
||||
BindingPattern::ArrayPattern(ap) => self.emit_array_binding(ap, src_reg, kind, is_const, fresh_cell, ctx),
|
||||
BindingPattern::ObjectPattern(op) => self.emit_object_binding(op, src_reg, kind, is_const, fresh_cell, ctx),
|
||||
BindingPattern::ArrayPattern(ap) => self.emit_array_binding(ap, src_reg, kind, fresh_cell, ctx),
|
||||
BindingPattern::ObjectPattern(op) => self.emit_object_binding(op, src_reg, kind, fresh_cell, ctx),
|
||||
BindingPattern::AssignmentPattern(ap) => {
|
||||
// `[x = fn]`:默认值函数按绑定名推断 name。
|
||||
let name = match &ap.left {
|
||||
@@ -245,14 +244,13 @@ impl Emitter {
|
||||
_ => None,
|
||||
};
|
||||
let val_reg = self.emit_default_if_undefined(src_reg, &ap.right, name, ctx)?;
|
||||
self.emit_binding_pattern(&ap.left, val_reg, kind, is_const, fresh_cell, ctx)
|
||||
self.emit_binding_pattern(&ap.left, val_reg, kind, fresh_cell, ctx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_array_binding(
|
||||
&self, ap: &ArrayPattern, src_reg: u32, kind: VariableDeclarationKind, is_const: bool, fresh_cell: bool,
|
||||
ctx: &mut CompileCtx,
|
||||
&self, ap: &ArrayPattern, src_reg: u32, kind: VariableDeclarationKind, fresh_cell: bool, ctx: &mut CompileCtx,
|
||||
) -> Result<(), String> {
|
||||
ctx.inst(Inst::new(OpCode::FOR_OF_INIT, Operand::None, Operand::Reg(src_reg), Operand::None));
|
||||
for elem in &ap.elements {
|
||||
@@ -261,12 +259,12 @@ impl Emitter {
|
||||
let val_reg = ctx.alloc_reg();
|
||||
ctx.inst(Inst::new(OpCode::FOR_OF_NEXT, Operand::Reg(val_reg), Operand::None, Operand::None));
|
||||
if let Some(pattern) = elem {
|
||||
self.emit_binding_pattern(pattern, val_reg, kind, is_const, fresh_cell, ctx)?;
|
||||
self.emit_binding_pattern(pattern, val_reg, kind, fresh_cell, ctx)?;
|
||||
}
|
||||
}
|
||||
if let Some(rest) = &ap.rest {
|
||||
let rest_reg = self.emit_collect_rest_array(ctx)?;
|
||||
self.emit_binding_pattern(&rest.argument, rest_reg, kind, is_const, fresh_cell, ctx)?;
|
||||
self.emit_binding_pattern(&rest.argument, rest_reg, kind, fresh_cell, ctx)?;
|
||||
}
|
||||
ctx.inst(Inst::new(OpCode::FOR_OF_CLOSE, Operand::None, Operand::None, Operand::None));
|
||||
Ok(())
|
||||
@@ -300,8 +298,7 @@ impl Emitter {
|
||||
}
|
||||
|
||||
fn emit_object_binding(
|
||||
&self, op: &ObjectPattern, src_reg: u32, kind: VariableDeclarationKind, is_const: bool, fresh_cell: bool,
|
||||
ctx: &mut CompileCtx,
|
||||
&self, op: &ObjectPattern, src_reg: u32, kind: VariableDeclarationKind, fresh_cell: bool, ctx: &mut CompileCtx,
|
||||
) -> Result<(), String> {
|
||||
// 对象解构先 ToObject(rhs):null/undefined 抛 TypeError(含空 pattern),
|
||||
// 原始值包装为对应对象,保证属性读取与 rest 都以对象为源。
|
||||
@@ -317,8 +314,7 @@ impl Emitter {
|
||||
excl_arr_reg = Some(self.emit_new_excluded_array(ctx));
|
||||
}
|
||||
for prop in &op.properties {
|
||||
let (prop_reg, static_key, key_reg) =
|
||||
self.emit_object_property_read_key(obj_reg, &prop.key, prop.computed, ctx)?;
|
||||
let (prop_reg, static_key, key_reg) = self.emit_object_property_read_key(obj_reg, &prop.key, ctx)?;
|
||||
if let Some(key) = static_key {
|
||||
excluded.push(key.clone());
|
||||
if let Some(arr) = excl_arr_reg {
|
||||
@@ -329,7 +325,7 @@ impl Emitter {
|
||||
self.emit_push_excluded_key(arr, Some(key_reg), "", excl_push, ctx);
|
||||
excl_push += 1;
|
||||
}
|
||||
self.emit_binding_pattern(&prop.value, prop_reg, kind, is_const, fresh_cell, ctx)?;
|
||||
self.emit_binding_pattern(&prop.value, prop_reg, kind, fresh_cell, ctx)?;
|
||||
}
|
||||
if let Some(rest) = &op.rest {
|
||||
let rest_reg = ctx.alloc_reg();
|
||||
@@ -340,7 +336,7 @@ impl Emitter {
|
||||
excluded_idx as u32,
|
||||
excl_arr_reg.map(Operand::Reg),
|
||||
));
|
||||
self.emit_binding_pattern(&rest.argument, rest_reg, kind, is_const, fresh_cell, ctx)?;
|
||||
self.emit_binding_pattern(&rest.argument, rest_reg, kind, fresh_cell, ctx)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -574,7 +570,7 @@ impl Emitter {
|
||||
}
|
||||
AssignmentTargetProperty::AssignmentTargetPropertyProperty(prop) => {
|
||||
let (prop_reg, static_key, key_reg) =
|
||||
self.emit_object_property_read_key(obj_reg, &prop.name, prop.computed, ctx)?;
|
||||
self.emit_object_property_read_key(obj_reg, &prop.name, ctx)?;
|
||||
if let Some(key) = static_key {
|
||||
excluded.push(key.clone());
|
||||
if let Some(arr) = excl_arr_reg {
|
||||
|
||||
@@ -305,8 +305,10 @@ impl Emitter {
|
||||
/// 读取对象属性并产出键信息:非计算键走字符串常量 IC 路径,计算键在字面量可折叠时走 IC,否则动态求值。
|
||||
/// 返回 `(结果寄存器, 常量键名, 键寄存器)`,后两者互补为 None(计算键路径无论 IC 折叠还是动态求值均以寄存器返回键)。
|
||||
pub(crate) fn emit_object_property_read_key(
|
||||
&self, src_reg: u32, key: &PropertyKey, computed: bool, ctx: &mut CompileCtx,
|
||||
&self, src_reg: u32, key: &PropertyKey, ctx: &mut CompileCtx,
|
||||
) -> Result<(u32, Option<String>, Option<u32>), String> {
|
||||
// 计算键即表达式形态键(oxc 计算键恒为 Expression 继承变体),静态/私有名键非计算。
|
||||
let computed = key.is_expression();
|
||||
if !computed {
|
||||
let key_name = crate::shared::string_pool::pool_key_property(key)?;
|
||||
let prop_reg = self.emit_object_property_read(src_reg, &key_name, ctx);
|
||||
|
||||
@@ -10,6 +10,8 @@ use oxide_parser::{Expression, MethodDefinitionKind, PropertyKey};
|
||||
impl Emitter {
|
||||
/// 实例字段初始化:define 语义(不触发原型 setter)。
|
||||
/// 非计算键用字符串常量;计算键从 `@@field_keys` upvalue 数组按 `key_slot` 取(类定义期求值一次)。
|
||||
/// 类元素字符串字面量键(`"a" = 1`)非计算(oxc `computed` 标志为假),
|
||||
/// 故 `computed` 取 AST 标志而非按键形态推导。
|
||||
pub(crate) fn emit_public_field_init(
|
||||
&self, target: Operand, key: &PropertyKey, computed: bool, value: Option<&Expression>, key_slot: Option<u8>,
|
||||
ctx: &mut CompileCtx,
|
||||
@@ -17,7 +19,7 @@ impl Emitter {
|
||||
let key_reg = if computed {
|
||||
self.emit_instance_field_key(key_slot, ctx)?
|
||||
} else {
|
||||
self.emit_class_key_reg(key, false, ctx)?
|
||||
self.emit_class_key_reg(key, ctx)?
|
||||
};
|
||||
let value_reg = self.emit_field_value(value, ctx)?;
|
||||
ctx.inst(Inst::define_prop(target, Operand::Reg(value_reg), Operand::Reg(key_reg)));
|
||||
|
||||
@@ -57,21 +57,14 @@ impl Emitter {
|
||||
Ok((brand_reg, brand_id))
|
||||
}
|
||||
|
||||
pub(crate) fn emit_class_key_reg(
|
||||
&self, key: &PropertyKey, computed: bool, ctx: &mut CompileCtx,
|
||||
) -> Result<u32, String> {
|
||||
if !computed {
|
||||
let name = crate::shared::string_pool::pool_key_property(key)?;
|
||||
let idx = ctx.add_constant(Constant::String(name));
|
||||
let reg = ctx.alloc_reg();
|
||||
ctx.inst(Inst::load_const(Operand::Reg(reg), idx));
|
||||
return Ok(reg);
|
||||
}
|
||||
|
||||
if matches!(key, PropertyKey::PrivateIdentifier(_)) {
|
||||
return Err("private class elements not yet supported".into());
|
||||
}
|
||||
self.emit_expression(key.to_expression(), ctx)
|
||||
/// 非计算类属性键的寄存器:全部调用点均为非计算键(计算键经
|
||||
/// `emit_class_array_key_reg` 从类定义期数组取),直接取池键字符串常量。
|
||||
pub(crate) fn emit_class_key_reg(&self, key: &PropertyKey, ctx: &mut CompileCtx) -> Result<u32, String> {
|
||||
let name = crate::shared::string_pool::pool_key_property(key)?;
|
||||
let idx = ctx.add_constant(Constant::String(name));
|
||||
let reg = ctx.alloc_reg();
|
||||
ctx.inst(Inst::load_const(Operand::Reg(reg), idx));
|
||||
Ok(reg)
|
||||
}
|
||||
|
||||
/// 从类定义期 computed key 数组按 slot 取键(方法/静态字段在类定义期使用)。
|
||||
|
||||
Reference in New Issue
Block a user