diff --git a/awk/interpreter/mod.rs b/awk/interpreter/mod.rs index c563d1c0d..793a8cdb6 100644 --- a/awk/interpreter/mod.rs +++ b/awk/interpreter/mod.rs @@ -61,7 +61,7 @@ fn strtod(s: &str) -> f64 { } fn gather_values(stack: &mut Stack, count: u16) -> Result, String> { - let mut values = Vec::new(); + let mut values = Vec::with_capacity(count as usize); for _ in 0..count { values.push(stack.pop_scalar_value()?); } @@ -73,7 +73,7 @@ fn print_to_string( argc: u16, global_env: &GlobalEnv, ) -> Result { - let mut values = Vec::new(); + let mut values = Vec::with_capacity(argc as usize); for _ in 0..argc { values.push( stack diff --git a/cc/arch/x86_64/codegen.rs b/cc/arch/x86_64/codegen.rs index f426269c2..7157f03e4 100644 --- a/cc/arch/x86_64/codegen.rs +++ b/cc/arch/x86_64/codegen.rs @@ -1898,7 +1898,7 @@ impl X86_64CodeGen { // First pass: determine which args go on stack // For variadic calls: variadic INTEGER args go on stack, variadic FLOAT args use XMM // For non-variadic calls: overflow args go on stack - let mut stack_arg_indices = Vec::new(); + let mut stack_arg_indices = Vec::with_capacity(insn.src.len()); let mut temp_int_idx = 0; let mut temp_fp_idx = 0; @@ -3734,22 +3734,23 @@ impl X86_64CodeGen { // Build operand strings for asm substitution // For constraints requiring specific registers (a,b,c,d,S,D), we use those registers // and emit mov instructions to/from the actual locations. - let mut operand_regs: Vec> = Vec::new(); - let mut operand_mem: Vec> = Vec::new(); - let mut operand_names: Vec> = Vec::new(); + let operand_count = asm_data.outputs.len() + asm_data.inputs.len(); + let mut operand_regs: Vec> = Vec::with_capacity(operand_count); + let mut operand_mem: Vec> = Vec::with_capacity(operand_count); + let mut operand_names: Vec> = Vec::with_capacity(operand_count); // Track which outputs need to be moved from specific registers after asm // (output_idx, specific_reg, actual_loc) - let mut output_moves: Vec<(usize, Reg, Loc)> = Vec::new(); + let mut output_moves: Vec<(usize, Reg, Loc)> = Vec::with_capacity(asm_data.outputs.len()); // Track which inputs need to be moved to specific registers before asm // (specific_reg, actual_loc) - let mut input_moves: Vec<(Reg, Loc)> = Vec::new(); + let mut input_moves: Vec<(Reg, Loc)> = Vec::with_capacity(asm_data.inputs.len()); // Track register remaps: if an allocated reg conflicts with reserved, use temp // (original_reg, temp_reg, actual_loc for restore) - let mut remap_setup: Vec<(Reg, Reg, Loc)> = Vec::new(); - let mut remap_restore: Vec<(Reg, Reg, Loc)> = Vec::new(); + let mut remap_setup: Vec<(Reg, Reg, Loc)> = Vec::with_capacity(operand_count); + let mut remap_restore: Vec<(Reg, Reg, Loc)> = Vec::with_capacity(operand_count); // Track which pseudos have been assigned temp registers (for +r where input/output share pseudo) let mut pseudo_to_temp: std::collections::HashMap = diff --git a/cc/ir/linearize.rs b/cc/ir/linearize.rs index 7f48aae32..e9db4225b 100644 --- a/cc/ir/linearize.rs +++ b/cc/ir/linearize.rs @@ -26,6 +26,11 @@ use crate::target::Target; use crate::types::{MemberInfo, TypeId, TypeKind, TypeModifiers, TypeTable}; use std::collections::HashMap; +/// Default capacity for variable mapping HashMaps during IR linearization +const DEFAULT_VAR_MAP_CAPACITY: usize = 64; +/// Default capacity for label/static HashMaps (typically smaller) +const DEFAULT_LABEL_MAP_CAPACITY: usize = 16; + /// Information about a local variable #[derive(Clone)] struct LocalVarInfo { @@ -127,9 +132,9 @@ impl<'a> Linearizer<'a> { current_bb: None, next_pseudo: 0, next_bb: 0, - var_map: HashMap::new(), - locals: HashMap::new(), - label_map: HashMap::new(), + var_map: HashMap::with_capacity(DEFAULT_VAR_MAP_CAPACITY), + locals: HashMap::with_capacity(DEFAULT_VAR_MAP_CAPACITY), + label_map: HashMap::with_capacity(DEFAULT_LABEL_MAP_CAPACITY), break_targets: Vec::new(), continue_targets: Vec::new(), run_ssa: true, // Enable SSA conversion by default @@ -142,7 +147,7 @@ impl<'a> Linearizer<'a> { current_func_name: String::new(), static_local_counter: 0, compound_literal_counter: 0, - static_locals: HashMap::new(), + static_locals: HashMap::with_capacity(DEFAULT_LABEL_MAP_CAPACITY), current_pos: None, target, current_func_is_non_static_inline: false, @@ -833,9 +838,11 @@ impl<'a> Linearizer<'a> { // Add parameters // For struct/union parameters, we need to copy them to local storage // so member access works properly - let mut struct_params: Vec<(String, TypeId, PseudoId)> = Vec::new(); + let mut struct_params: Vec<(String, TypeId, PseudoId)> = + Vec::with_capacity(func.params.len()); // Complex parameters also need local storage for real/imag access - let mut complex_params: Vec<(String, TypeId, PseudoId)> = Vec::new(); + let mut complex_params: Vec<(String, TypeId, PseudoId)> = + Vec::with_capacity(func.params.len()); for (i, param) in func.params.iter().enumerate() { let name = param diff --git a/cc/symbol.rs b/cc/symbol.rs index 1d72fbfc8..2c533fc5b 100644 --- a/cc/symbol.rs +++ b/cc/symbol.rs @@ -14,6 +14,9 @@ use crate::strings::StringId; use crate::types::TypeId; use std::collections::HashMap; +/// Default capacity for symbol table name lookup HashMap +const DEFAULT_SYMBOL_MAP_CAPACITY: usize = 256; + // ============================================================================ // Symbol ID // ============================================================================ @@ -234,7 +237,7 @@ impl SymbolTable { scopes: Vec::new(), current_scope: 0, scope_depth: 0, - name_map: HashMap::new(), + name_map: HashMap::with_capacity(DEFAULT_SYMBOL_MAP_CAPACITY), }; // Create the global scope table.scopes.push(Scope::new(None)); diff --git a/cc/token/preprocess.rs b/cc/token/preprocess.rs index f0cd8e465..c2a5c0e4c 100644 --- a/cc/token/preprocess.rs +++ b/cc/token/preprocess.rs @@ -23,6 +23,9 @@ use crate::diag; use crate::os; use crate::target::Target; +/// Default capacity for macro HashMap (covers predefined macros + typical program macros) +const DEFAULT_MACRO_CAPACITY: usize = 32; + // ============================================================================ // Macro Definition // ============================================================================ @@ -390,7 +393,7 @@ impl<'a> Preprocessor<'a> { let mut pp = Self { target, - macros: HashMap::new(), + macros: HashMap::with_capacity(DEFAULT_MACRO_CAPACITY), cond_stack: Vec::new(), system_include_paths: Vec::new(), quote_include_paths: Vec::new(), diff --git a/sh/shell/environment.rs b/sh/shell/environment.rs index c2d1cc9fc..4cd3c7098 100644 --- a/sh/shell/environment.rs +++ b/sh/shell/environment.rs @@ -174,7 +174,7 @@ impl Environment { } pub fn exported(&self) -> impl Iterator { - let mut exported = HashMap::new(); + let mut exported = HashMap::with_capacity(self.global_scope.len()); for (name, var) in &self.global_scope { if var.export { if let Some(value) = &var.value { diff --git a/sh/shell/mod.rs b/sh/shell/mod.rs index fdb79330c..cdedcc282 100644 --- a/sh/shell/mod.rs +++ b/sh/shell/mod.rs @@ -44,6 +44,9 @@ use std::rc::Rc; use std::time::Duration; use std::{env, io}; +/// Default capacity for cached command locations HashMap +const DEFAULT_COMMAND_CACHE_CAPACITY: usize = 64; + pub mod environment; pub mod history; pub mod opened_files; @@ -1058,7 +1061,7 @@ impl Default for Shell { background_jobs: JobManager::default(), history: History::new(32767), umask: !0o022 & 0o777, - saved_command_locations: HashMap::new(), + saved_command_locations: HashMap::with_capacity(DEFAULT_COMMAND_CACHE_CAPACITY), is_subshell: false, last_pipeline_command: String::new(), terminal: Terminal::default(), diff --git a/text/cut.rs b/text/cut.rs index 24eac36c4..28ccaa4da 100644 --- a/text/cut.rs +++ b/text/cut.rs @@ -126,7 +126,7 @@ fn is_character_boundary(bytes: &[u8]) -> bool { /// A vector containing the selected bytes from the input line based on the specified ranges. /// fn cut_bytes(line: &[u8], delim: Option, ranges: &Vec<(i32, i32)>, n: bool) -> Vec { - let mut result = Vec::new(); + let mut result = Vec::with_capacity(line.len()); for (start, end) in ranges { let mut start = *start as usize; diff --git a/text/sed.rs b/text/sed.rs index bc35ce946..9d6d42dca 100644 --- a/text/sed.rs +++ b/text/sed.rs @@ -1333,7 +1333,7 @@ fn print_multiline_binary(line: &str) { /// Find first label in [`Script`] that has duplicates fn find_first_repeated_label(vec: Vec) -> Option { - let mut counts = HashMap::new(); + let mut counts = HashMap::with_capacity(vec.len()); for item in &vec { *counts.entry(item).or_insert(0) += 1; } diff --git a/tree/mv.rs b/tree/mv.rs index 1b49d32c8..7cbeb30df 100644 --- a/tree/mv.rs +++ b/tree/mv.rs @@ -302,7 +302,7 @@ fn move_files(cfg: &MvConfig, sources: &[PathBuf], target: &Path) -> Option<()> let mut created_files = HashSet::new(); // inode of source -> target path - let mut inode_map = HashMap::new(); + let mut inode_map = HashMap::with_capacity(sources.len()); // Postpone deletion when moving across filesystems because it would // otherwise error when copying dangling hard links