Browse Source

Keep Integer type for inc/dec of an integer (#2615)

Keep Integer type after running unary increment/decrement ops if possible. The integer type will be useful to take fast paths for accessing index properties. (e.g., `let a = 1; arr[++a]`)
pull/2620/head
Choongwoo Han 2 years ago
parent
commit
3d6931cf9c
  1. 40
      boa_engine/src/tests.rs
  2. 17
      boa_engine/src/vm/opcode/unary_ops/decrement.rs
  3. 17
      boa_engine/src/vm/opcode/unary_ops/increment.rs

40
boa_engine/src/tests.rs

@ -541,6 +541,20 @@ fn unary_pre() {
--a === 4; --a === 4;
"#; "#;
assert_eq!(&exec(execs_before_dec), "true"); assert_eq!(&exec(execs_before_dec), "true");
let i32_limit_inc = r#"
let a = 2147483647;
++a;
a;
"#;
assert_eq!(&exec(i32_limit_inc), "2147483648");
let i32_limit_dec = r#"
let a = -2147483648;
--a;
a;
"#;
assert_eq!(&exec(i32_limit_dec), "-2147483649");
} }
#[test] #[test]
@ -683,6 +697,32 @@ fn unary_post() {
a-- === 5; a-- === 5;
"#; "#;
assert_eq!(&exec(execs_after_dec), "true"); assert_eq!(&exec(execs_after_dec), "true");
let i32_limit_inc = r#"
let a = 2147483647;
a++;
a;
"#;
assert_eq!(&exec(i32_limit_inc), "2147483648");
let i32_limit_dec = r#"
let a = -2147483648;
a--;
a;
"#;
assert_eq!(&exec(i32_limit_dec), "-2147483649");
let to_numeric_inc = r#"
let a = {[Symbol.toPrimitive]() { return 123; }};
a++
"#;
assert_eq!(&exec(to_numeric_inc), "123");
let to_numeric_dec = r#"
let a = {[Symbol.toPrimitive]() { return 123; }};
a--
"#;
assert_eq!(&exec(to_numeric_dec), "123");
} }
#[test] #[test]

17
boa_engine/src/vm/opcode/unary_ops/decrement.rs

@ -1,5 +1,5 @@
use crate::{ use crate::{
value::Numeric, value::{JsValue, Numeric},
vm::{opcode::Operation, ShouldExit}, vm::{opcode::Operation, ShouldExit},
Context, JsBigInt, JsResult, Context, JsBigInt, JsResult,
}; };
@ -17,11 +17,16 @@ impl Operation for Dec {
fn execute(context: &mut Context<'_>) -> JsResult<ShouldExit> { fn execute(context: &mut Context<'_>) -> JsResult<ShouldExit> {
let value = context.vm.pop(); let value = context.vm.pop();
match value.to_numeric(context)? { match value {
JsValue::Integer(number) if number > i32::MIN => {
context.vm.push(number - 1);
}
_ => match value.to_numeric(context)? {
Numeric::Number(number) => context.vm.push(number - 1f64), Numeric::Number(number) => context.vm.push(number - 1f64),
Numeric::BigInt(bigint) => { Numeric::BigInt(bigint) => {
context.vm.push(JsBigInt::sub(&bigint, &JsBigInt::one())); context.vm.push(JsBigInt::sub(&bigint, &JsBigInt::one()));
} }
},
} }
Ok(ShouldExit::False) Ok(ShouldExit::False)
} }
@ -40,6 +45,12 @@ impl Operation for DecPost {
fn execute(context: &mut Context<'_>) -> JsResult<ShouldExit> { fn execute(context: &mut Context<'_>) -> JsResult<ShouldExit> {
let value = context.vm.pop(); let value = context.vm.pop();
match value {
JsValue::Integer(number) if number > i32::MIN => {
context.vm.push(number - 1);
context.vm.push(value);
}
_ => {
let value = value.to_numeric(context)?; let value = value.to_numeric(context)?;
match value { match value {
Numeric::Number(number) => context.vm.push(number - 1f64), Numeric::Number(number) => context.vm.push(number - 1f64),
@ -48,6 +59,8 @@ impl Operation for DecPost {
} }
} }
context.vm.push(value); context.vm.push(value);
}
}
Ok(ShouldExit::False) Ok(ShouldExit::False)
} }
} }

17
boa_engine/src/vm/opcode/unary_ops/increment.rs

@ -1,5 +1,5 @@
use crate::{ use crate::{
value::Numeric, value::{JsValue, Numeric},
vm::{opcode::Operation, ShouldExit}, vm::{opcode::Operation, ShouldExit},
Context, JsBigInt, JsResult, Context, JsBigInt, JsResult,
}; };
@ -17,11 +17,16 @@ impl Operation for Inc {
fn execute(context: &mut Context<'_>) -> JsResult<ShouldExit> { fn execute(context: &mut Context<'_>) -> JsResult<ShouldExit> {
let value = context.vm.pop(); let value = context.vm.pop();
match value.to_numeric(context)? { match value {
JsValue::Integer(number) if number < i32::MAX => {
context.vm.push(number + 1);
}
_ => match value.to_numeric(context)? {
Numeric::Number(number) => context.vm.push(number + 1f64), Numeric::Number(number) => context.vm.push(number + 1f64),
Numeric::BigInt(bigint) => { Numeric::BigInt(bigint) => {
context.vm.push(JsBigInt::add(&bigint, &JsBigInt::one())); context.vm.push(JsBigInt::add(&bigint, &JsBigInt::one()));
} }
},
} }
Ok(ShouldExit::False) Ok(ShouldExit::False)
} }
@ -40,6 +45,12 @@ impl Operation for IncPost {
fn execute(context: &mut Context<'_>) -> JsResult<ShouldExit> { fn execute(context: &mut Context<'_>) -> JsResult<ShouldExit> {
let value = context.vm.pop(); let value = context.vm.pop();
match value {
JsValue::Integer(number) if number < i32::MAX => {
context.vm.push(number + 1);
context.vm.push(value);
}
_ => {
let value = value.to_numeric(context)?; let value = value.to_numeric(context)?;
match value { match value {
Numeric::Number(number) => context.vm.push(number + 1f64), Numeric::Number(number) => context.vm.push(number + 1f64),
@ -48,6 +59,8 @@ impl Operation for IncPost {
} }
} }
context.vm.push(value); context.vm.push(value);
}
}
Ok(ShouldExit::False) Ok(ShouldExit::False)
} }
} }

Loading…
Cancel
Save