Use SusLock to hold pre-calculated indexer hashes.

This commit is contained in:
Stephen Chung
2022-11-25 11:49:00 +08:00
parent 6600862c22
commit 0286a52084
3 changed files with 70 additions and 41 deletions

View File

@@ -3,13 +3,36 @@
use super::{Caches, GlobalRuntimeState, Target};
use crate::ast::{ASTFlags, Expr, OpAssignment};
use crate::config::hashing::SusLock;
use crate::engine::{FN_IDX_GET, FN_IDX_SET};
use crate::types::dynamic::Union;
use crate::types::RestoreOnDrop;
use crate::{Dynamic, Engine, FnArgsVec, Position, RhaiResult, RhaiResultOf, Scope, ERR};
use crate::{
calc_fn_hash, Dynamic, Engine, FnArgsVec, Position, RhaiResult, RhaiResultOf, Scope, ERR,
};
use std::hash::Hash;
#[cfg(feature = "no_std")]
use std::prelude::v1::*;
/// Function call hashes to index getters and setters.
///
/// # Safety
///
/// Uses the extremely unsafe [`SusLock`]. Change to [`OnceCell`] when it is stabilized.
static INDEXER_HASHES: SusLock<(u64, u64)> = SusLock::new();
/// Get the pre-calculated index getter/setter hashes.
#[inline(always)]
#[must_use]
fn hash_idx() -> (u64, u64) {
*INDEXER_HASHES.get_or_init(|| {
(
calc_fn_hash(None, FN_IDX_GET, 2),
calc_fn_hash(None, FN_IDX_SET, 3),
)
})
}
/// Method of chaining.
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub enum ChainType {
@@ -45,16 +68,21 @@ impl Engine {
idx: &mut Dynamic,
pos: Position,
) -> RhaiResultOf<Dynamic> {
let args = &mut [target, idx];
let hash = global.hash_idx_get();
let fn_name = crate::engine::FN_IDX_GET;
let orig_level = global.level;
global.level += 1;
let global = &mut *RestoreOnDrop::lock(global, move |g| g.level = orig_level);
self.exec_native_fn_call(global, caches, fn_name, None, hash, args, true, pos)
.map(|(r, ..)| r)
self.exec_native_fn_call(
global,
caches,
FN_IDX_GET,
None,
hash_idx().0,
&mut [target, idx],
true,
pos,
)
.map(|(r, ..)| r)
}
/// Call a set indexer.
@@ -69,15 +97,20 @@ impl Engine {
is_ref_mut: bool,
pos: Position,
) -> RhaiResultOf<(Dynamic, bool)> {
let hash = global.hash_idx_set();
let args = &mut [target, idx, new_val];
let fn_name = crate::engine::FN_IDX_SET;
let orig_level = global.level;
global.level += 1;
let global = &mut *RestoreOnDrop::lock(global, move |g| g.level = orig_level);
self.exec_native_fn_call(global, caches, fn_name, None, hash, args, is_ref_mut, pos)
self.exec_native_fn_call(
global,
caches,
FN_IDX_SET,
None,
hash_idx().1,
&mut [target, idx, new_val],
is_ref_mut,
pos,
)
}
/// Get the value at the indexed position of a base type.

View File

@@ -58,9 +58,6 @@ pub struct GlobalRuntimeState {
///
/// When that happens, this flag is turned on.
pub always_search_scope: bool,
/// Function call hashes to index getters and setters.
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
fn_hash_indexing: (u64, u64),
/// Embedded [module][crate::Module] resolver.
#[cfg(not(feature = "no_module"))]
pub embedded_module_resolver:
@@ -99,11 +96,6 @@ impl GlobalRuntimeState {
always_search_scope: false,
#[cfg(not(feature = "no_module"))]
embedded_module_resolver: None,
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
fn_hash_indexing: (
crate::calc_fn_hash(None, crate::engine::FN_IDX_GET, 2),
crate::calc_fn_hash(None, crate::engine::FN_IDX_SET, 3),
),
#[cfg(not(feature = "no_module"))]
#[cfg(not(feature = "no_function"))]
constants: None,
@@ -314,20 +306,6 @@ impl GlobalRuntimeState {
pub(crate) const fn source_raw(&self) -> Option<&ImmutableString> {
self.source.as_ref()
}
/// Get the pre-calculated index getter hash.
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
#[inline(always)]
#[must_use]
pub(crate) fn hash_idx_get(&mut self) -> u64 {
self.fn_hash_indexing.0
}
/// Get the pre-calculated index setter hash.
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
#[inline(always)]
#[must_use]
pub(crate) fn hash_idx_set(&mut self) -> u64 {
self.fn_hash_indexing.1
}
/// Return a reference to the debugging interface.
///
@@ -387,9 +365,6 @@ impl fmt::Debug for GlobalRuntimeState {
.field("scope_level", &self.scope_level)
.field("always_search_scope", &self.always_search_scope);
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
f.field("fn_hash_indexing", &self.fn_hash_indexing);
#[cfg(not(feature = "no_module"))]
#[cfg(not(feature = "no_function"))]
f.field("constants", &self.constants);