mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-25 19:21:11 +08:00
perf: 常量折叠加位运算与比较 C 组加池溢出守卫
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
//! 折叠表:一元与算术常量折叠(A 组)加逻辑短路选支(B 组)。
|
||||
//! 折叠表:一元与算术常量折叠(A 组)、位运算与比较折叠(C 组)加逻辑短路
|
||||
//! 选支(B 组)。
|
||||
//!
|
||||
//! 折值编码逐运算符镜像运行时产物编码,保证物化后与运行时执行结果逐字节
|
||||
//! 一致:折值计算复用 `oxide_runtime_api::coercion` 的纯函数族(`to_number` /
|
||||
//! `to_int32` / `to_boolean`),与 emit 层字面量折叠同源,杜绝两层折叠各自
|
||||
//! 镜像运行时语义的漂移风险。
|
||||
//! `to_int32` / `to_uint32` / `to_boolean` / `relational_compare` /
|
||||
//! `abstract_eq_primitives` / `strict_equality`),与 emit 层字面量折叠同源,
|
||||
//! 杜绝两层折叠各自镜像运行时语义的漂移风险。
|
||||
//!
|
||||
//! 语义守卫:
|
||||
//! - 算术二元(ADD/SUB/MUL/DIV/MOD/EXP)任一操作数非数值不折;BigInt 混合
|
||||
@@ -15,13 +17,19 @@
|
||||
//! (镜像运行时 `int_add`);其余组合 f64 加(不做恒等捷径,负零操作数
|
||||
//! 经实加得 `+0.0`)。
|
||||
//! - UNARY_PLUS 作用 BigInt 不折(运行期抛 TypeError)。
|
||||
//! - C 组位运算与比较:双操作数须均在 `Int`/`Number`/`Boolean`/`Null` 四变体
|
||||
//! 域,`BigInt`/`String`/`Undefined` 操作数不折(与共享表 `const_to_jsvalue`
|
||||
//! 四臂口径一致,字符串比较路径降为后续任务)。
|
||||
//!
|
||||
//! B 组逻辑短路:结果恒为某一操作数的原值(无类型转换,任何类型安全),
|
||||
//! 仅左操作数已知即可选支,右操作数类型不限。
|
||||
|
||||
use oxide_bytecode::module::Constant;
|
||||
use oxide_bytecode::opcode::OpCode;
|
||||
use oxide_runtime_api::{to_boolean, to_int32, to_number};
|
||||
use oxide_runtime_api::{
|
||||
abstract_eq_primitives, relational_compare, strict_equality, to_boolean, to_int32, to_number,
|
||||
to_uint32,
|
||||
};
|
||||
use oxide_types::string_forge::encode_key;
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
@@ -196,3 +204,82 @@ pub fn short_circuit(op: OpCode, l: &Constant) -> Option<bool> {
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// C 组操作数域守卫:仅 `Int`/`Number`/`Boolean`/`Null` 四变体可折。
|
||||
///
|
||||
/// 传播映射可承载 `BigInt`/`String`/`Undefined` 常量(来自 `LOAD_CONST`),
|
||||
/// 这三类操作数不折(与共享表 `const_to_jsvalue` 四臂口径一致)。
|
||||
fn is_foldable_c_operand(c: &Constant) -> bool {
|
||||
matches!(c, Constant::Int(_) | Constant::Number(_) | Constant::Boolean(_) | Constant::Null)
|
||||
}
|
||||
|
||||
/// C 组位运算与比较折叠:按操作码计算折值,守卫命中返回 `None`。
|
||||
///
|
||||
/// 折值编码逐运算符镜像运行时产物:
|
||||
/// - `BIT_AND`/`BIT_OR`/`BIT_XOR`:`Int`(`ToInt32` 按位与/或/异或)
|
||||
/// - `SHL`/`SHR`:`Int`(`ToInt32` 左移/右移,移位量 `ToUint32` 与 0x1F)
|
||||
/// - `USHR`:结果不超 i32::MAX 保 `Int`,否则升 `Number`(镜像
|
||||
/// `write_ushr_result`)
|
||||
/// - `LT`/`GT`/`LTE`/`GTE`:`Boolean`(镜像 `relational_compare`,GT/LTE
|
||||
/// 交换操作数,LTE/GTE 取反,`None` 归 false)
|
||||
/// - `EQ`/`NEQ`:`Boolean`(镜像 `abstract_eq_primitives`)
|
||||
/// - `STRICT_EQ`/`STRICT_NEQ`:`Boolean`(镜像 `strict_equality`)
|
||||
///
|
||||
/// 操作数域守卫:双操作数须均在 `Int`/`Number`/`Boolean`/`Null` 四变体域,
|
||||
/// `BigInt`/`String`/`Undefined` 操作数不折(命中即返回 `None`)。
|
||||
pub fn fold_c_group(op: OpCode, l: &Constant, r: &Constant) -> Option<Constant> {
|
||||
// 操作数域守卫先行:传播映射可承载 BigInt/String/Undefined 常量,
|
||||
// C 组表只接受四变体域。
|
||||
if !is_foldable_c_operand(l) || !is_foldable_c_operand(r) {
|
||||
return None;
|
||||
}
|
||||
let (lv, rv) = (const_to_jsvalue(l)?, const_to_jsvalue(r)?);
|
||||
match op {
|
||||
OpCode::BIT_AND | OpCode::BIT_OR | OpCode::BIT_XOR => {
|
||||
let (a, b) = (to_int32(lv), to_int32(rv));
|
||||
Some(match op {
|
||||
OpCode::BIT_AND => Constant::Int(a & b),
|
||||
OpCode::BIT_OR => Constant::Int(a | b),
|
||||
_ => Constant::Int(a ^ b),
|
||||
})
|
||||
}
|
||||
OpCode::SHL | OpCode::SHR => {
|
||||
let a = to_int32(lv);
|
||||
let shift = to_uint32(rv) & 0x1F;
|
||||
Some(match op {
|
||||
OpCode::SHL => Constant::Int(a << shift),
|
||||
_ => Constant::Int(a >> shift),
|
||||
})
|
||||
}
|
||||
OpCode::USHR => {
|
||||
let a = to_int32(lv) as u32;
|
||||
let shift = to_uint32(rv) & 0x1F;
|
||||
let result = a >> shift;
|
||||
// 结果不超 i32::MAX 保 Int,否则升 Number(镜像 write_ushr_result)。
|
||||
if result <= i32::MAX as u32 {
|
||||
Some(Constant::Int(result as i32))
|
||||
} else {
|
||||
Some(Constant::Number(result as f64))
|
||||
}
|
||||
}
|
||||
OpCode::LT | OpCode::GT | OpCode::LTE | OpCode::GTE => {
|
||||
// GT/LTE 交换操作数,LTE/GTE 取反(镜像运行时派发口径)。
|
||||
let (a, b) = match op {
|
||||
OpCode::GT | OpCode::LTE => (rv, lv),
|
||||
_ => (lv, rv),
|
||||
};
|
||||
let cmp = relational_compare(a, b).unwrap_or(false);
|
||||
let negate = matches!(op, OpCode::LTE | OpCode::GTE);
|
||||
Some(Constant::Boolean(if negate { !cmp } else { cmp }))
|
||||
}
|
||||
OpCode::EQ | OpCode::NEQ => {
|
||||
let eq = abstract_eq_primitives(lv, rv);
|
||||
Some(Constant::Boolean(if op == OpCode::NEQ { !eq } else { eq }))
|
||||
}
|
||||
OpCode::STRICT_EQ | OpCode::STRICT_NEQ => {
|
||||
let eq = strict_equality(lv, rv);
|
||||
Some(Constant::Boolean(if op == OpCode::STRICT_NEQ { !eq } else { eq }))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user