Fix sync build.

This commit is contained in:
Stephen Chung 2022-11-24 16:05:23 +08:00
parent d1913edf3c
commit b4ef89b596
6 changed files with 25 additions and 26 deletions

View File

@ -1,5 +1,6 @@
//! Module that defines the public compilation API of [`Engine`]. //! Module that defines the public compilation API of [`Engine`].
use crate::func::native::locked_write;
use crate::parser::{ParseResult, ParseState}; use crate::parser::{ParseResult, ParseState};
use crate::{Engine, OptimizationLevel, Scope, AST}; use crate::{Engine, OptimizationLevel, Scope, AST};
#[cfg(feature = "no_std")] #[cfg(feature = "no_std")]
@ -221,7 +222,7 @@ impl Engine {
scripts.as_ref(), scripts.as_ref(),
self.token_mapper.as_ref().map(<_>::as_ref), self.token_mapper.as_ref().map(<_>::as_ref),
); );
let interned_strings = &mut *self.interned_strings.borrow_mut(); let interned_strings = &mut *locked_write(&self.interned_strings);
let mut state = ParseState::new(self, scope, interned_strings, tokenizer_control); let mut state = ParseState::new(self, scope, interned_strings, tokenizer_control);
let mut _ast = self.parse(&mut stream.peekable(), &mut state, optimization_level)?; let mut _ast = self.parse(&mut stream.peekable(), &mut state, optimization_level)?;
#[cfg(feature = "metadata")] #[cfg(feature = "metadata")]
@ -295,7 +296,7 @@ impl Engine {
self.lex_raw(&scripts, self.token_mapper.as_ref().map(<_>::as_ref)); self.lex_raw(&scripts, self.token_mapper.as_ref().map(<_>::as_ref));
let mut peekable = stream.peekable(); let mut peekable = stream.peekable();
let interned_strings = &mut *self.interned_strings.borrow_mut(); let interned_strings = &mut *locked_write(&self.interned_strings);
let mut state = ParseState::new(self, scope, interned_strings, tokenizer_control); let mut state = ParseState::new(self, scope, interned_strings, tokenizer_control);
self.parse_global_expr(&mut peekable, &mut state, |_| {}, self.optimization_level) self.parse_global_expr(&mut peekable, &mut state, |_| {}, self.optimization_level)
} }

View File

@ -1,6 +1,7 @@
//! Module that defines the public evaluation API of [`Engine`]. //! Module that defines the public evaluation API of [`Engine`].
use crate::eval::{Caches, GlobalRuntimeState}; use crate::eval::{Caches, GlobalRuntimeState};
use crate::func::native::locked_write;
use crate::parser::ParseState; use crate::parser::ParseState;
use crate::types::dynamic::Variant; use crate::types::dynamic::Variant;
use crate::{ use crate::{
@ -118,7 +119,7 @@ impl Engine {
) -> RhaiResultOf<T> { ) -> RhaiResultOf<T> {
let scripts = [script]; let scripts = [script];
let ast = { let ast = {
let interned_strings = &mut *self.interned_strings.borrow_mut(); let interned_strings = &mut *locked_write(&self.interned_strings);
let (stream, tokenizer_control) = let (stream, tokenizer_control) =
self.lex_raw(&scripts, self.token_mapper.as_ref().map(<_>::as_ref)); self.lex_raw(&scripts, self.token_mapper.as_ref().map(<_>::as_ref));

View File

@ -1,6 +1,7 @@
//! Module that defines JSON manipulation functions for [`Engine`]. //! Module that defines JSON manipulation functions for [`Engine`].
#![cfg(not(feature = "no_object"))] #![cfg(not(feature = "no_object"))]
use crate::func::native::locked_write;
use crate::parser::{ParseSettingFlags, ParseState}; use crate::parser::{ParseSettingFlags, ParseState};
use crate::tokenizer::Token; use crate::tokenizer::Token;
use crate::{Engine, LexError, Map, OptimizationLevel, RhaiResultOf, Scope}; use crate::{Engine, LexError, Map, OptimizationLevel, RhaiResultOf, Scope};
@ -118,7 +119,7 @@ impl Engine {
let ast = { let ast = {
let scope = Scope::new(); let scope = Scope::new();
let interned_strings = &mut *self.interned_strings.borrow_mut(); let interned_strings = &mut *locked_write(&self.interned_strings);
let mut state = ParseState::new(self, &scope, interned_strings, tokenizer_control); let mut state = ParseState::new(self, &scope, interned_strings, tokenizer_control);
self.parse_global_expr( self.parse_global_expr(

View File

@ -1,6 +1,7 @@
//! Module that defines the public evaluation API of [`Engine`]. //! Module that defines the public evaluation API of [`Engine`].
use crate::eval::{Caches, GlobalRuntimeState}; use crate::eval::{Caches, GlobalRuntimeState};
use crate::func::native::locked_write;
use crate::parser::ParseState; use crate::parser::ParseState;
use crate::{Engine, RhaiResultOf, Scope, AST}; use crate::{Engine, RhaiResultOf, Scope, AST};
#[cfg(feature = "no_std")] #[cfg(feature = "no_std")]
@ -57,7 +58,7 @@ impl Engine {
pub fn run_with_scope(&self, scope: &mut Scope, script: &str) -> RhaiResultOf<()> { pub fn run_with_scope(&self, scope: &mut Scope, script: &str) -> RhaiResultOf<()> {
let scripts = [script]; let scripts = [script];
let ast = { let ast = {
let interned_strings = &mut *self.interned_strings.borrow_mut(); let interned_strings = &mut *locked_write(&self.interned_strings);
let (stream, tokenizer_control) = let (stream, tokenizer_control) =
self.lex_raw(&scripts, self.token_mapper.as_ref().map(<_>::as_ref)); self.lex_raw(&scripts, self.token_mapper.as_ref().map(<_>::as_ref));

View File

@ -51,7 +51,7 @@ pub struct ParseState<'e, 's> {
pub tokenizer_control: TokenizerControl, pub tokenizer_control: TokenizerControl,
/// Controls whether parsing of an expression should stop given the next token. /// Controls whether parsing of an expression should stop given the next token.
pub expr_filter: fn(&Token) -> bool, pub expr_filter: fn(&Token) -> bool,
/// String interners. /// Strings interner.
interned_strings: &'s mut StringsInterner, interned_strings: &'s mut StringsInterner,
/// External [scope][Scope] with constants. /// External [scope][Scope] with constants.
pub scope: &'e Scope<'e>, pub scope: &'e Scope<'e>,

View File

@ -3,6 +3,7 @@
use super::BloomFilterU64; use super::BloomFilterU64;
use crate::func::{hashing::get_hasher, StraightHashMap}; use crate::func::{hashing::get_hasher, StraightHashMap};
use crate::ImmutableString; use crate::ImmutableString;
use ahash::HashMapExt;
#[cfg(feature = "no_std")] #[cfg(feature = "no_std")]
use hashbrown::hash_map::Entry; use hashbrown::hash_map::Entry;
#[cfg(not(feature = "no_std"))] #[cfg(not(feature = "no_std"))]
@ -26,14 +27,10 @@ pub const MAX_STRING_LEN: usize = 24;
#[derive(Clone)] #[derive(Clone)]
#[must_use] #[must_use]
pub struct StringsInterner { pub struct StringsInterner {
/// Maximum number of strings interned.
pub capacity: usize,
/// Maximum string length.
pub max_string_len: usize,
/// Cached strings. /// Cached strings.
cache: StraightHashMap<ImmutableString>, cache: StraightHashMap<ImmutableString>,
/// Bloom filter to avoid caching "one-hit wonders". /// Bloom filter to avoid caching "one-hit wonders".
filter: BloomFilterU64, bloom_filter: BloomFilterU64,
} }
impl Default for StringsInterner { impl Default for StringsInterner {
@ -56,10 +53,8 @@ impl StringsInterner {
#[inline(always)] #[inline(always)]
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
capacity: MAX_INTERNED_STRINGS, cache: StraightHashMap::new(),
max_string_len: MAX_STRING_LEN, bloom_filter: BloomFilterU64::new(),
cache: StraightHashMap::default(),
filter: BloomFilterU64::new(),
} }
} }
@ -87,10 +82,14 @@ impl StringsInterner {
let hash = hasher.finish(); let hash = hasher.finish();
// Cache long strings only on the second try to avoid caching "one-hit wonders". // Cache long strings only on the second try to avoid caching "one-hit wonders".
if key.len() > MAX_STRING_LEN && self.filter.is_absent_and_set(hash) { if key.len() > MAX_STRING_LEN && self.bloom_filter.is_absent_and_set(hash) {
return mapper(text); return mapper(text);
} }
if self.cache.is_empty() {
self.cache.reserve(MAX_INTERNED_STRINGS);
}
let result = match self.cache.entry(hash) { let result = match self.cache.entry(hash) {
Entry::Occupied(e) => return e.get().clone(), Entry::Occupied(e) => return e.get().clone(),
Entry::Vacant(e) => { Entry::Vacant(e) => {
@ -110,26 +109,22 @@ impl StringsInterner {
} }
/// If the interner is over capacity, remove the longest entry that has the lowest count /// If the interner is over capacity, remove the longest entry that has the lowest count
fn throttle_cache(&mut self, hash: u64) { #[inline]
if self.cache.len() <= self.capacity { fn throttle_cache(&mut self, skip_hash: u64) {
if self.cache.len() <= MAX_INTERNED_STRINGS {
return; return;
} }
// Leave some buffer to grow when shrinking the cache. // 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 // We leave at least two entries, one for the empty string, and one for the string
// that has just been inserted. // that has just been inserted.
let max = if self.capacity < 5 { while self.cache.len() > MAX_INTERNED_STRINGS - 3 {
2
} else {
self.capacity - 3
};
while self.cache.len() > max {
let (_, _, n) = self let (_, _, n) = self
.cache .cache
.iter() .iter()
.fold((0, usize::MAX, 0), |(x, c, n), (&k, v)| { .fold((0, usize::MAX, 0), |(x, c, n), (&k, v)| {
if k != hash && (v.strong_count() < c || (v.strong_count() == c && v.len() > x)) if k != skip_hash
&& (v.strong_count() < c || (v.strong_count() == c && v.len() > x))
{ {
(v.len(), v.strong_count(), k) (v.len(), v.strong_count(), k)
} else { } else {