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