Expand function call arguments inline storage.

This commit is contained in:
Stephen Chung 2021-12-27 12:27:44 +08:00
parent 05d4c81e7a
commit dfb3378b28
3 changed files with 50 additions and 30 deletions

View File

@ -2,19 +2,16 @@
use crate::ast::{Expr, FnCallExpr, Ident, OpAssignment, Stmt, AST_OPTION_FLAGS::*};
use crate::custom_syntax::CustomSyntax;
use crate::func::{
get_hasher,
native::{OnDebugCallback, OnParseTokenCallback, OnPrintCallback, OnVarCallback},
CallableFunction, IteratorFn,
};
use crate::func::native::{OnDebugCallback, OnParseTokenCallback, OnPrintCallback, OnVarCallback};
use crate::func::{get_hasher, CallableFunction, IteratorFn};
use crate::module::Namespace;
use crate::packages::{Package, StandardPackage};
use crate::r#unsafe::unsafe_cast_var_name_to_lifetime;
use crate::tokenizer::Token;
use crate::types::dynamic::{map_std_type_name, AccessMode, Union, Variant};
use crate::{
calc_fn_params_hash, combine_hashes, Dynamic, Identifier, ImmutableString, Module, Position,
RhaiError, RhaiResult, RhaiResultOf, Scope, Shared, StaticVec, ERR, INT,
calc_fn_params_hash, combine_hashes, Dynamic, FnArgsVec, Identifier, ImmutableString, Module,
Position, RhaiError, RhaiResult, RhaiResultOf, Scope, Shared, StaticVec, ERR, INT,
};
#[cfg(feature = "no_std")]
use std::prelude::v1::*;
@ -372,7 +369,7 @@ enum ChainArgument {
/// Arguments to a dot method call.
/// Wrapped values are the arguments plus the [position][Position] of the first argument.
#[cfg(not(feature = "no_object"))]
MethodCallArgs(StaticVec<Dynamic>, Position),
MethodCallArgs(FnArgsVec<Dynamic>, Position),
/// Index value and [position][Position].
#[cfg(not(feature = "no_index"))]
IndexValue(Dynamic, Position),
@ -395,7 +392,7 @@ impl ChainArgument {
#[inline(always)]
#[cfg(not(feature = "no_object"))]
#[must_use]
pub fn into_fn_call_args(self) -> Option<(StaticVec<Dynamic>, Position)> {
pub fn into_fn_call_args(self) -> Option<(FnArgsVec<Dynamic>, Position)> {
match self {
Self::MethodCallArgs(values, pos) => Some((values, pos)),
_ => None,
@ -418,9 +415,9 @@ impl ChainArgument {
}
#[cfg(not(feature = "no_object"))]
impl From<(StaticVec<Dynamic>, Position)> for ChainArgument {
impl From<(FnArgsVec<Dynamic>, Position)> for ChainArgument {
#[inline(always)]
fn from((values, pos): (StaticVec<Dynamic>, Position)) -> Self {
fn from((values, pos): (FnArgsVec<Dynamic>, Position)) -> Self {
Self::MethodCallArgs(values, pos)
}
}
@ -1325,7 +1322,7 @@ impl Engine {
root: (&str, Position),
rhs: &Expr,
terminate_chaining: bool,
idx_values: &mut StaticVec<ChainArgument>,
idx_values: &mut FnArgsVec<ChainArgument>,
chain_type: ChainType,
level: usize,
new_val: Option<((Dynamic, Position), (Option<OpAssignment>, Position))>,
@ -1790,7 +1787,7 @@ impl Engine {
_ => unreachable!("index or dot chain expected, but gets {:?}", expr),
};
let idx_values = &mut StaticVec::new_const();
let idx_values = &mut FnArgsVec::new_const();
self.eval_dot_index_chain_arguments(
scope, mods, state, lib, this_ptr, rhs, term, chain_type, idx_values, 0, level,
@ -1846,7 +1843,7 @@ impl Engine {
expr: &Expr,
terminate_chaining: bool,
parent_chain_type: ChainType,
idx_values: &mut StaticVec<ChainArgument>,
idx_values: &mut FnArgsVec<ChainArgument>,
size: usize,
level: usize,
) -> RhaiResultOf<()> {
@ -1863,7 +1860,7 @@ impl Engine {
} = x.as_ref();
let (values, pos) = args.iter().try_fold(
(StaticVec::with_capacity(args.len()), Position::NONE),
(FnArgsVec::with_capacity(args.len()), Position::NONE),
|(mut values, mut pos), expr| -> RhaiResultOf<_> {
let (value, arg_pos) = self.get_arg_value(
scope, mods, state, lib, this_ptr, level, expr, constants,
@ -1910,7 +1907,7 @@ impl Engine {
args.iter()
.try_fold(
(StaticVec::with_capacity(args.len()), Position::NONE),
(FnArgsVec::with_capacity(args.len()), Position::NONE),
|(mut values, mut pos), expr| -> RhaiResultOf<_> {
let (value, arg_pos) = self.get_arg_value(
scope, mods, state, lib, this_ptr, level, expr, constants,

View File

@ -12,8 +12,8 @@ use crate::engine::{
use crate::module::Namespace;
use crate::tokenizer::Token;
use crate::{
calc_fn_hash, calc_fn_params_hash, combine_hashes, Dynamic, Engine, FnPtr, Identifier,
ImmutableString, Module, Position, RhaiResult, RhaiResultOf, Scope, StaticVec, ERR,
calc_fn_hash, calc_fn_params_hash, combine_hashes, Dynamic, Engine, FnArgsVec, FnPtr,
Identifier, ImmutableString, Module, Position, RhaiResult, RhaiResultOf, Scope, ERR,
};
#[cfg(feature = "no_std")]
use std::prelude::v1::*;
@ -149,7 +149,7 @@ impl Engine {
} else {
self.map_type_name(a.type_name())
})
.collect::<StaticVec<_>>()
.collect::<FnArgsVec<_>>()
.join(", ")
)
}
@ -727,7 +727,7 @@ impl Engine {
fn_name: impl AsRef<str>,
mut hash: FnCallHashes,
target: &mut crate::engine::Target,
(call_args, call_arg_pos): &mut (StaticVec<Dynamic>, Position),
(call_args, call_arg_pos): &mut (FnArgsVec<Dynamic>, Position),
pos: Position,
level: usize,
) -> RhaiResultOf<(Dynamic, bool)> {
@ -744,9 +744,9 @@ impl Engine {
// Recalculate hashes
let new_hash = calc_fn_hash(fn_name, args_len).into();
// Arguments are passed as-is, adding the curried arguments
let mut curry = StaticVec::with_capacity(fn_ptr.num_curried());
let mut curry = FnArgsVec::with_capacity(fn_ptr.num_curried());
curry.extend(fn_ptr.curry().iter().cloned());
let mut args = StaticVec::with_capacity(curry.len() + call_args.len());
let mut args = FnArgsVec::with_capacity(curry.len() + call_args.len());
args.extend(curry.iter_mut());
args.extend(call_args.iter_mut());
@ -782,9 +782,9 @@ impl Engine {
calc_fn_hash(fn_name, args_len + 1),
);
// Replace the first argument with the object pointer, adding the curried arguments
let mut curry = StaticVec::with_capacity(fn_ptr.num_curried());
let mut curry = FnArgsVec::with_capacity(fn_ptr.num_curried());
curry.extend(fn_ptr.curry().iter().cloned());
let mut args = StaticVec::with_capacity(curry.len() + call_args.len() + 1);
let mut args = FnArgsVec::with_capacity(curry.len() + call_args.len() + 1);
args.push(target.as_mut());
args.extend(curry.iter_mut());
args.extend(call_args.iter_mut());
@ -858,7 +858,7 @@ impl Engine {
};
// Attached object pointer in front of the arguments
let mut args = StaticVec::with_capacity(call_args.len() + 1);
let mut args = FnArgsVec::with_capacity(call_args.len() + 1);
args.push(target.as_mut());
args.extend(call_args.iter_mut());
@ -918,7 +918,7 @@ impl Engine {
let fn_name = fn_name.as_ref();
let mut a_expr = args_expr;
let mut total_args = a_expr.len();
let mut curry = StaticVec::new_const();
let mut curry = FnArgsVec::new_const();
let mut name = fn_name;
let mut hashes = hashes;
let redirected; // Handle call() - Redirect function call
@ -1086,8 +1086,8 @@ impl Engine {
}
// Normal function call - except for Fn, curry, call and eval (handled above)
let mut arg_values = StaticVec::with_capacity(a_expr.len());
let mut args = StaticVec::with_capacity(a_expr.len() + curry.len());
let mut arg_values = FnArgsVec::with_capacity(a_expr.len());
let mut args = FnArgsVec::with_capacity(a_expr.len() + curry.len());
let mut is_ref_mut = false;
// Capture parent scope?
@ -1187,8 +1187,8 @@ impl Engine {
level: usize,
) -> RhaiResult {
let fn_name = fn_name.as_ref();
let mut arg_values = StaticVec::with_capacity(args_expr.len());
let mut args = StaticVec::with_capacity(args_expr.len());
let mut arg_values = FnArgsVec::with_capacity(args_expr.len());
let mut args = FnArgsVec::with_capacity(args_expr.len());
let mut first_arg_value = None;
if args_expr.is_empty() {

View File

@ -313,6 +313,29 @@ type StaticVec<T> = smallvec::SmallVec<[T; 3]>;
#[cfg(feature = "internals")]
pub type StaticVec<T> = smallvec::SmallVec<[T; 3]>;
/// Inline arguments storage for function calls.
///
/// # Notes
///
/// Since most usage of this is during a function call to gather up arguments, this is mostly
/// allocated on the stack, so we can tolerate a larger number of values stored inline.
///
/// Most functions have few parameters, but closures with a lot of captured variables can
/// potentially have many. Having a larger inline storage for arguments reduces allocations in
/// scripts with heavy closure usage.
///
/// Under `no_closure`, this type aliases to [`StaticVec`][crate::StaticVec] instead.
#[cfg(not(feature = "no_closure"))]
type FnArgsVec<T> = smallvec::SmallVec<[T; 8]>;
/// Inline arguments storage for function calls.
///
/// # Notes
///
/// This type aliases to [`StaticVec`][crate::StaticVec] under `no_closure`.
#[cfg(feature = "no_closure")]
type FnArgsVec<T> = crate::StaticVec<T>;
pub(crate) type SmartString = smartstring::SmartString<smartstring::LazyCompact>;
// Compiler guards against mutually-exclusive feature flags