mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-25 19:21:11 +08:00
perf: 一元逻辑条件字面量表达式折叠为单常量
This commit is contained in:
@@ -102,6 +102,101 @@ fn fold_guard_matrix() {
|
||||
}
|
||||
}
|
||||
|
||||
/// 一元/逻辑/条件命中矩阵:每行一条源串,断言目标操作码计数为 0 且常量池含折值。
|
||||
/// 折值编码逐运算符镜像运行时产物(`NEG`/`UNARY_PLUS` 恒 `Number`、`BIT_NOT` 恒
|
||||
/// `Int`、`-`/`~` 对 BigInt 折 `BigInt`、`NOT` 恒 `Boolean`、`TYPEOF` 恒 `String`、
|
||||
/// `VOID` 恒 `Undefined`、逻辑与条件恒操作数原样拷贝)。
|
||||
#[test]
|
||||
fn fold_unary_logical_conditional_hit_matrix() {
|
||||
// (源串, 目标操作码, 期望折值)
|
||||
let cases: &[(&str, OpCode, Constant)] = &[
|
||||
// 一元:NOT。
|
||||
("!0", OpCode::NOT, Constant::Boolean(true)),
|
||||
("!1", OpCode::NOT, Constant::Boolean(false)),
|
||||
("!0n", OpCode::NOT, Constant::Boolean(true)),
|
||||
("!1n", OpCode::NOT, Constant::Boolean(false)),
|
||||
// 一元:NEG 恒 Number(不保 Int),BigInt 折 BigInt。
|
||||
("-1", OpCode::NEG, Constant::Number(-1.0)),
|
||||
("-1.5", OpCode::NEG, Constant::Number(-1.5)),
|
||||
// 双层负号经剥壳。
|
||||
("-(-1)", OpCode::NEG, Constant::Number(1.0)),
|
||||
("-10n", OpCode::NEG, Constant::BigInt(num_bigint::BigInt::from(-10))),
|
||||
// 一元:UNARY_PLUS 恒 Number。
|
||||
("+1", OpCode::UNARY_PLUS, Constant::Number(1.0)),
|
||||
("+true", OpCode::UNARY_PLUS, Constant::Number(1.0)),
|
||||
("+null", OpCode::UNARY_PLUS, Constant::Number(0.0)),
|
||||
// 负零守卫:奇数层负号作用于 0 字面量保 Number(-0.0)。
|
||||
("+(-0.0)", OpCode::UNARY_PLUS, Constant::Number(-0.0)),
|
||||
// 一元:BIT_NOT 恒 Int,BigInt 折 BigInt。
|
||||
("~1", OpCode::BIT_NOT, Constant::Int(-2)),
|
||||
("~true", OpCode::BIT_NOT, Constant::Int(-2)),
|
||||
("~10n", OpCode::BIT_NOT, Constant::BigInt(num_bigint::BigInt::from(-11))),
|
||||
// 一元:TYPEOF 恒 String(BigInt 归 "bigint",独立于 "number")。
|
||||
("typeof 1", OpCode::TYPEOF, Constant::String("number".into())),
|
||||
("typeof true", OpCode::TYPEOF, Constant::String("boolean".into())),
|
||||
("typeof null", OpCode::TYPEOF, Constant::String("object".into())),
|
||||
("typeof 1n", OpCode::TYPEOF, Constant::String("bigint".into())),
|
||||
// 一元:VOID 恒 Undefined。
|
||||
("void 1", OpCode::VOID, Constant::Undefined),
|
||||
("void 0n", OpCode::VOID, Constant::Undefined),
|
||||
// 逻辑:恒操作数原样拷贝。
|
||||
("1 && 2", OpCode::AND, Constant::Int(2)),
|
||||
("0 && 2", OpCode::AND, Constant::Int(0)),
|
||||
("true || 2", OpCode::OR, Constant::Boolean(true)),
|
||||
("0 || 2", OpCode::OR, Constant::Int(2)),
|
||||
("1n && 2n", OpCode::AND, Constant::BigInt(num_bigint::BigInt::from(2))),
|
||||
("0n && 2n", OpCode::AND, Constant::BigInt(num_bigint::BigInt::from(0))),
|
||||
("null ?? 1", OpCode::NULLISH, Constant::Int(1)),
|
||||
("1 ?? 2", OpCode::NULLISH, Constant::Int(1)),
|
||||
("1n ?? 2n", OpCode::NULLISH, Constant::BigInt(num_bigint::BigInt::from(1))),
|
||||
// 条件:test 布尔值选定分支。
|
||||
("1 ? 2 : 3", OpCode::JMP_IF_FALSE, Constant::Int(2)),
|
||||
("0 ? 2 : 3", OpCode::JMP_IF_FALSE, Constant::Int(3)),
|
||||
("true ? 1n : 2n", OpCode::JMP_IF_FALSE, Constant::BigInt(num_bigint::BigInt::from(1))),
|
||||
];
|
||||
for (src, op, folded) in cases {
|
||||
let ir = emit_ir(src);
|
||||
assert_eq!(count_op(&ir.insts, *op), 0, "{src:?} 应折叠,目标操作码 {op:?} 计数应为 0");
|
||||
assert!(pool_contains(&ir, folded), "{src:?} 常量池应含折值 {folded:?}");
|
||||
}
|
||||
}
|
||||
|
||||
/// 一元/逻辑/条件守卫矩阵:非字面量操作数落回运行时路径,每条带显式期望计数
|
||||
/// (落回路径操作码因运算符而异,不复用二元守卫的「计数为 1」单操作码断言)。
|
||||
#[test]
|
||||
fn fold_unary_logical_conditional_guard_matrix() {
|
||||
// (源串, 目标操作码, 期望计数)
|
||||
let cases: &[(&str, OpCode, usize)] = &[
|
||||
// + 作用 BigInt:运行期 TypeError 唯一来源,不折。
|
||||
("+1n", OpCode::UNARY_PLUS, 1),
|
||||
// 剥壳后仍 BigInt。
|
||||
("+(-1n)", OpCode::UNARY_PLUS, 1),
|
||||
// typeof 操作数为二元表达式(非字面量),不折。
|
||||
("typeof (1 + 2)", OpCode::TYPEOF, 1),
|
||||
// typeof 未声明标识符走 LOAD_GLOBAL_TYPEOF 特判加 TYPEOF,不折。
|
||||
("typeof x", OpCode::TYPEOF, 1),
|
||||
// 逻辑短路路径(非字面量操作数)。
|
||||
("x && 1", OpCode::AND, 0),
|
||||
("1 && x", OpCode::AND, 0),
|
||||
("x || 1", OpCode::OR, 0),
|
||||
("x ?? 1", OpCode::NULLISH, 0),
|
||||
// 条件:consequent / test 非字面量。
|
||||
("1 ? x : 2", OpCode::JMP_IF_FALSE, 1),
|
||||
("x ? 1 : 2", OpCode::JMP_IF_FALSE, 1),
|
||||
];
|
||||
for (src, op, expected) in cases {
|
||||
let ir = emit_ir(src);
|
||||
assert_eq!(
|
||||
count_op(&ir.insts, *op),
|
||||
*expected,
|
||||
"{src:?} 守卫命中,目标操作码 {op:?} 计数应为 {expected}"
|
||||
);
|
||||
}
|
||||
// typeof 未声明标识符走 LOAD_GLOBAL_TYPEOF 特判路径。
|
||||
let ir = emit_ir("typeof x");
|
||||
assert_eq!(count_op(&ir.insts, OpCode::LOAD_GLOBAL_TYPEOF), 1, "typeof x 应发 LOAD_GLOBAL_TYPEOF");
|
||||
}
|
||||
|
||||
/// 字节码指纹:`CompiledModule` 未派生 `Debug`,逐字段展开为确定串(子模块递归)。
|
||||
fn bytecode_fingerprint(m: &oxide_bytecode::module::CompiledModule) -> String {
|
||||
let mut out = format!(
|
||||
@@ -124,7 +219,12 @@ fn bytecode_fingerprint(m: &oxide_bytecode::module::CompiledModule) -> String {
|
||||
/// 确定性:同一源串连续编译八次,IR 与字节码指纹全等(折叠路径纯函数无迭代序依赖)。
|
||||
#[test]
|
||||
fn fold_deterministic() {
|
||||
let srcs = ["1 + 2 * 3;", "var a = -1 >>> 0; var b = 1 < 2;", "var c = 5 & 3 | 4;"];
|
||||
let srcs = [
|
||||
"1 + 2 * 3;",
|
||||
"var a = -1 >>> 0; var b = 1 < 2;",
|
||||
"var c = 5 & 3 | 4;",
|
||||
"var a = !1 && 2; var b = 1 ? 2 : 3; var c = typeof 1n; var d = 0n ?? 1n;",
|
||||
];
|
||||
for src in srcs {
|
||||
let mut fingerprints: Vec<(String, String)> = Vec::new();
|
||||
for _ in 0..8 {
|
||||
|
||||
Reference in New Issue
Block a user