From be88d103ba3a678459f65e4aebc3399b4b738fa4 Mon Sep 17 00:00:00 2001 From: Peter Ammon Date: Sun, 16 Mar 2025 13:45:48 -0700 Subject: [PATCH] ast: Use boxed slice instead of vec for list nodes This saves a decent amount of memory, both because we no longer have excess capacity sitting around that we'll never use, but also because we no longer need to store the "capacity" value. --- src/ast.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ast.rs b/src/ast.rs index 643bea9ca..f98a796d4 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -439,7 +439,7 @@ fn allows_keyword(&self, kw: ParseKeyword) -> bool { pub trait List: Node { type ContentsNode: Node + Default; fn contents(&self) -> &[Box]; - fn contents_mut(&mut self) -> &mut Vec>; + fn contents_mut(&mut self) -> &mut Box<[Box]>; /// Return our count. fn count(&self) -> usize { self.contents().len() @@ -636,7 +636,8 @@ macro_rules! define_list_node { #[derive(Default, Debug)] pub struct $name { parent: Option<*const dyn Node>, - list_contents: Vec>, + // Note we box the nodes themselves, for pointer stability. + list_contents: Box<[Box<$contents>]>, } implement_node!($name, list, $type); impl List for $name { @@ -644,7 +645,7 @@ impl List for $name { fn contents(&self) -> &[Box] { &self.list_contents } - fn contents_mut(&mut self) -> &mut Vec> { + fn contents_mut(&mut self) -> &mut Box<[Box]> { &mut self.list_contents } } @@ -3547,7 +3548,6 @@ fn populate_list(&mut self, list: &mut ListType, exhaust_stream: } // We're going to populate a vector with our nodes. - // Later on we will copy this to the heap with a single allocation. let mut contents = vec![]; loop { @@ -3614,7 +3614,7 @@ fn populate_list(&mut self, list: &mut ListType, exhaust_stream: "Contents size out of bounds" ); assert!(list.contents().is_empty(), "List should still be empty"); - *list.contents_mut() = contents; + *list.contents_mut() = contents.into_boxed_slice(); } FLOGF!(