From 54be7e1cfa4cb18bc59f3025d5e71b9f5a982f84 Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Thu, 8 Jun 2023 20:06:35 -0600 Subject: [PATCH] Replace SmallVec with Vec for niche optimizations Niche-filling optimization was improved in rust-lang/rust#94075, which allows PrefixEntry to use the niche in Vec, but not SmallVec. --- src/syntax/prefix.rs | 46 ++++++++------------------------------------ src/ws/parse.rs | 3 +-- 2 files changed, 9 insertions(+), 40 deletions(-) diff --git a/src/syntax/prefix.rs b/src/syntax/prefix.rs index 76b7b84..18b6c3e 100644 --- a/src/syntax/prefix.rs +++ b/src/syntax/prefix.rs @@ -9,8 +9,6 @@ use std::collections::HashMap; use std::fmt::{self, Debug, Formatter}; -use smallvec::{smallvec, SmallVec}; - use crate::syntax::{TokenSeq, VariantIndex}; use crate::text::EncodingError; @@ -23,20 +21,20 @@ pub struct PrefixTable { #[derive(Clone, Debug)] pub enum PrefixEntry { Terminal(O), - Prefix(SmallVec<[O; 16]>), + Prefix(Vec), } #[derive(Clone, Debug, PartialEq, Eq)] pub struct ConflictError { prefix: TokenSeq, - opcodes: SmallVec<[O; 16]>, + opcodes: Vec, } #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum PrefixError { EncodingError(EncodingError, TokenSeq), UnknownOpcode(TokenSeq), - IncompleteOpcode(TokenSeq, SmallVec<[O; 16]>), + IncompleteOpcode(TokenSeq, Vec), } impl PrefixTable @@ -85,17 +83,17 @@ where let entry = self.get_mut(seq); match entry { Some(PrefixEntry::Terminal(terminal)) => { - return Err(ConflictError::new(seq, smallvec![*terminal, opcode])); + return Err(ConflictError::new(seq, vec![*terminal, opcode])); } Some(PrefixEntry::Prefix(opcodes)) => opcodes.push(opcode), - None => *entry = Some(PrefixEntry::Prefix(smallvec![opcode])), + None => *entry = Some(PrefixEntry::Prefix(vec![opcode])), } seq.push(tok); } let entry = self.get_mut(seq); match entry { Some(PrefixEntry::Terminal(terminal)) => { - return Err(ConflictError::new(seq, smallvec![*terminal, opcode])); + return Err(ConflictError::new(seq, vec![*terminal, opcode])); } Some(PrefixEntry::Prefix(opcodes)) => { let mut opcodes = opcodes.clone(); @@ -135,7 +133,7 @@ where let prefix = match self.get(seq) { Some(PrefixEntry::Terminal(opcode)) => return Some(Ok(*opcode)), Some(PrefixEntry::Prefix(opcodes)) => opcodes.clone(), - None => SmallVec::new(), + None => Vec::new(), }; return Some(Err(PrefixError::IncompleteOpcode(seq, prefix))); } @@ -200,7 +198,7 @@ where impl ConflictError { #[inline] #[must_use] - const fn new(prefix: TokenSeq, opcodes: SmallVec<[O; 16]>) -> Self { + const fn new(prefix: TokenSeq, opcodes: Vec) -> Self { ConflictError { prefix, opcodes } } } @@ -211,31 +209,3 @@ pub trait Tokens { #[must_use] fn tokens(&self) -> &'static [Self::Token]; } - -#[cfg(test)] -mod tests { - use std::mem::size_of; - - use static_assertions::{assert_eq_size, const_assert}; - - use super::*; - use crate::ws::inst::Opcode; - - #[test] - fn optimal_size() { - #[allow(dead_code)] - enum PrefixEntryOf { - Terminal(T), - Prefix(P), - } - - assert_eq_size!( - PrefixEntry, - Option>, - PrefixEntryOf>, - PrefixEntryOf>, - ); - assert_eq_size!(Vec, SmallVec<[Opcode; 16]>); - const_assert!(size_of::>() < size_of::>()); - } -} diff --git a/src/ws/parse.rs b/src/ws/parse.rs index 0e9a026..622339f 100644 --- a/src/ws/parse.rs +++ b/src/ws/parse.rs @@ -10,7 +10,6 @@ use std::iter::FusedIterator; use std::sync::LazyLock; use bitvec::vec::BitVec; -use smallvec::SmallVec; use crate::syntax::{PrefixError, PrefixTable, TokenSeq, Tokens}; use crate::text::EncodingError; @@ -35,7 +34,7 @@ pub struct Parser<'a, L> { pub enum ParseError { EncodingError(EncodingError, Vec), UnknownOpcode(TokenSeq), - IncompleteInst(TokenSeq, SmallVec<[Opcode; 16]>), + IncompleteInst(TokenSeq, Vec), UnterminatedArg(Opcode, BitVec), }