diff --git a/Cargo.toml b/Cargo.toml index 663af9d63..54c6862e0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,6 @@ arrayvec = { version = "0.5.0", default-features = false, optional = true } byteorder = { version = "1.0", default-features = false } fallible-iterator = { version = "0.2.0", default-features = false, optional = true } indexmap = { version = "1.0.2", optional = true } -smallvec = { version = "1.1.0", default-features = false, optional = true } stable_deref_trait = { version = "1.1.0", default-features = false, optional = true } [dev-dependencies] @@ -36,7 +35,7 @@ test-assembler = "0.1.3" typed-arena = "2" [features] -read = ["arrayvec", "fallible-iterator", "smallvec", "stable_deref_trait"] +read = ["arrayvec", "fallible-iterator", "stable_deref_trait"] write = ["indexmap"] std = ["fallible-iterator/std", "stable_deref_trait/std"] default = ["read", "write", "std"] diff --git a/src/read/abbrev.rs b/src/read/abbrev.rs index 01fad5d21..8c60e627f 100644 --- a/src/read/abbrev.rs +++ b/src/read/abbrev.rs @@ -2,7 +2,9 @@ use alloc::collections::btree_map; use alloc::vec::Vec; -use smallvec::SmallVec; +use core::fmt::{self, Debug}; +use core::iter::FromIterator; +use core::ops::Deref; use crate::common::{DebugAbbrevOffset, SectionId}; use crate::constants; @@ -174,9 +176,6 @@ impl Abbreviations { } } -// Length of 5 based on benchmark results for both x86-64 and i686. -type Attributes = SmallVec<[AttributeSpecification; 5]>; - /// An abbreviation describes the shape of a `DebuggingInformationEntry`'s type: /// its code, tag type, whether it has children, and its set of attributes. #[derive(Debug, Clone, PartialEq, Eq)] @@ -193,7 +192,7 @@ impl Abbreviation { /// ### Panics /// /// Panics if `code` is `0`. - pub fn new( + pub(crate) fn new( code: u64, tag: constants::DwTag, has_children: constants::DwChildren, @@ -256,7 +255,7 @@ impl Abbreviation { /// Parse a series of attribute specifications, terminated by a null attribute /// specification. fn parse_attributes(input: &mut R) -> Result { - let mut attrs = SmallVec::new(); + let mut attrs = Attributes::new(); while let Some(attr) = AttributeSpecification::parse(input)? { attrs.push(attr); @@ -281,6 +280,93 @@ impl Abbreviation { } } +/// A list of attributes found in an `Abbreviation` +#[derive(Clone)] +pub(crate) enum Attributes { + Inline { + buf: [AttributeSpecification; MAX_ATTRIBUTES_INLINE], + len: usize, + }, + Heap(Vec), +} + +// Length of 5 based on benchmark results for both x86-64 and i686. +const MAX_ATTRIBUTES_INLINE: usize = 5; + +impl Attributes { + /// Returns a new empty list of attributes + fn new() -> Attributes { + let default = + AttributeSpecification::new(constants::DW_AT_null, constants::DW_FORM_null, None); + Attributes::Inline { + buf: [default; 5], + len: 0, + } + } + + /// Pushes a new value onto this list of attributes. + fn push(&mut self, attr: AttributeSpecification) { + match self { + Attributes::Heap(list) => return list.push(attr), + Attributes::Inline { + buf, + len: MAX_ATTRIBUTES_INLINE, + } => { + let mut list = buf.to_vec(); + list.push(attr); + *self = Attributes::Heap(list); + } + Attributes::Inline { buf, len } => { + buf[*len] = attr; + *len += 1; + } + } + } +} + +impl Debug for Attributes { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (&**self).fmt(f) + } +} + +impl PartialEq for Attributes { + fn eq(&self, other: &Attributes) -> bool { + &**self == &**other + } +} + +impl Eq for Attributes {} + +impl Deref for Attributes { + type Target = [AttributeSpecification]; + fn deref(&self) -> &[AttributeSpecification] { + match self { + Attributes::Inline { buf, len } => &buf[..*len], + Attributes::Heap(list) => list, + } + } +} + +impl FromIterator for Attributes { + fn from_iter(iter: I) -> Attributes + where + I: IntoIterator, + { + let mut list = Attributes::new(); + for item in iter { + list.push(item); + } + return list; + } +} + +impl From> for Attributes { + fn from(list: Vec) -> Attributes { + Attributes::Heap(list) + } +} + /// The description of an attribute in an abbreviated type. It is a pair of name /// and form. #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -420,7 +506,6 @@ pub mod tests { use crate::test_util::GimliSectionMethods; #[cfg(target_pointer_width = "32")] use core::u32; - use smallvec::smallvec; use test_assembler::Section; pub trait AbbrevSectionMethods { @@ -478,7 +563,7 @@ pub mod tests { 1, constants::DW_TAG_compile_unit, constants::DW_CHILDREN_yes, - smallvec![ + vec![ AttributeSpecification::new( constants::DW_AT_producer, constants::DW_FORM_strp, @@ -489,18 +574,20 @@ pub mod tests { constants::DW_FORM_data2, None, ), - ], + ] + .into(), ); let abbrev2 = Abbreviation::new( 2, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no, - smallvec![AttributeSpecification::new( + vec![AttributeSpecification::new( constants::DW_AT_name, constants::DW_FORM_string, None, - )], + )] + .into(), ); let debug_abbrev = DebugAbbrev::new(&buf, LittleEndian); @@ -519,7 +606,7 @@ pub mod tests { code.into(), constants::DwTag(code), constants::DW_CHILDREN_no, - smallvec![], + vec![].into(), ) } @@ -586,7 +673,7 @@ pub mod tests { code, constants::DwTag(code as u16), constants::DW_CHILDREN_no, - smallvec![], + vec![].into(), ) } @@ -629,7 +716,7 @@ pub mod tests { 1, constants::DW_TAG_compile_unit, constants::DW_CHILDREN_yes, - smallvec![ + vec![ AttributeSpecification::new( constants::DW_AT_producer, constants::DW_FORM_strp, @@ -640,18 +727,20 @@ pub mod tests { constants::DW_FORM_data2, None, ), - ], + ] + .into(), ); let abbrev2 = Abbreviation::new( 2, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no, - smallvec![AttributeSpecification::new( + vec![AttributeSpecification::new( constants::DW_AT_name, constants::DW_FORM_string, None, - )], + )] + .into(), ); let abbrevs = Abbreviations::parse(rest).expect("Should parse abbreviations"); @@ -733,11 +822,12 @@ pub mod tests { 1, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no, - smallvec![AttributeSpecification::new( + vec![AttributeSpecification::new( constants::DW_AT_name, constants::DW_FORM_string, None, - )], + )] + .into(), )); let abbrev = Abbreviation::parse(rest).expect("Should parse abbreviation"); @@ -761,11 +851,12 @@ pub mod tests { 1, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no, - smallvec![AttributeSpecification::new( + vec![AttributeSpecification::new( constants::DW_AT_name, constants::DW_FORM_implicit_const, Some(-42), - )], + )] + .into(), )); let abbrev = Abbreviation::parse(rest).expect("Should parse abbreviation"); diff --git a/src/read/unit.rs b/src/read/unit.rs index 1048d3672..d665392ea 100644 --- a/src/read/unit.rs +++ b/src/read/unit.rs @@ -3447,7 +3447,6 @@ mod tests { use crate::test_util::GimliSectionMethods; use alloc::vec::Vec; use core::cell::Cell; - use smallvec::smallvec; use test_assembler::{Endian, Label, LabelMaker, Section}; // Mixin methods for `Section` to help define binary test data. @@ -4766,7 +4765,7 @@ mod tests { 42, constants::DW_TAG_subprogram, constants::DW_CHILDREN_yes, - smallvec![ + vec![ AttributeSpecification::new(constants::DW_AT_name, constants::DW_FORM_string, None), AttributeSpecification::new(constants::DW_AT_low_pc, constants::DW_FORM_addr, None), AttributeSpecification::new( @@ -4774,7 +4773,8 @@ mod tests { constants::DW_FORM_addr, None, ), - ], + ] + .into(), ); // "foo", 42, 1337, 4 dangling bytes of 0xaa where children would be @@ -4874,7 +4874,7 @@ mod tests { 42, constants::DW_TAG_subprogram, constants::DW_CHILDREN_yes, - smallvec![ + vec![ AttributeSpecification::new(constants::DW_AT_name, constants::DW_FORM_string, None), AttributeSpecification::new(constants::DW_AT_low_pc, constants::DW_FORM_addr, None), AttributeSpecification::new( @@ -4882,7 +4882,8 @@ mod tests { constants::DW_FORM_addr, None, ), - ], + ] + .into(), ); // "foo" diff --git a/src/read/value.rs b/src/read/value.rs index 0cb4abe48..292320485 100644 --- a/src/read/value.rs +++ b/src/read/value.rs @@ -912,7 +912,6 @@ mod tests { Abbreviation, AttributeSpecification, DebuggingInformationEntry, EndianSlice, UnitHeader, UnitOffset, }; - use smallvec::smallvec; #[test] #[rustfmt::skip] @@ -933,7 +932,7 @@ mod tests { 42, constants::DW_TAG_base_type, constants::DW_CHILDREN_no, - smallvec![ + vec![ AttributeSpecification::new( constants::DW_AT_byte_size, constants::DW_FORM_udata, @@ -949,7 +948,7 @@ mod tests { constants::DW_FORM_udata, None, ), - ], + ].into(), ); for &(attrs, result) in &[