From f874850bf7945b8d069267fd3469a9be369171a3 Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Thu, 13 Aug 2026 14:44:24 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E7=AE=97=E6=9C=AF=E8=BF=90=E7=AE=97=20?= =?UTF-8?q?int=20=E7=BB=93=E6=9E=9C=E4=BF=9D=20int=20+=20double=20?= =?UTF-8?q?=E5=BF=AB=E8=B7=AF=E5=BE=84=EF=BC=88B1/B3=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/oxide_vm/src/dispatch/arithmetic.rs | 72 ++++++++++++++++++++-- 1 file changed, 67 insertions(+), 5 deletions(-) diff --git a/crates/oxide_vm/src/dispatch/arithmetic.rs b/crates/oxide_vm/src/dispatch/arithmetic.rs index 3a6b773..7f3a1f9 100644 --- a/crates/oxide_vm/src/dispatch/arithmetic.rs +++ b/crates/oxide_vm/src/dispatch/arithmetic.rs @@ -8,6 +8,33 @@ fn bigint_is_zero(v: &num_bigint::BigInt) -> bool { num_traits::Zero::is_zero(v) } +/// int+int 加法:结果落在 i32 范围则保 int,否则升 double。 +#[inline(always)] +fn int_add(a: i32, b: i32) -> JsValue { + match a.checked_add(b) { + Some(v) => JsValue::int(v), + None => JsValue::float(a as f64 + b as f64), + } +} + +/// int+int 减法:结果落在 i32 范围则保 int,否则升 double。 +#[inline(always)] +fn int_sub(a: i32, b: i32) -> JsValue { + match a.checked_sub(b) { + Some(v) => JsValue::int(v), + None => JsValue::float(a as f64 - b as f64), + } +} + +/// int+int 乘法:结果落在 i32 范围则保 int,否则升 double。 +#[inline(always)] +fn int_mul(a: i32, b: i32) -> JsValue { + match a.checked_mul(b) { + Some(v) => JsValue::int(v), + None => JsValue::float(a as f64 * b as f64), + } +} + impl Vm { #[inline(always)] pub(crate) fn dispatch_add(&mut self, rd: usize, a: usize, b: usize) -> Result<(), String> { @@ -15,7 +42,11 @@ impl Vm { let lv = self.regs[a]; let rv = self.regs[b]; if lv.is_int() && rv.is_int() { - self.regs[rd] = JsValue::float(lv.as_int() as f64 + rv.as_int() as f64); + self.regs[rd] = int_add(lv.as_int(), rv.as_int()); + return Ok(()); + } + if lv.is_double() && rv.is_double() { + self.regs[rd] = JsValue::float(lv.as_double() + rv.as_double()); return Ok(()); } if lv.is_bigint() && rv.is_bigint() { @@ -97,7 +128,11 @@ impl Vm { let lv = self.regs[rd]; let rv = self.regs[a]; if lv.is_int() && rv.is_int() { - self.regs[rd] = JsValue::float(lv.as_int() as f64 + rv.as_int() as f64); + self.regs[rd] = int_add(lv.as_int(), rv.as_int()); + return Ok(()); + } + if lv.is_double() && rv.is_double() { + self.regs[rd] = JsValue::float(lv.as_double() + rv.as_double()); return Ok(()); } if lv.is_bigint() && rv.is_bigint() { @@ -131,7 +166,11 @@ impl Vm { let lv = self.regs[rd]; let rv = self.regs[a]; if lv.is_int() && rv.is_int() { - self.regs[rd] = JsValue::float(lv.as_int() as f64 - rv.as_int() as f64); + self.regs[rd] = int_sub(lv.as_int(), rv.as_int()); + return Ok(()); + } + if lv.is_double() && rv.is_double() { + self.regs[rd] = JsValue::float(lv.as_double() - rv.as_double()); return Ok(()); } if lv.is_bigint() && rv.is_bigint() { @@ -159,7 +198,11 @@ impl Vm { let lv = self.regs[rd]; let rv = self.regs[a]; if lv.is_int() && rv.is_int() { - self.regs[rd] = JsValue::float(lv.as_int() as f64 * rv.as_int() as f64); + self.regs[rd] = int_mul(lv.as_int(), rv.as_int()); + return Ok(()); + } + if lv.is_double() && rv.is_double() { + self.regs[rd] = JsValue::float(lv.as_double() * rv.as_double()); return Ok(()); } if lv.is_bigint() && rv.is_bigint() { @@ -190,6 +233,10 @@ impl Vm { self.regs[rd] = JsValue::float(lv.as_int() as f64 / rv.as_int() as f64); return Ok(()); } + if lv.is_double() && rv.is_double() { + self.regs[rd] = JsValue::float(lv.as_double() / rv.as_double()); + return Ok(()); + } if lv.is_bigint() && rv.is_bigint() { let r = self.bigint_value(rv); if bigint_is_zero(r) { @@ -223,7 +270,22 @@ impl Vm { let lv = self.regs[rd]; let rv = self.regs[a]; if lv.is_int() && rv.is_int() { - self.regs[rd] = JsValue::float(lv.as_int() as f64 % rv.as_int() as f64); + let a = lv.as_int(); + let b = rv.as_int(); + if b != 0 { + match a.checked_rem(b) { + Some(v) => { + self.regs[rd] = JsValue::int(v); + return Ok(()); + } + None => {} + } + } + self.regs[rd] = JsValue::float(a as f64 % b as f64); + return Ok(()); + } + if lv.is_double() && rv.is_double() { + self.regs[rd] = JsValue::float(lv.as_double() % rv.as_double()); return Ok(()); } if lv.is_bigint() && rv.is_bigint() {