Expand function call arguments inline storage.
This commit is contained in:
parent
05d4c81e7a
commit
dfb3378b28
@ -2,19 +2,16 @@
|
|||||||
|
|
||||||
use crate::ast::{Expr, FnCallExpr, Ident, OpAssignment, Stmt, AST_OPTION_FLAGS::*};
|
use crate::ast::{Expr, FnCallExpr, Ident, OpAssignment, Stmt, AST_OPTION_FLAGS::*};
|
||||||
use crate::custom_syntax::CustomSyntax;
|
use crate::custom_syntax::CustomSyntax;
|
||||||
use crate::func::{
|
use crate::func::native::{OnDebugCallback, OnParseTokenCallback, OnPrintCallback, OnVarCallback};
|
||||||
get_hasher,
|
use crate::func::{get_hasher, CallableFunction, IteratorFn};
|
||||||
native::{OnDebugCallback, OnParseTokenCallback, OnPrintCallback, OnVarCallback},
|
|
||||||
CallableFunction, IteratorFn,
|
|
||||||
};
|
|
||||||
use crate::module::Namespace;
|
use crate::module::Namespace;
|
||||||
use crate::packages::{Package, StandardPackage};
|
use crate::packages::{Package, StandardPackage};
|
||||||
use crate::r#unsafe::unsafe_cast_var_name_to_lifetime;
|
use crate::r#unsafe::unsafe_cast_var_name_to_lifetime;
|
||||||
use crate::tokenizer::Token;
|
use crate::tokenizer::Token;
|
||||||
use crate::types::dynamic::{map_std_type_name, AccessMode, Union, Variant};
|
use crate::types::dynamic::{map_std_type_name, AccessMode, Union, Variant};
|
||||||
use crate::{
|
use crate::{
|
||||||
calc_fn_params_hash, combine_hashes, Dynamic, Identifier, ImmutableString, Module, Position,
|
calc_fn_params_hash, combine_hashes, Dynamic, FnArgsVec, Identifier, ImmutableString, Module,
|
||||||
RhaiError, RhaiResult, RhaiResultOf, Scope, Shared, StaticVec, ERR, INT,
|
Position, RhaiError, RhaiResult, RhaiResultOf, Scope, Shared, StaticVec, ERR, INT,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
@ -372,7 +369,7 @@ enum ChainArgument {
|
|||||||
/// Arguments to a dot method call.
|
/// Arguments to a dot method call.
|
||||||
/// Wrapped values are the arguments plus the [position][Position] of the first argument.
|
/// Wrapped values are the arguments plus the [position][Position] of the first argument.
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
MethodCallArgs(StaticVec<Dynamic>, Position),
|
MethodCallArgs(FnArgsVec<Dynamic>, Position),
|
||||||
/// Index value and [position][Position].
|
/// Index value and [position][Position].
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
IndexValue(Dynamic, Position),
|
IndexValue(Dynamic, Position),
|
||||||
@ -395,7 +392,7 @@ impl ChainArgument {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
#[must_use]
|
#[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 {
|
match self {
|
||||||
Self::MethodCallArgs(values, pos) => Some((values, pos)),
|
Self::MethodCallArgs(values, pos) => Some((values, pos)),
|
||||||
_ => None,
|
_ => None,
|
||||||
@ -418,9 +415,9 @@ impl ChainArgument {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
impl From<(StaticVec<Dynamic>, Position)> for ChainArgument {
|
impl From<(FnArgsVec<Dynamic>, Position)> for ChainArgument {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from((values, pos): (StaticVec<Dynamic>, Position)) -> Self {
|
fn from((values, pos): (FnArgsVec<Dynamic>, Position)) -> Self {
|
||||||
Self::MethodCallArgs(values, pos)
|
Self::MethodCallArgs(values, pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1325,7 +1322,7 @@ impl Engine {
|
|||||||
root: (&str, Position),
|
root: (&str, Position),
|
||||||
rhs: &Expr,
|
rhs: &Expr,
|
||||||
terminate_chaining: bool,
|
terminate_chaining: bool,
|
||||||
idx_values: &mut StaticVec<ChainArgument>,
|
idx_values: &mut FnArgsVec<ChainArgument>,
|
||||||
chain_type: ChainType,
|
chain_type: ChainType,
|
||||||
level: usize,
|
level: usize,
|
||||||
new_val: Option<((Dynamic, Position), (Option<OpAssignment>, Position))>,
|
new_val: Option<((Dynamic, Position), (Option<OpAssignment>, Position))>,
|
||||||
@ -1790,7 +1787,7 @@ impl Engine {
|
|||||||
_ => unreachable!("index or dot chain expected, but gets {:?}", expr),
|
_ => 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(
|
self.eval_dot_index_chain_arguments(
|
||||||
scope, mods, state, lib, this_ptr, rhs, term, chain_type, idx_values, 0, level,
|
scope, mods, state, lib, this_ptr, rhs, term, chain_type, idx_values, 0, level,
|
||||||
@ -1846,7 +1843,7 @@ impl Engine {
|
|||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
terminate_chaining: bool,
|
terminate_chaining: bool,
|
||||||
parent_chain_type: ChainType,
|
parent_chain_type: ChainType,
|
||||||
idx_values: &mut StaticVec<ChainArgument>,
|
idx_values: &mut FnArgsVec<ChainArgument>,
|
||||||
size: usize,
|
size: usize,
|
||||||
level: usize,
|
level: usize,
|
||||||
) -> RhaiResultOf<()> {
|
) -> RhaiResultOf<()> {
|
||||||
@ -1863,7 +1860,7 @@ impl Engine {
|
|||||||
} = x.as_ref();
|
} = x.as_ref();
|
||||||
|
|
||||||
let (values, pos) = args.iter().try_fold(
|
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<_> {
|
|(mut values, mut pos), expr| -> RhaiResultOf<_> {
|
||||||
let (value, arg_pos) = self.get_arg_value(
|
let (value, arg_pos) = self.get_arg_value(
|
||||||
scope, mods, state, lib, this_ptr, level, expr, constants,
|
scope, mods, state, lib, this_ptr, level, expr, constants,
|
||||||
@ -1910,7 +1907,7 @@ impl Engine {
|
|||||||
|
|
||||||
args.iter()
|
args.iter()
|
||||||
.try_fold(
|
.try_fold(
|
||||||
(StaticVec::with_capacity(args.len()), Position::NONE),
|
(FnArgsVec::with_capacity(args.len()), Position::NONE),
|
||||||
|(mut values, mut pos), expr| -> RhaiResultOf<_> {
|
|(mut values, mut pos), expr| -> RhaiResultOf<_> {
|
||||||
let (value, arg_pos) = self.get_arg_value(
|
let (value, arg_pos) = self.get_arg_value(
|
||||||
scope, mods, state, lib, this_ptr, level, expr, constants,
|
scope, mods, state, lib, this_ptr, level, expr, constants,
|
||||||
|
@ -12,8 +12,8 @@ use crate::engine::{
|
|||||||
use crate::module::Namespace;
|
use crate::module::Namespace;
|
||||||
use crate::tokenizer::Token;
|
use crate::tokenizer::Token;
|
||||||
use crate::{
|
use crate::{
|
||||||
calc_fn_hash, calc_fn_params_hash, combine_hashes, Dynamic, Engine, FnPtr, Identifier,
|
calc_fn_hash, calc_fn_params_hash, combine_hashes, Dynamic, Engine, FnArgsVec, FnPtr,
|
||||||
ImmutableString, Module, Position, RhaiResult, RhaiResultOf, Scope, StaticVec, ERR,
|
Identifier, ImmutableString, Module, Position, RhaiResult, RhaiResultOf, Scope, ERR,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
@ -149,7 +149,7 @@ impl Engine {
|
|||||||
} else {
|
} else {
|
||||||
self.map_type_name(a.type_name())
|
self.map_type_name(a.type_name())
|
||||||
})
|
})
|
||||||
.collect::<StaticVec<_>>()
|
.collect::<FnArgsVec<_>>()
|
||||||
.join(", ")
|
.join(", ")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -727,7 +727,7 @@ impl Engine {
|
|||||||
fn_name: impl AsRef<str>,
|
fn_name: impl AsRef<str>,
|
||||||
mut hash: FnCallHashes,
|
mut hash: FnCallHashes,
|
||||||
target: &mut crate::engine::Target,
|
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,
|
pos: Position,
|
||||||
level: usize,
|
level: usize,
|
||||||
) -> RhaiResultOf<(Dynamic, bool)> {
|
) -> RhaiResultOf<(Dynamic, bool)> {
|
||||||
@ -744,9 +744,9 @@ impl Engine {
|
|||||||
// Recalculate hashes
|
// Recalculate hashes
|
||||||
let new_hash = calc_fn_hash(fn_name, args_len).into();
|
let new_hash = calc_fn_hash(fn_name, args_len).into();
|
||||||
// Arguments are passed as-is, adding the curried arguments
|
// 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());
|
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(curry.iter_mut());
|
||||||
args.extend(call_args.iter_mut());
|
args.extend(call_args.iter_mut());
|
||||||
|
|
||||||
@ -782,9 +782,9 @@ impl Engine {
|
|||||||
calc_fn_hash(fn_name, args_len + 1),
|
calc_fn_hash(fn_name, args_len + 1),
|
||||||
);
|
);
|
||||||
// Replace the first argument with the object pointer, adding the curried arguments
|
// 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());
|
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.push(target.as_mut());
|
||||||
args.extend(curry.iter_mut());
|
args.extend(curry.iter_mut());
|
||||||
args.extend(call_args.iter_mut());
|
args.extend(call_args.iter_mut());
|
||||||
@ -858,7 +858,7 @@ impl Engine {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Attached object pointer in front of the arguments
|
// 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.push(target.as_mut());
|
||||||
args.extend(call_args.iter_mut());
|
args.extend(call_args.iter_mut());
|
||||||
|
|
||||||
@ -918,7 +918,7 @@ impl Engine {
|
|||||||
let fn_name = fn_name.as_ref();
|
let fn_name = fn_name.as_ref();
|
||||||
let mut a_expr = args_expr;
|
let mut a_expr = args_expr;
|
||||||
let mut total_args = a_expr.len();
|
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 name = fn_name;
|
||||||
let mut hashes = hashes;
|
let mut hashes = hashes;
|
||||||
let redirected; // Handle call() - Redirect function call
|
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)
|
// Normal function call - except for Fn, curry, call and eval (handled above)
|
||||||
let mut arg_values = StaticVec::with_capacity(a_expr.len());
|
let mut arg_values = FnArgsVec::with_capacity(a_expr.len());
|
||||||
let mut args = StaticVec::with_capacity(a_expr.len() + curry.len());
|
let mut args = FnArgsVec::with_capacity(a_expr.len() + curry.len());
|
||||||
let mut is_ref_mut = false;
|
let mut is_ref_mut = false;
|
||||||
|
|
||||||
// Capture parent scope?
|
// Capture parent scope?
|
||||||
@ -1187,8 +1187,8 @@ impl Engine {
|
|||||||
level: usize,
|
level: usize,
|
||||||
) -> RhaiResult {
|
) -> RhaiResult {
|
||||||
let fn_name = fn_name.as_ref();
|
let fn_name = fn_name.as_ref();
|
||||||
let mut arg_values = StaticVec::with_capacity(args_expr.len());
|
let mut arg_values = FnArgsVec::with_capacity(args_expr.len());
|
||||||
let mut args = StaticVec::with_capacity(args_expr.len());
|
let mut args = FnArgsVec::with_capacity(args_expr.len());
|
||||||
let mut first_arg_value = None;
|
let mut first_arg_value = None;
|
||||||
|
|
||||||
if args_expr.is_empty() {
|
if args_expr.is_empty() {
|
||||||
|
23
src/lib.rs
23
src/lib.rs
@ -313,6 +313,29 @@ type StaticVec<T> = smallvec::SmallVec<[T; 3]>;
|
|||||||
#[cfg(feature = "internals")]
|
#[cfg(feature = "internals")]
|
||||||
pub type StaticVec<T> = smallvec::SmallVec<[T; 3]>;
|
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>;
|
pub(crate) type SmartString = smartstring::SmartString<smartstring::LazyCompact>;
|
||||||
|
|
||||||
// Compiler guards against mutually-exclusive feature flags
|
// Compiler guards against mutually-exclusive feature flags
|
||||||
|
Loading…
x
Reference in New Issue
Block a user