Speed up method calls.
This commit is contained in:
parent
f4ebaa7abf
commit
bbaad8dfcb
@ -197,15 +197,17 @@ impl Engine {
|
|||||||
name, hashes, args, ..
|
name, hashes, args, ..
|
||||||
} = x.as_ref();
|
} = x.as_ref();
|
||||||
|
|
||||||
let call_args = &mut (
|
let offset = idx_values.len() - args.len();
|
||||||
idx_values.drain(idx_values.len() - args.len()..).collect(),
|
let call_args = &mut idx_values[offset..];
|
||||||
args.get(0).map_or(Position::NONE, Expr::position),
|
let pos1 = args.get(0).map_or(Position::NONE, Expr::position);
|
||||||
);
|
|
||||||
|
|
||||||
let result = self.make_method_call(
|
let result = self.make_method_call(
|
||||||
global, caches, lib, name, *hashes, target, call_args, *pos, level,
|
global, caches, lib, name, *hashes, target, call_args, pos1, *pos,
|
||||||
|
level,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
idx_values.truncate(offset);
|
||||||
|
|
||||||
#[cfg(feature = "debugging")]
|
#[cfg(feature = "debugging")]
|
||||||
global.debugger.reset_status(reset_debugger);
|
global.debugger.reset_status(reset_debugger);
|
||||||
|
|
||||||
@ -372,16 +374,17 @@ impl Engine {
|
|||||||
name, hashes, args, ..
|
name, hashes, args, ..
|
||||||
} = x.as_ref();
|
} = x.as_ref();
|
||||||
|
|
||||||
let call_args = &mut (
|
let offset = idx_values.len() - args.len();
|
||||||
idx_values.drain(idx_values.len() - args.len()..).collect(),
|
let call_args = &mut idx_values[offset..];
|
||||||
args.get(0).map_or(Position::NONE, Expr::position),
|
let pos1 = args.get(0).map_or(Position::NONE, Expr::position);
|
||||||
);
|
|
||||||
|
|
||||||
let result = self.make_method_call(
|
let result = self.make_method_call(
|
||||||
global, caches, lib, name, *hashes, target, call_args, pos,
|
global, caches, lib, name, *hashes, target, call_args, pos1,
|
||||||
level,
|
pos, level,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
idx_values.truncate(offset);
|
||||||
|
|
||||||
#[cfg(feature = "debugging")]
|
#[cfg(feature = "debugging")]
|
||||||
global.debugger.reset_status(reset_debugger);
|
global.debugger.reset_status(reset_debugger);
|
||||||
|
|
||||||
@ -497,16 +500,17 @@ impl Engine {
|
|||||||
} = f.as_ref();
|
} = f.as_ref();
|
||||||
let rhs_chain = rhs.into();
|
let rhs_chain = rhs.into();
|
||||||
|
|
||||||
let call_args = &mut (
|
let offset = idx_values.len() - args.len();
|
||||||
idx_values.drain(idx_values.len() - args.len()..).collect(),
|
let call_args = &mut idx_values[offset..];
|
||||||
args.get(0).map_or(Position::NONE, Expr::position),
|
let pos1 = args.get(0).map_or(Position::NONE, Expr::position);
|
||||||
);
|
|
||||||
|
|
||||||
let result = self.make_method_call(
|
let result = self.make_method_call(
|
||||||
global, caches, lib, name, *hashes, target, call_args, pos,
|
global, caches, lib, name, *hashes, target, call_args, pos1,
|
||||||
level,
|
pos, level,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
idx_values.truncate(offset);
|
||||||
|
|
||||||
#[cfg(feature = "debugging")]
|
#[cfg(feature = "debugging")]
|
||||||
global.debugger.reset_status(reset_debugger);
|
global.debugger.reset_status(reset_debugger);
|
||||||
|
|
||||||
@ -570,11 +574,14 @@ impl Engine {
|
|||||||
Expr::FnCall(x, ..)
|
Expr::FnCall(x, ..)
|
||||||
if chain_type == ChainType::Dotting && x.args.iter().all(Expr::is_constant) =>
|
if chain_type == ChainType::Dotting && x.args.iter().all(Expr::is_constant) =>
|
||||||
{
|
{
|
||||||
x.args
|
idx_values.extend(x.args.iter().map(|expr| expr.get_literal_value().unwrap()))
|
||||||
.iter()
|
|
||||||
.map(|expr| expr.get_literal_value().unwrap())
|
|
||||||
.for_each(|v| idx_values.push(v))
|
|
||||||
}
|
}
|
||||||
|
// Short-circuit for indexing with literal: {expr}[1]
|
||||||
|
#[cfg(not(feature = "no_index"))]
|
||||||
|
_ if chain_type == ChainType::Indexing && rhs.is_constant() => {
|
||||||
|
idx_values.push(rhs.get_literal_value().unwrap())
|
||||||
|
}
|
||||||
|
// All other patterns - evaluate the arguments chain
|
||||||
_ => {
|
_ => {
|
||||||
self.eval_dot_index_chain_arguments(
|
self.eval_dot_index_chain_arguments(
|
||||||
scope, global, caches, lib, this_ptr, rhs, options, chain_type, idx_values, 0,
|
scope, global, caches, lib, this_ptr, rhs, options, chain_type, idx_values, 0,
|
||||||
@ -649,9 +656,11 @@ impl Engine {
|
|||||||
if _parent_chain_type == ChainType::Dotting && !x.is_qualified() =>
|
if _parent_chain_type == ChainType::Dotting && !x.is_qualified() =>
|
||||||
{
|
{
|
||||||
for arg_expr in x.args.as_ref() {
|
for arg_expr in x.args.as_ref() {
|
||||||
let (value, _) =
|
idx_values.push(
|
||||||
self.get_arg_value(scope, global, caches, lib, this_ptr, arg_expr, level)?;
|
self.get_arg_value(scope, global, caches, lib, this_ptr, arg_expr, level)?
|
||||||
idx_values.push(value.flatten());
|
.0
|
||||||
|
.flatten(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
@ -681,10 +690,13 @@ impl Engine {
|
|||||||
if _parent_chain_type == ChainType::Dotting && !x.is_qualified() =>
|
if _parent_chain_type == ChainType::Dotting && !x.is_qualified() =>
|
||||||
{
|
{
|
||||||
for arg_expr in x.args.as_ref() {
|
for arg_expr in x.args.as_ref() {
|
||||||
let (value, _) = self.get_arg_value(
|
arg_values.push(
|
||||||
|
self.get_arg_value(
|
||||||
scope, global, caches, lib, this_ptr, arg_expr, level,
|
scope, global, caches, lib, this_ptr, arg_expr, level,
|
||||||
)?;
|
)?
|
||||||
arg_values.push(value.flatten());
|
.0
|
||||||
|
.flatten(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
|
@ -315,7 +315,7 @@ impl Debugger {
|
|||||||
/// Change the current status to [`CONTINUE`][DebuggerStatus::CONTINUE] and return the previous status.
|
/// Change the current status to [`CONTINUE`][DebuggerStatus::CONTINUE] and return the previous status.
|
||||||
pub(crate) fn clear_status_if(
|
pub(crate) fn clear_status_if(
|
||||||
&mut self,
|
&mut self,
|
||||||
filter: impl Fn(&DebuggerStatus) -> bool,
|
filter: impl FnOnce(&DebuggerStatus) -> bool,
|
||||||
) -> Option<DebuggerStatus> {
|
) -> Option<DebuggerStatus> {
|
||||||
if filter(&self.status) {
|
if filter(&self.status) {
|
||||||
Some(mem::replace(&mut self.status, DebuggerStatus::CONTINUE))
|
Some(mem::replace(&mut self.status, DebuggerStatus::CONTINUE))
|
||||||
|
@ -46,7 +46,7 @@ pub fn calc_index<E>(
|
|||||||
length: usize,
|
length: usize,
|
||||||
start: crate::INT,
|
start: crate::INT,
|
||||||
negative_count_from_end: bool,
|
negative_count_from_end: bool,
|
||||||
err: impl Fn() -> Result<usize, E>,
|
err: impl FnOnce() -> Result<usize, E>,
|
||||||
) -> Result<usize, E> {
|
) -> Result<usize, E> {
|
||||||
if start < 0 {
|
if start < 0 {
|
||||||
if negative_count_from_end {
|
if negative_count_from_end {
|
||||||
|
@ -782,8 +782,9 @@ impl Engine {
|
|||||||
fn_name: &str,
|
fn_name: &str,
|
||||||
mut hash: FnCallHashes,
|
mut hash: FnCallHashes,
|
||||||
target: &mut crate::eval::Target,
|
target: &mut crate::eval::Target,
|
||||||
(call_args, call_arg_pos): &mut (FnArgsVec<Dynamic>, Position),
|
mut call_args: &mut [Dynamic],
|
||||||
pos: Position,
|
first_arg_pos: Position,
|
||||||
|
fn_call_pos: Position,
|
||||||
level: usize,
|
level: usize,
|
||||||
) -> RhaiResultOf<(Dynamic, bool)> {
|
) -> RhaiResultOf<(Dynamic, bool)> {
|
||||||
let is_ref_mut = target.is_ref();
|
let is_ref_mut = target.is_ref();
|
||||||
@ -806,7 +807,16 @@ impl Engine {
|
|||||||
|
|
||||||
// Map it to name(args) in function-call style
|
// Map it to name(args) in function-call style
|
||||||
self.exec_fn_call(
|
self.exec_fn_call(
|
||||||
None, global, caches, lib, fn_name, new_hash, &mut args, false, false, pos,
|
None,
|
||||||
|
global,
|
||||||
|
caches,
|
||||||
|
lib,
|
||||||
|
fn_name,
|
||||||
|
new_hash,
|
||||||
|
&mut args,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
fn_call_pos,
|
||||||
level,
|
level,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -814,15 +824,17 @@ impl Engine {
|
|||||||
if !call_args.is_empty() {
|
if !call_args.is_empty() {
|
||||||
if !call_args[0].is::<FnPtr>() {
|
if !call_args[0].is::<FnPtr>() {
|
||||||
let typ = self.map_type_name(call_args[0].type_name());
|
let typ = self.map_type_name(call_args[0].type_name());
|
||||||
return Err(self.make_type_mismatch_err::<FnPtr>(typ, *call_arg_pos));
|
return Err(self.make_type_mismatch_err::<FnPtr>(typ, first_arg_pos));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let typ = self.map_type_name(target.type_name());
|
let typ = self.map_type_name(target.type_name());
|
||||||
return Err(self.make_type_mismatch_err::<FnPtr>(typ, pos));
|
return Err(self.make_type_mismatch_err::<FnPtr>(typ, fn_call_pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
// FnPtr call on object
|
// FnPtr call on object
|
||||||
let fn_ptr = call_args.remove(0).cast::<FnPtr>();
|
let fn_ptr = mem::take(&mut call_args[0]).cast::<FnPtr>();
|
||||||
|
call_args = &mut call_args[1..];
|
||||||
|
|
||||||
// Redirect function name
|
// Redirect function name
|
||||||
let fn_name = fn_ptr.fn_name();
|
let fn_name = fn_ptr.fn_name();
|
||||||
let args_len = call_args.len() + fn_ptr.curry().len();
|
let args_len = call_args.len() + fn_ptr.curry().len();
|
||||||
@ -842,14 +854,23 @@ impl Engine {
|
|||||||
|
|
||||||
// Map it to name(args) in function-call style
|
// Map it to name(args) in function-call style
|
||||||
self.exec_fn_call(
|
self.exec_fn_call(
|
||||||
None, global, caches, lib, fn_name, new_hash, &mut args, is_ref_mut, true, pos,
|
None,
|
||||||
|
global,
|
||||||
|
caches,
|
||||||
|
lib,
|
||||||
|
fn_name,
|
||||||
|
new_hash,
|
||||||
|
&mut args,
|
||||||
|
is_ref_mut,
|
||||||
|
true,
|
||||||
|
fn_call_pos,
|
||||||
level,
|
level,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
KEYWORD_FN_PTR_CURRY => {
|
KEYWORD_FN_PTR_CURRY => {
|
||||||
if !target.is::<FnPtr>() {
|
if !target.is::<FnPtr>() {
|
||||||
let typ = self.map_type_name(target.type_name());
|
let typ = self.map_type_name(target.type_name());
|
||||||
return Err(self.make_type_mismatch_err::<FnPtr>(typ, pos));
|
return Err(self.make_type_mismatch_err::<FnPtr>(typ, fn_call_pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
let fn_ptr = target.read_lock::<FnPtr>().expect("`FnPtr`");
|
let fn_ptr = target.read_lock::<FnPtr>().expect("`FnPtr`");
|
||||||
@ -883,6 +904,8 @@ impl Engine {
|
|||||||
_ => {
|
_ => {
|
||||||
let mut fn_name = fn_name;
|
let mut fn_name = fn_name;
|
||||||
let _redirected;
|
let _redirected;
|
||||||
|
let mut call_args = call_args;
|
||||||
|
let mut arg_values: FnArgsVec<_>;
|
||||||
|
|
||||||
// Check if it is a map method call in OOP style
|
// Check if it is a map method call in OOP style
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
@ -894,7 +917,13 @@ impl Engine {
|
|||||||
fn_name = &_redirected;
|
fn_name = &_redirected;
|
||||||
// Add curried arguments
|
// Add curried arguments
|
||||||
if fn_ptr.is_curried() {
|
if fn_ptr.is_curried() {
|
||||||
call_args.insert_many(0, fn_ptr.curry().iter().cloned());
|
arg_values = fn_ptr
|
||||||
|
.curry()
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.chain(call_args.iter_mut().map(mem::take))
|
||||||
|
.collect();
|
||||||
|
call_args = &mut arg_values;
|
||||||
}
|
}
|
||||||
// Recalculate the hash based on the new function name and new arguments
|
// Recalculate the hash based on the new function name and new arguments
|
||||||
hash = FnCallHashes::from_all(
|
hash = FnCallHashes::from_all(
|
||||||
@ -912,7 +941,16 @@ impl Engine {
|
|||||||
args.extend(call_args.iter_mut());
|
args.extend(call_args.iter_mut());
|
||||||
|
|
||||||
self.exec_fn_call(
|
self.exec_fn_call(
|
||||||
None, global, caches, lib, fn_name, hash, &mut args, is_ref_mut, true, pos,
|
None,
|
||||||
|
global,
|
||||||
|
caches,
|
||||||
|
lib,
|
||||||
|
fn_name,
|
||||||
|
hash,
|
||||||
|
&mut args,
|
||||||
|
is_ref_mut,
|
||||||
|
true,
|
||||||
|
fn_call_pos,
|
||||||
level,
|
level,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -920,7 +958,7 @@ impl Engine {
|
|||||||
|
|
||||||
// Propagate the changed value back to the source if necessary
|
// Propagate the changed value back to the source if necessary
|
||||||
if updated {
|
if updated {
|
||||||
target.propagate_changed_value(pos)?;
|
target.propagate_changed_value(fn_call_pos)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((result, updated))
|
Ok((result, updated))
|
||||||
|
Loading…
Reference in New Issue
Block a user