Use caching for fast operators.
This commit is contained in:
parent
0516e8088c
commit
fcdd2eb143
@ -242,17 +242,57 @@ impl Engine {
|
||||
|
||||
let arg_values = &mut [&mut lhs, &mut rhs];
|
||||
|
||||
return if let Some(f) =
|
||||
crate::func::get_builtin_binary_op_fn(&name, arg_values[0], arg_values[1])
|
||||
{
|
||||
let context = (self, name, None, &*global, lib, pos, level).into();
|
||||
(f)(context, arg_values)
|
||||
} else {
|
||||
self.exec_fn_call(
|
||||
None, global, caches, lib, name, *hashes, arg_values, false, false, pos, level,
|
||||
let hash = crate::func::combine_hashes(
|
||||
hashes.native,
|
||||
crate::func::calc_fn_params_hash(arg_values.iter().map(|a| a.type_id())),
|
||||
);
|
||||
|
||||
let c = caches.fn_resolution_cache_mut();
|
||||
|
||||
let entry = if c.contains_key(&hash) {
|
||||
match c.get(&hash).unwrap() {
|
||||
Some(entry) => entry,
|
||||
None => {
|
||||
return Err(ERR::ErrorFunctionNotFound(
|
||||
self.gen_fn_call_signature(
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
&crate::ast::Namespace::NONE,
|
||||
name,
|
||||
arg_values,
|
||||
),
|
||||
pos,
|
||||
)
|
||||
.map(|(v, ..)| v)
|
||||
.into())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
match crate::func::get_builtin_binary_op_fn(&name, arg_values[0], arg_values[1]) {
|
||||
Some(f) => {
|
||||
let entry = crate::eval::FnResolutionCacheEntry {
|
||||
func: crate::func::CallableFunction::from_method(
|
||||
Box::new(f) as Box<crate::func::FnAny>
|
||||
),
|
||||
source: None,
|
||||
};
|
||||
c.insert(hash, Some(entry));
|
||||
c.get(&hash).unwrap().as_ref().unwrap()
|
||||
}
|
||||
None => {
|
||||
println!("Exec {name} with {:?}", arg_values);
|
||||
return self
|
||||
.exec_fn_call(
|
||||
None, global, caches, lib, name, *hashes, arg_values, false, false,
|
||||
pos, level,
|
||||
)
|
||||
.map(|(v, ..)| v);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let func = entry.func.get_native_fn().unwrap();
|
||||
let context = (self, name, None, &*global, lib, pos, level).into();
|
||||
let result = (func)(context, arg_values);
|
||||
return self.check_return_value(result, pos);
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
|
@ -131,7 +131,7 @@ impl Engine {
|
||||
/// Generate the signature for a function call.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
fn gen_call_signature(
|
||||
pub(crate) fn gen_fn_call_signature(
|
||||
&self,
|
||||
#[cfg(not(feature = "no_module"))] namespace: &crate::ast::Namespace,
|
||||
fn_name: &str,
|
||||
@ -174,26 +174,26 @@ impl Engine {
|
||||
fn resolve_fn<'s>(
|
||||
&self,
|
||||
_global: &GlobalRuntimeState,
|
||||
state: &'s mut Caches,
|
||||
caches: &'s mut Caches,
|
||||
lib: &[&Module],
|
||||
fn_name: &str,
|
||||
hash_script: u64,
|
||||
hash_base: u64,
|
||||
args: Option<&mut FnCallArgs>,
|
||||
allow_dynamic: bool,
|
||||
is_op_assignment: bool,
|
||||
) -> Option<&'s FnResolutionCacheEntry> {
|
||||
if hash_script == 0 {
|
||||
if hash_base == 0 {
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut hash = args.as_ref().map_or(hash_script, |args| {
|
||||
let mut hash = args.as_ref().map_or(hash_base, |args| {
|
||||
combine_hashes(
|
||||
hash_script,
|
||||
hash_base,
|
||||
calc_fn_params_hash(args.iter().map(|a| a.type_id())),
|
||||
)
|
||||
});
|
||||
|
||||
let result = state
|
||||
let result = caches
|
||||
.fn_resolution_cache_mut()
|
||||
.entry(hash)
|
||||
.or_insert_with(|| {
|
||||
@ -248,21 +248,21 @@ impl Engine {
|
||||
|
||||
// Check `Dynamic` parameters for functions with parameters
|
||||
if allow_dynamic && max_bitmask == 0 && num_args > 0 {
|
||||
let is_dynamic = lib.iter().any(|&m| m.contains_dynamic_fn(hash_script))
|
||||
let is_dynamic = lib.iter().any(|&m| m.contains_dynamic_fn(hash_base))
|
||||
|| self
|
||||
.global_modules
|
||||
.iter()
|
||||
.any(|m| m.contains_dynamic_fn(hash_script));
|
||||
.any(|m| m.contains_dynamic_fn(hash_base));
|
||||
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
let is_dynamic = is_dynamic
|
||||
|| _global
|
||||
.iter_imports_raw()
|
||||
.any(|(_, m)| m.contains_dynamic_fn(hash_script))
|
||||
.any(|(_, m)| m.contains_dynamic_fn(hash_base))
|
||||
|| self
|
||||
.global_sub_modules
|
||||
.values()
|
||||
.any(|m| m.contains_dynamic_fn(hash_script));
|
||||
.any(|m| m.contains_dynamic_fn(hash_base));
|
||||
|
||||
// Set maximum bitmask when there are dynamic versions of the function
|
||||
if is_dynamic {
|
||||
@ -317,7 +317,7 @@ impl Engine {
|
||||
}
|
||||
}),
|
||||
);
|
||||
hash = combine_hashes(hash_script, hash_params);
|
||||
hash = combine_hashes(hash_base, hash_params);
|
||||
|
||||
bitmask += 1;
|
||||
}
|
||||
@ -542,7 +542,7 @@ impl Engine {
|
||||
|
||||
// Raise error
|
||||
_ => Err(ERR::ErrorFunctionNotFound(
|
||||
self.gen_call_signature(
|
||||
self.gen_fn_call_signature(
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
&crate::ast::Namespace::NONE,
|
||||
name,
|
||||
@ -1429,7 +1429,7 @@ impl Engine {
|
||||
Some(f) => unreachable!("unknown function type: {:?}", f),
|
||||
|
||||
None => Err(ERR::ErrorFunctionNotFound(
|
||||
self.gen_call_signature(namespace, fn_name, &args),
|
||||
self.gen_fn_call_signature(namespace, fn_name, &args),
|
||||
pos,
|
||||
)
|
||||
.into()),
|
||||
|
@ -123,7 +123,7 @@ pub mod array_functions {
|
||||
/// let x = [1, 2, 3];
|
||||
/// let y = [true, 'x'];
|
||||
///
|
||||
/// x.push(y);
|
||||
/// x.append(y);
|
||||
///
|
||||
/// print(x); // prints "[1, 2, 3, true, 'x']"
|
||||
/// ```
|
||||
|
Loading…
Reference in New Issue
Block a user