mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
perf(span): compare Spans as single u64s (#8300)
#8298 made `Span` aligned on 8 on 64-bit platforms. Utilize this property to compare `Span`s as a single `u64` instead of 2 x `u32`s. This removes some really weird assembly which compiler otherwise produces, using expensive SIMD operations for a simple comparison: https://godbolt.org/z/sEf9MGvsr Note: This only affects comparing `&Span`s. Makes no difference when comparing owned `Span`s.
This commit is contained in:
parent
a43560c056
commit
63eb29868d
2 changed files with 33 additions and 2 deletions
|
|
@ -108,8 +108,9 @@ impl Span {
|
||||||
/// assert!(!Span::new(0, 5).is_unspanned());
|
/// assert!(!Span::new(0, 5).is_unspanned());
|
||||||
/// assert!(!Span::new(5, 5).is_unspanned());
|
/// assert!(!Span::new(5, 5).is_unspanned());
|
||||||
/// ```
|
/// ```
|
||||||
|
#[inline]
|
||||||
pub const fn is_unspanned(self) -> bool {
|
pub const fn is_unspanned(self) -> bool {
|
||||||
self.start == SPAN.start && self.end == SPAN.end
|
self.const_eq(SPAN)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if this [`Span`] contains another [`Span`].
|
/// Check if this [`Span`] contains another [`Span`].
|
||||||
|
|
@ -360,6 +361,21 @@ impl Span {
|
||||||
((self.start as u64) << 32) | (self.end as u64)
|
((self.start as u64) << 32) | (self.end as u64)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Compare two [`Span`]s.
|
||||||
|
///
|
||||||
|
/// Same as `PartialEq::eq`, but a const function, and takes owned `Span`s.
|
||||||
|
//
|
||||||
|
// `#[inline(always)]` because want to make sure this is inlined into `PartialEq::eq`.
|
||||||
|
#[expect(clippy::inline_always)]
|
||||||
|
#[inline(always)]
|
||||||
|
const fn const_eq(self, other: Self) -> bool {
|
||||||
|
if cfg!(target_pointer_width = "64") {
|
||||||
|
self.as_u64() == other.as_u64()
|
||||||
|
} else {
|
||||||
|
self.start == other.start && self.end == other.end
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Index<Span> for str {
|
impl Index<Span> for str {
|
||||||
|
|
@ -397,6 +413,15 @@ impl From<Span> for LabeledSpan {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// On 64-bit platforms, compare `Span`s as single `u64`s, which is faster when used with `&Span` refs.
|
||||||
|
// https://godbolt.org/z/sEf9MGvsr
|
||||||
|
impl PartialEq for Span {
|
||||||
|
#[inline]
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.const_eq(*other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Skip hashing `_align` field.
|
// Skip hashing `_align` field.
|
||||||
// On 64-bit platforms, hash `Span` as a single `u64`, which is faster with `FxHash`.
|
// On 64-bit platforms, hash `Span` as a single `u64`, which is faster with `FxHash`.
|
||||||
// https://godbolt.org/z/4fbvcsTxM
|
// https://godbolt.org/z/4fbvcsTxM
|
||||||
|
|
@ -511,7 +536,13 @@ mod test {
|
||||||
fn test_eq() {
|
fn test_eq() {
|
||||||
assert_eq!(Span::new(0, 0), Span::new(0, 0));
|
assert_eq!(Span::new(0, 0), Span::new(0, 0));
|
||||||
assert_eq!(Span::new(0, 1), Span::new(0, 1));
|
assert_eq!(Span::new(0, 1), Span::new(0, 1));
|
||||||
|
assert_eq!(Span::new(1, 5), Span::new(1, 5));
|
||||||
|
|
||||||
assert_ne!(Span::new(0, 0), Span::new(0, 1));
|
assert_ne!(Span::new(0, 0), Span::new(0, 1));
|
||||||
|
assert_ne!(Span::new(1, 5), Span::new(0, 5));
|
||||||
|
assert_ne!(Span::new(1, 5), Span::new(2, 5));
|
||||||
|
assert_ne!(Span::new(1, 5), Span::new(1, 4));
|
||||||
|
assert_ne!(Span::new(1, 5), Span::new(1, 6));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ use super::PointerAlign;
|
||||||
/// [`expand`]: Span::expand
|
/// [`expand`]: Span::expand
|
||||||
/// [`shrink`]: Span::shrink
|
/// [`shrink`]: Span::shrink
|
||||||
#[ast(visit)]
|
#[ast(visit)]
|
||||||
#[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Default, Clone, Copy, Eq, PartialOrd, Ord)]
|
||||||
#[generate_derive(ESTree)]
|
#[generate_derive(ESTree)]
|
||||||
#[estree(no_type, always_flatten)]
|
#[estree(no_type, always_flatten)]
|
||||||
pub struct Span {
|
pub struct Span {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue