Skip to content

Commit

Permalink
specialize interning f64s that fit in a usize
Browse files Browse the repository at this point in the history
  • Loading branch information
y21 committed Feb 17, 2024
1 parent 056f0fe commit 6cb02c3
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 13 deletions.
10 changes: 5 additions & 5 deletions crates/dash_vm/src/js_std/number.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::throw;
use crate::util::format_f64;
use crate::util::intern_f64;
use crate::value::function::native::CallContext;
use crate::value::ops::conversions::ValueConversion;
use crate::value::primitive::{Number, MAX_SAFE_INTEGERF};
Expand Down Expand Up @@ -30,13 +30,13 @@ pub fn to_string(cx: CallContext) -> Result<Value, Value> {
};

let re = match radix {
2 => format!("{:b}", num as u64),
10 => format_f64(num),
16 => format!("{:x}", num as u64),
2 => cx.scope.intern(format!("{:b}", num as u64).as_ref()),
10 => intern_f64(cx.scope, num),
16 => cx.scope.intern(format!("{:x}", num as u64)),
_ => throw!(cx.scope, RangeError, "Invalid radix: {}", radix),
};

Ok(Value::String(cx.scope.intern(re.as_ref()).into()))
Ok(Value::String(re.into()))
}

pub fn is_finite(cx: CallContext) -> Result<Value, Value> {
Expand Down
21 changes: 15 additions & 6 deletions crates/dash_vm/src/util.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
use std::num::FpCategory;

use dash_middle::interner::{sym, Symbol};

use crate::localscope::LocalScope;

/// Marks the code path leading to this call as cold, or "unlikely"
#[cold]
pub fn cold_path() {}
Expand All @@ -19,11 +23,16 @@ pub trait Captures<'a> {}

impl<'a, T: ?Sized> Captures<'a> for T {}

pub fn format_f64(n: f64) -> String {
// TODO: specialize zero, infinity, NaN by "interning" them in vm.statics
pub fn intern_f64(sc: &mut LocalScope, n: f64) -> Symbol {
if n.trunc() == n && n >= 0.0 && n <= usize::MAX as f64 {
// Happy path: no fractional part and fits in a usize
// This can use the specialized usize interner
return sc.intern_usize(n as usize);
}

match n.classify() {
FpCategory::Infinite => "Infinity".into(),
FpCategory::Nan => "NaN".into(),
FpCategory::Infinite => sym::Infinity,
FpCategory::Nan => sym::NaN,
_ if n >= 1e21f64 || n <= -1e21f64 => {
let mut digits = 0;
let mut n = n;
Expand All @@ -35,8 +44,8 @@ pub fn format_f64(n: f64) -> String {
n /= 10f64;
digits += 1;
}
format!("{n:.0}e+{digits}")
sc.intern(format!("{n:.0}e+{digits}").as_ref())
}
_ => format!("{n}"),
_ => sc.intern(n.to_string().as_ref()),
}
}
4 changes: 2 additions & 2 deletions crates/dash_vm/src/value/primitive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::gc::handle::Handle;
use crate::gc::interner::sym;
use crate::localscope::LocalScope;
use crate::throw;
use crate::util::{format_f64, Captures};
use crate::util::{intern_f64, Captures};

use super::boxed::{Boolean as BoxedBoolean, Number as BoxedNumber, Symbol as BoxedSymbol};
use super::object::{Object, PropertyKey, PropertyValue};
Expand Down Expand Up @@ -481,7 +481,7 @@ impl ValueConversion for f64 {
}

fn to_js_string(&self, sc: &mut LocalScope) -> Result<JsString, Value> {
Ok(sc.intern(format_f64(*self).as_ref()).into())
Ok(intern_f64(sc, *self).into())
}

fn length_of_array_like(&self, _sc: &mut LocalScope) -> Result<usize, Value> {
Expand Down

0 comments on commit 6cb02c3

Please sign in to comment.