diff --git a/src/ast/expr.rs b/src/ast/expr.rs index 76c9587d..b3b55aac 100644 --- a/src/ast/expr.rs +++ b/src/ast/expr.rs @@ -493,6 +493,9 @@ impl fmt::Debug for Expr { } } f.write_str(&x.3)?; + if let Some(n) = x.1.index() { + write!(f, " #{}", n)?; + } if let Some(n) = i.map_or_else(|| x.0, |n| NonZeroUsize::new(n.get() as usize)) { write!(f, " #{}", n)?; } diff --git a/src/ast/stmt.rs b/src/ast/stmt.rs index a763860c..a72e2f01 100644 --- a/src/ast/stmt.rs +++ b/src/ast/stmt.rs @@ -302,6 +302,10 @@ pub struct TryCatchBlock { pub catch_block: StmtBlock, } +/// Number of items to keep inline for [`StmtBlockContainer`]. +#[cfg(not(feature = "no_std"))] +const STMT_BLOCK_INLINE_SIZE: usize = 8; + /// _(internals)_ The underlying container type for [`StmtBlock`]. /// Exported under the `internals` feature only. /// @@ -309,7 +313,7 @@ pub struct TryCatchBlock { /// hold a statements block, with the assumption that most program blocks would container fewer than /// 8 statements, and those that do have a lot more statements. #[cfg(not(feature = "no_std"))] -pub type StmtBlockContainer = smallvec::SmallVec<[Stmt; 8]>; +pub type StmtBlockContainer = smallvec::SmallVec<[Stmt; STMT_BLOCK_INLINE_SIZE]>; /// _(internals)_ The underlying container type for [`StmtBlock`]. /// Exported under the `internals` feature only. @@ -491,9 +495,9 @@ impl From for StmtBlock { impl IntoIterator for StmtBlock { type Item = Stmt; #[cfg(not(feature = "no_std"))] - type IntoIter = smallvec::IntoIter<[Stmt; 8]>; + type IntoIter = smallvec::IntoIter<[Stmt; STMT_BLOCK_INLINE_SIZE]>; #[cfg(feature = "no_std")] - type IntoIter = smallvec::IntoIter<[Stmt; 3]>; + type IntoIter = smallvec::IntoIter<[Stmt; crate::STATIC_VEC_INLINE_SIZE]>; #[inline(always)] fn into_iter(self) -> Self::IntoIter { diff --git a/src/eval/expr.rs b/src/eval/expr.rs index ce34a8ad..72915161 100644 --- a/src/eval/expr.rs +++ b/src/eval/expr.rs @@ -24,13 +24,13 @@ impl Engine { let root = namespace.root(); - // Qualified - check if the root module is directly indexed let index = if global.always_search_scope { None } else { namespace.index() }; + // Qualified - check if the root module is directly indexed if let Some(index) = index { let offset = global.num_imports() - index.get(); diff --git a/src/lib.rs b/src/lib.rs index 4976d4b7..7b36c9cf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -341,6 +341,9 @@ pub use eval::{Caches, FnResolutionCache, FnResolutionCacheEntry, GlobalRuntimeS #[cfg(feature = "metadata")] pub use api::definitions::Definitions; +/// Number of items to keep inline for [`StaticVec`]. +const STATIC_VEC_INLINE_SIZE: usize = 3; + /// Alias to [`smallvec::SmallVec<[T; 3]>`](https://crates.io/crates/smallvec), which is a /// specialized [`Vec`] backed by a small, inline, fixed-size array when there are ≤ 3 items stored. /// @@ -373,7 +376,7 @@ pub use api::definitions::Definitions; /// most scripts load fewer than 4 external modules; most module paths contain fewer than 4 levels /// (e.g. `std::collections::map::HashMap` is 4 levels and it is just about as long as they get). #[cfg(not(feature = "internals"))] -type StaticVec = smallvec::SmallVec<[T; 3]>; +type StaticVec = smallvec::SmallVec<[T; STATIC_VEC_INLINE_SIZE]>; /// _(internals)_ Alias to [`smallvec::SmallVec<[T; 3]>`](https://crates.io/crates/smallvec), /// which is a [`Vec`] backed by a small, inline, fixed-size array when there are ≤ 3 items stored. @@ -408,7 +411,11 @@ type StaticVec = smallvec::SmallVec<[T; 3]>; /// most scripts load fewer than 4 external modules; most module paths contain fewer than 4 levels /// (e.g. `std::collections::map::HashMap` is 4 levels and it is just about as long as they get). #[cfg(feature = "internals")] -pub type StaticVec = smallvec::SmallVec<[T; 3]>; +pub type StaticVec = smallvec::SmallVec<[T; STATIC_VEC_INLINE_SIZE]>; + +/// Number of items to keep inline for [`FnArgsVec`]. +#[cfg(not(feature = "no_closure"))] +const FN_ARGS_VEC_INLINE_SIZE: usize = 5; /// Inline arguments storage for function calls. /// @@ -423,7 +430,7 @@ pub type StaticVec = smallvec::SmallVec<[T; 3]>; /// /// Under `no_closure`, this type aliases to [`StaticVec`][crate::StaticVec] instead. #[cfg(not(feature = "no_closure"))] -type FnArgsVec = smallvec::SmallVec<[T; 5]>; +type FnArgsVec = smallvec::SmallVec<[T; FN_ARGS_VEC_INLINE_SIZE]>; /// Inline arguments storage for function calls. /// This type aliases to [`StaticVec`][crate::StaticVec]. diff --git a/src/module/resolvers/collection.rs b/src/module/resolvers/collection.rs index fd6780d4..8a61d715 100644 --- a/src/module/resolvers/collection.rs +++ b/src/module/resolvers/collection.rs @@ -1,7 +1,10 @@ -use crate::{Engine, Module, ModuleResolver, Position, RhaiResultOf, Shared, ERR}; +use crate::{ + Engine, Module, ModuleResolver, Position, RhaiResultOf, Shared, StaticVec, ERR, + STATIC_VEC_INLINE_SIZE, +}; #[cfg(feature = "no_std")] use std::prelude::v1::*; -use std::{ops::AddAssign, slice::Iter, vec::IntoIter}; +use std::{ops::AddAssign, slice::Iter}; /// [Module] resolution service that holds a collection of module resolvers, /// to be searched in sequential order. @@ -21,7 +24,7 @@ use std::{ops::AddAssign, slice::Iter, vec::IntoIter}; /// engine.set_module_resolver(collection); /// ``` #[derive(Default)] -pub struct ModuleResolversCollection(Vec>); +pub struct ModuleResolversCollection(StaticVec>); impl ModuleResolversCollection { /// Create a new [`ModuleResolversCollection`]. @@ -43,7 +46,7 @@ impl ModuleResolversCollection { #[inline(always)] #[must_use] pub const fn new() -> Self { - Self(Vec::new()) + Self(StaticVec::new_const()) } /// Append a [module resolver][ModuleResolver] to the end. #[inline(always)] @@ -109,7 +112,7 @@ impl ModuleResolversCollection { impl IntoIterator for ModuleResolversCollection { type Item = Box; - type IntoIter = IntoIter>; + type IntoIter = smallvec::IntoIter<[Box; STATIC_VEC_INLINE_SIZE]>; #[inline(always)] #[must_use] diff --git a/src/types/interner.rs b/src/types/interner.rs index 5832dbe0..4b7d387e 100644 --- a/src/types/interner.rs +++ b/src/types/interner.rs @@ -110,7 +110,7 @@ impl StringsInterner<'_> { // If the interner is over capacity, remove the longest entry that has the lowest count if self.cache.len() > self.capacity { - // Leave some buffer to grow when shrinking the cache. + // Throttle: leave some buffer to grow when shrinking the cache. // We leave at least two entries, one for the empty string, and one for the string // that has just been inserted. let max = if self.capacity < 5 {