Shrink arrays and use boxed slices.

This commit is contained in:
Stephen Chung 2021-05-05 18:38:52 +08:00
parent 13c620de4b
commit 2c0215ea3f
4 changed files with 63 additions and 31 deletions

View File

@ -14,6 +14,7 @@ use std::{
fmt, fmt,
hash::Hash, hash::Hash,
iter::empty, iter::empty,
mem,
num::{NonZeroU8, NonZeroUsize}, num::{NonZeroU8, NonZeroUsize},
ops::{Add, AddAssign, Deref, DerefMut}, ops::{Add, AddAssign, Deref, DerefMut},
}; };
@ -203,9 +204,10 @@ impl AST {
statements: impl IntoIterator<Item = Stmt>, statements: impl IntoIterator<Item = Stmt>,
functions: impl Into<Shared<Module>>, functions: impl Into<Shared<Module>>,
) -> Self { ) -> Self {
let statements: StaticVec<_> = statements.into_iter().collect();
Self { Self {
source: None, source: None,
body: StmtBlock(statements.into_iter().collect(), Position::NONE), body: StmtBlock::new(statements, Position::NONE),
functions: functions.into(), functions: functions.into(),
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
resolver: None, resolver: None,
@ -218,9 +220,10 @@ impl AST {
functions: impl Into<Shared<Module>>, functions: impl Into<Shared<Module>>,
source: impl Into<Identifier>, source: impl Into<Identifier>,
) -> Self { ) -> Self {
let statements: StaticVec<_> = statements.into_iter().collect();
Self { Self {
source: Some(source.into()), source: Some(source.into()),
body: StmtBlock(statements.into_iter().collect(), Position::NONE), body: StmtBlock::new(statements, Position::NONE),
functions: functions.into(), functions: functions.into(),
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
resolver: None, resolver: None,
@ -852,7 +855,9 @@ pub struct StmtBlock(StaticVec<Stmt>, Position);
impl StmtBlock { impl StmtBlock {
/// Create a new [`StmtBlock`]. /// Create a new [`StmtBlock`].
pub fn new(statements: impl Into<StaticVec<Stmt>>, pos: Position) -> Self { pub fn new(statements: impl Into<StaticVec<Stmt>>, pos: Position) -> Self {
Self(statements.into(), pos) let mut statements = statements.into();
statements.shrink_to_fit();
Self(statements, pos)
} }
/// Is this statements block empty? /// Is this statements block empty?
#[inline(always)] #[inline(always)]
@ -899,7 +904,7 @@ impl fmt::Debug for StmtBlock {
impl From<StmtBlock> for Stmt { impl From<StmtBlock> for Stmt {
fn from(block: StmtBlock) -> Self { fn from(block: StmtBlock) -> Self {
let block_pos = block.position(); let block_pos = block.position();
Self::Block(block.0.into_vec(), block_pos) Self::Block(block.0.into_boxed_slice(), block_pos)
} }
} }
@ -939,7 +944,7 @@ pub enum Stmt {
/// function call forming one statement. /// function call forming one statement.
FnCall(Box<FnCallExpr>, Position), FnCall(Box<FnCallExpr>, Position),
/// `{` stmt`;` ... `}` /// `{` stmt`;` ... `}`
Block(Vec<Stmt>, Position), Block(Box<[Stmt]>, Position),
/// `try` `{` stmt; ... `}` `catch` `(` var `)` `{` stmt; ... `}` /// `try` `{` stmt; ... `}` `catch` `(` var `)` `{` stmt; ... `}`
TryCatch( TryCatch(
Box<(StmtBlock, Option<Ident>, StmtBlock)>, Box<(StmtBlock, Option<Ident>, StmtBlock)>,
@ -959,7 +964,7 @@ pub enum Stmt {
Import(Expr, Option<Box<Ident>>, Position), Import(Expr, Option<Box<Ident>>, Position),
/// `export` var `as` var `,` ... /// `export` var `as` var `,` ...
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
Export(Vec<(Ident, Option<Ident>)>, Position), Export(Box<[(Ident, Option<Ident>)]>, Position),
/// Convert a variable to shared. /// Convert a variable to shared.
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
Share(Identifier), Share(Identifier),
@ -976,7 +981,9 @@ impl From<Stmt> for StmtBlock {
#[inline(always)] #[inline(always)]
fn from(stmt: Stmt) -> Self { fn from(stmt: Stmt) -> Self {
match stmt { match stmt {
Stmt::Block(block, pos) => Self(block.into(), pos), Stmt::Block(mut block, pos) => {
Self(block.iter_mut().map(|v| mem::take(v)).collect(), pos)
}
Stmt::Noop(pos) => Self(Default::default(), pos), Stmt::Noop(pos) => Self(Default::default(), pos),
_ => { _ => {
let pos = stmt.position(); let pos = stmt.position();
@ -1282,7 +1289,7 @@ impl Stmt {
} }
} }
Self::Block(x, _) => { Self::Block(x, _) => {
for s in x { for s in x.iter() {
if !s.walk(path, on_node) { if !s.walk(path, on_node) {
return false; return false;
} }
@ -1330,10 +1337,10 @@ impl Stmt {
pub struct CustomExpr { pub struct CustomExpr {
/// List of keywords. /// List of keywords.
pub keywords: StaticVec<Expr>, pub keywords: StaticVec<Expr>,
/// List of tokens actually parsed.
pub tokens: Vec<Identifier>,
/// Delta number of variables in the scope. /// Delta number of variables in the scope.
pub scope_delta: isize, pub scope_delta: isize,
/// List of tokens actually parsed.
pub tokens: StaticVec<Identifier>,
} }
/// _(INTERNALS)_ A binary expression. /// _(INTERNALS)_ A binary expression.

View File

@ -695,19 +695,22 @@ impl Module {
) -> u64 { ) -> u64 {
let is_method = func.is_method(); let is_method = func.is_method();
let param_types: StaticVec<_> = arg_types let mut param_types: StaticVec<_> = arg_types
.iter() .iter()
.cloned() .cloned()
.enumerate() .enumerate()
.map(|(i, type_id)| Self::map_type(!is_method || i > 0, type_id)) .map(|(i, type_id)| Self::map_type(!is_method || i > 0, type_id))
.collect(); .collect();
param_types.shrink_to_fit();
#[cfg(feature = "metadata")] #[cfg(feature = "metadata")]
let param_names = _arg_names let mut param_names: StaticVec<_> = _arg_names
.iter() .iter()
.flat_map(|p| p.iter()) .flat_map(|p| p.iter())
.map(|&arg| self.identifiers.get(arg)) .map(|&arg| self.identifiers.get(arg))
.collect(); .collect();
#[cfg(feature = "metadata")]
param_names.shrink_to_fit();
let hash_fn = calc_native_fn_hash(empty(), &name, &param_types); let hash_fn = calc_native_fn_hash(empty(), &name, &param_types);
@ -1692,6 +1695,8 @@ impl DerefMut for NamespaceRef {
impl From<StaticVec<Ident>> for NamespaceRef { impl From<StaticVec<Ident>> for NamespaceRef {
#[inline(always)] #[inline(always)]
fn from(path: StaticVec<Ident>) -> Self { fn from(path: StaticVec<Ident>) -> Self {
let mut path = path;
path.shrink_to_fit();
Self { index: None, path } Self { index: None, path }
} }
} }

View File

@ -417,7 +417,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut State, preserve_result: bool) {
*stmt = if preserve_result { *stmt = if preserve_result {
// -> { expr, Noop } // -> { expr, Noop }
Stmt::Block(vec![Stmt::Expr(expr), Stmt::Noop(pos)], pos) Stmt::Block(Box::new([Stmt::Expr(expr), Stmt::Noop(pos)]), pos)
} else { } else {
// -> expr // -> expr
Stmt::Expr(expr) Stmt::Expr(expr)
@ -434,7 +434,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut State, preserve_result: bool) {
let else_block = mem::take(&mut *x.1).into_vec(); let else_block = mem::take(&mut *x.1).into_vec();
*stmt = match optimize_stmt_block(else_block, state, preserve_result, true, false) { *stmt = match optimize_stmt_block(else_block, state, preserve_result, true, false) {
statements if statements.is_empty() => Stmt::Noop(x.1.position()), statements if statements.is_empty() => Stmt::Noop(x.1.position()),
statements => Stmt::Block(statements, x.1.position()), statements => Stmt::Block(statements.into_boxed_slice(), x.1.position()),
} }
} }
// if true { if_block } else { else_block } -> if_block // if true { if_block } else { else_block } -> if_block
@ -443,7 +443,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut State, preserve_result: bool) {
let if_block = mem::take(&mut *x.0).into_vec(); let if_block = mem::take(&mut *x.0).into_vec();
*stmt = match optimize_stmt_block(if_block, state, preserve_result, true, false) { *stmt = match optimize_stmt_block(if_block, state, preserve_result, true, false) {
statements if statements.is_empty() => Stmt::Noop(x.0.position()), statements if statements.is_empty() => Stmt::Noop(x.0.position()),
statements => Stmt::Block(statements, x.0.position()), statements => Stmt::Block(statements.into_boxed_slice(), x.0.position()),
} }
} }
// if expr { if_block } else { else_block } // if expr { if_block } else { else_block }
@ -484,7 +484,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut State, preserve_result: bool) {
condition, condition,
Box::new(( Box::new((
mem::take(&mut block.1), mem::take(&mut block.1),
Stmt::Block(def_stmt, def_pos).into(), Stmt::Block(def_stmt.into_boxed_slice(), def_pos).into(),
)), )),
match_expr.position(), match_expr.position(),
); );
@ -494,7 +494,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut State, preserve_result: bool) {
let statements = mem::take(&mut *block.1); let statements = mem::take(&mut *block.1);
let statements = let statements =
optimize_stmt_block(statements.into_vec(), state, true, true, false); optimize_stmt_block(statements.into_vec(), state, true, true, false);
*stmt = Stmt::Block(statements, new_pos); *stmt = Stmt::Block(statements.into_boxed_slice(), new_pos);
} }
} else { } else {
// Promote the default case // Promote the default case
@ -505,7 +505,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut State, preserve_result: bool) {
} else { } else {
x.1.position() x.1.position()
}; };
*stmt = Stmt::Block(def_stmt, def_pos); *stmt = Stmt::Block(def_stmt.into_boxed_slice(), def_pos);
} }
} }
// switch // switch
@ -572,7 +572,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut State, preserve_result: bool) {
if preserve_result { if preserve_result {
statements.push(Stmt::Noop(pos)) statements.push(Stmt::Noop(pos))
} }
*stmt = Stmt::Block(statements, pos); *stmt = Stmt::Block(statements.into_boxed_slice(), pos);
} else { } else {
*stmt = Stmt::Noop(pos); *stmt = Stmt::Noop(pos);
}; };
@ -588,7 +588,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut State, preserve_result: bool) {
let block_pos = body.position(); let block_pos = body.position();
let block = mem::take(body.statements()).into_vec(); let block = mem::take(body.statements()).into_vec();
*stmt = Stmt::Block( *stmt = Stmt::Block(
optimize_stmt_block(block, state, false, true, false), optimize_stmt_block(block, state, false, true, false).into_boxed_slice(),
block_pos, block_pos,
); );
} }
@ -611,8 +611,8 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut State, preserve_result: bool) {
Stmt::Import(expr, _, _) => optimize_expr(expr, state), Stmt::Import(expr, _, _) => optimize_expr(expr, state),
// { block } // { block }
Stmt::Block(statements, pos) => { Stmt::Block(statements, pos) => {
let mut block = let statements = mem::take(statements).into_vec();
optimize_stmt_block(mem::take(statements), state, preserve_result, true, false); let mut block = optimize_stmt_block(statements, state, preserve_result, true, false);
match block.as_mut_slice() { match block.as_mut_slice() {
[] => { [] => {
@ -624,7 +624,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut State, preserve_result: bool) {
state.set_dirty(); state.set_dirty();
*stmt = mem::take(s); *stmt = mem::take(s);
} }
_ => *stmt = Stmt::Block(block, *pos), _ => *stmt = Stmt::Block(block.into_boxed_slice(), *pos),
} }
} }
// try { pure try_block } catch ( var ) { catch_block } -> try_block // try { pure try_block } catch ( var ) { catch_block } -> try_block
@ -634,7 +634,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut State, preserve_result: bool) {
let try_pos = x.0.position(); let try_pos = x.0.position();
let try_block = mem::take(&mut *x.0).into_vec(); let try_block = mem::take(&mut *x.0).into_vec();
*stmt = Stmt::Block( *stmt = Stmt::Block(
optimize_stmt_block(try_block, state, false, true, false), optimize_stmt_block(try_block, state, false, true, false).into_boxed_slice(),
try_pos, try_pos,
); );
} }
@ -820,6 +820,8 @@ fn optimize_expr(expr: &mut Expr, state: &mut State) {
} }
} }
} }
x.shrink_to_fit();
} }
// [ constant .. ] // [ constant .. ]
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
@ -947,6 +949,7 @@ fn optimize_expr(expr: &mut Expr, state: &mut State) {
} }
x.args.shrink_to_fit(); x.args.shrink_to_fit();
x.constant_args.shrink_to_fit();
} }
// Eagerly call functions // Eagerly call functions
@ -1006,6 +1009,7 @@ fn optimize_expr(expr: &mut Expr, state: &mut State) {
} }
x.args.shrink_to_fit(); x.args.shrink_to_fit();
x.constant_args.shrink_to_fit();
} }
// constant-name // constant-name

View File

@ -348,6 +348,8 @@ fn parse_fn_call(
FnCallHashes::from_native(hash) FnCallHashes::from_native(hash)
}; };
args.shrink_to_fit();
return Ok(Expr::FnCall( return Ok(Expr::FnCall(
Box::new(FnCallExpr { Box::new(FnCallExpr {
name: state.get_identifier(id), name: state.get_identifier(id),
@ -393,6 +395,8 @@ fn parse_fn_call(
FnCallHashes::from_native(hash) FnCallHashes::from_native(hash)
}; };
args.shrink_to_fit();
return Ok(Expr::FnCall( return Ok(Expr::FnCall(
Box::new(FnCallExpr { Box::new(FnCallExpr {
name: state.get_identifier(id), name: state.get_identifier(id),
@ -1066,6 +1070,7 @@ fn parse_primary(
} }
} }
segments.shrink_to_fit();
Expr::InterpolatedString(Box::new(segments)) Expr::InterpolatedString(Box::new(segments))
} }
@ -1344,6 +1349,7 @@ fn parse_unary(
expr => { expr => {
let mut args = StaticVec::new(); let mut args = StaticVec::new();
args.push(expr); args.push(expr);
args.shrink_to_fit();
Ok(Expr::FnCall( Ok(Expr::FnCall(
Box::new(FnCallExpr { Box::new(FnCallExpr {
@ -1370,6 +1376,7 @@ fn parse_unary(
expr => { expr => {
let mut args = StaticVec::new(); let mut args = StaticVec::new();
args.push(expr); args.push(expr);
args.shrink_to_fit();
Ok(Expr::FnCall( Ok(Expr::FnCall(
Box::new(FnCallExpr { Box::new(FnCallExpr {
@ -1387,8 +1394,8 @@ fn parse_unary(
Token::Bang => { Token::Bang => {
let pos = eat_token(input, Token::Bang); let pos = eat_token(input, Token::Bang);
let mut args = StaticVec::new(); let mut args = StaticVec::new();
let expr = parse_unary(input, state, lib, settings.level_up())?; args.push(parse_unary(input, state, lib, settings.level_up())?);
args.push(expr); args.shrink_to_fit();
Ok(Expr::FnCall( Ok(Expr::FnCall(
Box::new(FnCallExpr { Box::new(FnCallExpr {
@ -1730,6 +1737,7 @@ fn parse_binary_op(
let mut args = StaticVec::new(); let mut args = StaticVec::new();
args.push(root); args.push(root);
args.push(rhs); args.push(rhs);
args.shrink_to_fit();
root = match op_token { root = match op_token {
Token::Plus Token::Plus
@ -1782,6 +1790,7 @@ fn parse_binary_op(
// Swap the arguments // Swap the arguments
let current_lhs = args.remove(0); let current_lhs = args.remove(0);
args.push(current_lhs); args.push(current_lhs);
args.shrink_to_fit();
// Convert into a call to `contains` // Convert into a call to `contains`
let hash = calc_fn_hash(empty(), OP_CONTAINS, 2); let hash = calc_fn_hash(empty(), OP_CONTAINS, 2);
@ -1836,7 +1845,7 @@ fn parse_custom_syntax(
) -> Result<Expr, ParseError> { ) -> Result<Expr, ParseError> {
let mut keywords: StaticVec<Expr> = Default::default(); let mut keywords: StaticVec<Expr> = Default::default();
let mut segments: StaticVec<_> = Default::default(); let mut segments: StaticVec<_> = Default::default();
let mut tokens: Vec<_> = Default::default(); let mut tokens: StaticVec<_> = Default::default();
// Adjust the variables stack // Adjust the variables stack
match syntax.scope_delta { match syntax.scope_delta {
@ -1920,6 +1929,9 @@ fn parse_custom_syntax(
} }
} }
keywords.shrink_to_fit();
tokens.shrink_to_fit();
Ok(Expr::Custom( Ok(Expr::Custom(
Box::new(CustomExpr { Box::new(CustomExpr {
keywords, keywords,
@ -2366,7 +2378,7 @@ fn parse_export(
} }
} }
Ok(Stmt::Export(exports, settings.pos)) Ok(Stmt::Export(exports.into_boxed_slice(), settings.pos))
} }
/// Parse a statement block. /// Parse a statement block.
@ -2467,7 +2479,7 @@ fn parse_block(
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
state.modules.truncate(prev_mods_len); state.modules.truncate(prev_mods_len);
Ok(Stmt::Block(statements, settings.pos)) Ok(Stmt::Block(statements.into_boxed_slice(), settings.pos))
} }
/// Parse an expression as a statement. /// Parse an expression as a statement.
@ -2820,7 +2832,8 @@ fn parse_fn(
} }
.into(); .into();
let params: StaticVec<_> = params.into_iter().map(|(p, _)| p).collect(); let mut params: StaticVec<_> = params.into_iter().map(|(p, _)| p).collect();
params.shrink_to_fit();
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
let externals = state let externals = state
@ -2874,6 +2887,8 @@ fn make_curry_from_externals(
)); ));
}); });
args.shrink_to_fit();
let expr = Expr::FnCall( let expr = Expr::FnCall(
Box::new(FnCallExpr { Box::new(FnCallExpr {
name: state.get_identifier(crate::engine::KEYWORD_FN_PTR_CURRY), name: state.get_identifier(crate::engine::KEYWORD_FN_PTR_CURRY),
@ -2967,7 +2982,7 @@ fn parse_anon_fn(
Default::default() Default::default()
}; };
let params: StaticVec<_> = if cfg!(not(feature = "no_closure")) { let mut params: StaticVec<_> = if cfg!(not(feature = "no_closure")) {
externals externals
.iter() .iter()
.cloned() .cloned()
@ -2976,6 +2991,7 @@ fn parse_anon_fn(
} else { } else {
params.into_iter().map(|(v, _)| v).collect() params.into_iter().map(|(v, _)| v).collect()
}; };
params.shrink_to_fit();
// Create unique function name by hashing the script body plus the parameters. // Create unique function name by hashing the script body plus the parameters.
let hasher = &mut get_hasher(); let hasher = &mut get_hasher();