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]
|
&RECORDS[address % LEN]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Safety: lol, there is a reason its called `SusLock<T>`
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// LOL, there is a reason its called `SusLock`
|
||||||
#[must_use]
|
#[must_use]
|
||||||
struct SusLock<T: 'static> {
|
pub struct SusLock<T: 'static> {
|
||||||
initialized: AtomicBool,
|
initialized: AtomicBool,
|
||||||
data: UnsafeCell<MaybeUninit<T>>,
|
data: UnsafeCell<MaybeUninit<T>>,
|
||||||
_marker: PhantomData<T>,
|
_marker: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: 'static> Default for SusLock<T> {
|
||||||
|
#[inline(always)]
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: 'static> SusLock<T> {
|
impl<T: 'static> SusLock<T> {
|
||||||
|
/// Create a new [`SusLock`].
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -112,12 +122,15 @@ impl<T: 'static> SusLock<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Is the [`SusLock`] initialized?
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn is_initialized(&self) -> bool {
|
pub fn is_initialized(&self) -> bool {
|
||||||
self.initialized.load(Ordering::SeqCst)
|
self.initialized.load(Ordering::SeqCst)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the value of the [`SusLock`] (if initialized).
|
||||||
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn get(&self) -> Option<&'static T> {
|
pub fn get(&self) -> Option<&'static T> {
|
||||||
if self.initialized.load(Ordering::SeqCst) {
|
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]
|
#[must_use]
|
||||||
pub fn get_or_init(&self, f: impl FnOnce() -> T) -> &'static T {
|
pub fn get_or_init(&self, f: impl FnOnce() -> T) -> &'static T {
|
||||||
if !self.initialized.load(Ordering::SeqCst) {
|
if !self.initialized.load(Ordering::SeqCst) {
|
||||||
@ -147,7 +162,13 @@ impl<T: 'static> SusLock<T> {
|
|||||||
self.get().unwrap()
|
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) {
|
if self.initialized.load(Ordering::SeqCst) {
|
||||||
Err(value)
|
Err(value)
|
||||||
} else {
|
} else {
|
||||||
@ -198,7 +219,7 @@ static AHASH_SEED: SusLock<Option<[u64; 4]>> = SusLock::new();
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn set_ahash_seed(new_seed: Option<[u64; 4]>) -> Result<(), Option<[u64; 4]>> {
|
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.
|
/// Get the current hashing Seed.
|
||||||
|
@ -3,13 +3,36 @@
|
|||||||
|
|
||||||
use super::{Caches, GlobalRuntimeState, Target};
|
use super::{Caches, GlobalRuntimeState, Target};
|
||||||
use crate::ast::{ASTFlags, Expr, OpAssignment};
|
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::dynamic::Union;
|
||||||
use crate::types::RestoreOnDrop;
|
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;
|
use std::hash::Hash;
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
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.
|
/// Method of chaining.
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||||
pub enum ChainType {
|
pub enum ChainType {
|
||||||
@ -45,15 +68,20 @@ impl Engine {
|
|||||||
idx: &mut Dynamic,
|
idx: &mut Dynamic,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
) -> RhaiResultOf<Dynamic> {
|
) -> 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;
|
let orig_level = global.level;
|
||||||
global.level += 1;
|
global.level += 1;
|
||||||
let global = &mut *RestoreOnDrop::lock(global, move |g| g.level = orig_level);
|
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)
|
self.exec_native_fn_call(
|
||||||
|
global,
|
||||||
|
caches,
|
||||||
|
FN_IDX_GET,
|
||||||
|
None,
|
||||||
|
hash_idx().0,
|
||||||
|
&mut [target, idx],
|
||||||
|
true,
|
||||||
|
pos,
|
||||||
|
)
|
||||||
.map(|(r, ..)| r)
|
.map(|(r, ..)| r)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,15 +97,20 @@ impl Engine {
|
|||||||
is_ref_mut: bool,
|
is_ref_mut: bool,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
) -> RhaiResultOf<(Dynamic, bool)> {
|
) -> 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;
|
let orig_level = global.level;
|
||||||
global.level += 1;
|
global.level += 1;
|
||||||
let global = &mut *RestoreOnDrop::lock(global, move |g| g.level = orig_level);
|
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.
|
/// 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.
|
/// When that happens, this flag is turned on.
|
||||||
pub always_search_scope: bool,
|
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.
|
/// Embedded [module][crate::Module] resolver.
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
pub embedded_module_resolver:
|
pub embedded_module_resolver:
|
||||||
@ -99,11 +96,6 @@ impl GlobalRuntimeState {
|
|||||||
always_search_scope: false,
|
always_search_scope: false,
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
embedded_module_resolver: None,
|
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_module"))]
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
constants: None,
|
constants: None,
|
||||||
@ -314,20 +306,6 @@ impl GlobalRuntimeState {
|
|||||||
pub(crate) const fn source_raw(&self) -> Option<&ImmutableString> {
|
pub(crate) const fn source_raw(&self) -> Option<&ImmutableString> {
|
||||||
self.source.as_ref()
|
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.
|
/// Return a reference to the debugging interface.
|
||||||
///
|
///
|
||||||
@ -387,9 +365,6 @@ impl fmt::Debug for GlobalRuntimeState {
|
|||||||
.field("scope_level", &self.scope_level)
|
.field("scope_level", &self.scope_level)
|
||||||
.field("always_search_scope", &self.always_search_scope);
|
.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_module"))]
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
f.field("constants", &self.constants);
|
f.field("constants", &self.constants);
|
||||||
|
Loading…
Reference in New Issue
Block a user