Use SusLock to hold pre-calculated indexer hashes.
This commit is contained in:
parent
6600862c22
commit
0286a52084
@ -94,15 +94,25 @@ fn hokmalock(address: usize) -> &'static HokmaLock {
|
||||
&RECORDS[address % LEN]
|
||||
}
|
||||
|
||||
// Safety: lol, there is a reason its called `SusLock<T>`
|
||||
/// # Safety
|
||||
///
|
||||
/// LOL, there is a reason its called `SusLock`
|
||||
#[must_use]
|
||||
struct SusLock<T: 'static> {
|
||||
pub struct SusLock<T: 'static> {
|
||||
initialized: AtomicBool,
|
||||
data: UnsafeCell<MaybeUninit<T>>,
|
||||
_marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T: 'static> Default for SusLock<T> {
|
||||
#[inline(always)]
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: 'static> SusLock<T> {
|
||||
/// Create a new [`SusLock`].
|
||||
#[inline]
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
@ -112,12 +122,15 @@ impl<T: 'static> SusLock<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Is the [`SusLock`] initialized?
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub fn is_initialized(&self) -> bool {
|
||||
self.initialized.load(Ordering::SeqCst)
|
||||
}
|
||||
|
||||
/// Return the value of the [`SusLock`] (if initialized).
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn get(&self) -> Option<&'static T> {
|
||||
if self.initialized.load(Ordering::SeqCst) {
|
||||
@ -133,6 +146,8 @@ impl<T: 'static> SusLock<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the value of the [`SusLock`], initializing it if not yet done.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn get_or_init(&self, f: impl FnOnce() -> T) -> &'static T {
|
||||
if !self.initialized.load(Ordering::SeqCst) {
|
||||
@ -147,7 +162,13 @@ impl<T: 'static> SusLock<T> {
|
||||
self.get().unwrap()
|
||||
}
|
||||
|
||||
pub fn set(&self, value: T) -> Result<(), T> {
|
||||
/// Initialize the value of the [`SusLock`].
|
||||
///
|
||||
/// # Error
|
||||
///
|
||||
/// If the [`SusLock`] has already been initialized, the current value is returned as error.
|
||||
#[inline]
|
||||
pub fn init(&self, value: T) -> Result<(), T> {
|
||||
if self.initialized.load(Ordering::SeqCst) {
|
||||
Err(value)
|
||||
} else {
|
||||
@ -198,7 +219,7 @@ static AHASH_SEED: SusLock<Option<[u64; 4]>> = SusLock::new();
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub fn set_ahash_seed(new_seed: Option<[u64; 4]>) -> Result<(), Option<[u64; 4]>> {
|
||||
AHASH_SEED.set(new_seed)
|
||||
AHASH_SEED.init(new_seed)
|
||||
}
|
||||
|
||||
/// Get the current hashing Seed.
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user