Browse Source

Add integer type to fast path of to_property_key (#2261)

Skip `to_string` for integer type primitives in `to_property_key`. It's unnecessary to convert the integer value to string and convert back to `Index(u32)` type.

In this example code, it improves around 10% of runtime.
```js
let arr = [1,2,3,4,5];
for (let i = 0; i < 10000000; i++) {
  arr[0] = 123;
}
```

Before: 6.24s
After: 5.38s
pull/2268/head
Choongwoo Han 2 years ago
parent
commit
3983363124
  1. 5
      boa_engine/src/value/mod.rs
  2. 51
      boa_engine/src/value/tests.rs

5
boa_engine/src/value/mod.rs

@ -549,12 +549,15 @@ impl JsValue {
// Fast path:
Self::String(string) => string.clone().into(),
Self::Symbol(symbol) => symbol.clone().into(),
Self::Integer(integer) => (*integer).into(),
// Slow path:
_ => match self.to_primitive(context, PreferredType::String)? {
Self::Object(_) => match self.to_primitive(context, PreferredType::String)? {
Self::String(ref string) => string.clone().into(),
Self::Symbol(ref symbol) => symbol.clone().into(),
Self::Integer(integer) => integer.into(),
primitive => primitive.to_string(context)?.into(),
},
primitive => primitive.to_string(context)?.into(),
})
}

51
boa_engine/src/value/tests.rs

@ -611,6 +611,57 @@ fn to_primitive() {
]);
}
#[test]
fn object_to_property_key() {
let src = r#"
let obj = {};
let to_primitive_42 = {
[Symbol.toPrimitive]() {
return 42;
}
};
obj[to_primitive_42] = 1;
let to_primitive_true = {
[Symbol.toPrimitive]() {
return true;
}
};
obj[to_primitive_true] = 2;
let to_primitive_str = {
[Symbol.toPrimitive]() {
return "str1";
}
};
obj[to_primitive_str] = 3;
let mysymbol = Symbol("test");
let to_primitive_symbol = {
[Symbol.toPrimitive]() {
return mysymbol;
}
};
obj[to_primitive_symbol] = 4;
let to_str = {
toString: function() {
return "str2";
}
};
obj[to_str] = 5;
"#;
check_output(&[
TestAction::Execute(src),
TestAction::TestEq("obj[42]", "1"),
TestAction::TestEq("obj[true]", "2"),
TestAction::TestEq("obj['str1']", "3"),
TestAction::TestEq("obj[mysymbol]", "4"),
TestAction::TestEq("obj['str2']", "5"),
]);
}
/// Test cyclic conversions that previously caused stack overflows
/// Relevant mitigation for these are in `JsObject::ordinary_to_primitive` and
/// `JsObject::to_json`

Loading…
Cancel
Save