perf: Use FxHasher over default hash implementation

This commit is contained in:
Will Lillis 2026-03-01 15:39:08 -05:00
parent b9f40095d7
commit f50c7d9e64
15 changed files with 95 additions and 86 deletions

View file

@ -6,12 +6,13 @@ mod item_set_builder;
mod minimize_parse_table;
mod token_conflicts;
use std::collections::{BTreeSet, HashMap};
use std::collections::BTreeSet;
pub use build_lex_table::LARGE_CHARACTER_RANGE_COUNT;
use build_parse_table::BuildTableResult;
pub use build_parse_table::ParseTableBuilderError;
use log::{debug, info};
use rustc_hash::FxHashMap;
use self::{
build_lex_table::build_lex_table,
@ -284,7 +285,7 @@ fn populate_used_symbols(
}
fn populate_external_lex_states(parse_table: &mut ParseTable, syntax_grammar: &SyntaxGrammar) {
let mut external_tokens_by_corresponding_internal_token = HashMap::new();
let mut external_tokens_by_corresponding_internal_token = FxHashMap::default();
for (i, external_token) in syntax_grammar.external_tokens.iter().enumerate() {
if let Some(symbol) = external_token.corresponding_internal_token {
external_tokens_by_corresponding_internal_token.insert(symbol.index, i);

View file

@ -1,8 +1,10 @@
use std::{
collections::{HashMap, VecDeque, hash_map::Entry},
collections::{VecDeque, hash_map::Entry},
mem,
};
use rustc_hash::FxHashMap;
use log::debug;
use super::{coincident_tokens::CoincidentTokenIndex, token_conflicts::TokenConflictMap};
@ -139,7 +141,7 @@ struct LexTableBuilder<'a> {
cursor: NfaCursor<'a>,
table: LexTable,
state_queue: VecDeque<QueueEntry>,
state_ids_by_nfa_state_set: HashMap<(Vec<u32>, bool), usize>,
state_ids_by_nfa_state_set: FxHashMap<(Vec<u32>, bool), usize>,
}
impl<'a> LexTableBuilder<'a> {
@ -149,7 +151,7 @@ impl<'a> LexTableBuilder<'a> {
cursor: NfaCursor::new(&lexical_grammar.nfa, vec![]),
table: LexTable::default(),
state_queue: VecDeque::new(),
state_ids_by_nfa_state_set: HashMap::new(),
state_ids_by_nfa_state_set: FxHashMap::default(),
}
}
@ -345,7 +347,7 @@ fn merge_token_set(
fn minimize_lex_table(table: &mut LexTable, parse_table: &mut ParseTable) {
// Initially group the states by their accept action and their
// valid lookahead characters.
let mut state_ids_by_signature = HashMap::new();
let mut state_ids_by_signature = FxHashMap::default();
for (i, state) in table.states.iter().enumerate() {
let signature = (
i == 0,

View file

@ -1,12 +1,12 @@
use std::{
cmp::Ordering,
collections::{BTreeMap, BTreeSet, HashMap, HashSet, VecDeque},
collections::{BTreeMap, BTreeSet, VecDeque},
hash::BuildHasherDefault,
};
use indexmap::{IndexMap, map::Entry};
use log::warn;
use rustc_hash::FxHasher;
use rustc_hash::{FxHashMap, FxHashSet, FxHasher};
use serde::Serialize;
use thiserror::Error;
@ -56,12 +56,12 @@ struct ParseTableBuilder<'a> {
syntax_grammar: &'a SyntaxGrammar,
lexical_grammar: &'a LexicalGrammar,
variable_info: &'a [VariableInfo],
core_ids_by_core: HashMap<ParseItemSetCore<'a>, usize>,
core_ids_by_core: FxHashMap<ParseItemSetCore<'a>, usize>,
state_ids_by_item_set: IndexMap<ParseItemSet<'a>, ParseStateId, BuildHasherDefault<FxHasher>>,
parse_state_info_by_id: Vec<ParseStateInfo<'a>>,
parse_state_queue: VecDeque<ParseStateQueueEntry>,
non_terminal_extra_states: Vec<(Symbol, usize)>,
actual_conflicts: HashSet<Vec<Symbol>>,
actual_conflicts: FxHashSet<Vec<Symbol>>,
parse_table: ParseTable,
}
@ -252,7 +252,7 @@ impl<'a> ParseTableBuilder<'a> {
variable_info,
non_terminal_extra_states: Vec::new(),
state_ids_by_item_set: IndexMap::default(),
core_ids_by_core: HashMap::new(),
core_ids_by_core: FxHashMap::default(),
parse_state_info_by_id: Vec::new(),
parse_state_queue: VecDeque::new(),
actual_conflicts: syntax_grammar.expected_conflicts.iter().cloned().collect(),
@ -417,7 +417,7 @@ impl<'a> ParseTableBuilder<'a> {
let mut terminal_successors = BTreeMap::new();
let mut non_terminal_successors = BTreeMap::new();
let mut lookaheads_with_conflicts = TokenSet::new();
let mut reduction_infos = HashMap::<Symbol, ReductionInfo>::new();
let mut reduction_infos = FxHashMap::<Symbol, ReductionInfo>::default();
// Each item in the item set contributes to either or a Shift action or a Reduce
// action in this state.
@ -616,7 +616,7 @@ impl<'a> ParseTableBuilder<'a> {
None
}
})
.collect::<HashSet<_>>();
.collect::<FxHashSet<_>>();
let parent_symbol_names = parent_symbols
.iter()
.map(|&variable_index| {

View file

@ -1,7 +1,6 @@
use std::{
collections::{HashMap, HashSet},
fmt,
};
use std::fmt;
use rustc_hash::{FxHashMap, FxHashSet};
use super::item::{ParseItem, ParseItemDisplay, ParseItemSet, ParseItemSetEntry, TokenSetDisplay};
use crate::{
@ -25,9 +24,9 @@ struct FollowSetInfo {
pub struct ParseItemSetBuilder<'a> {
syntax_grammar: &'a SyntaxGrammar,
lexical_grammar: &'a LexicalGrammar,
first_sets: HashMap<Symbol, TokenSet>,
reserved_first_sets: HashMap<Symbol, ReservedWordSetId>,
last_sets: HashMap<Symbol, TokenSet>,
first_sets: FxHashMap<Symbol, TokenSet>,
reserved_first_sets: FxHashMap<Symbol, ReservedWordSetId>,
last_sets: FxHashMap<Symbol, TokenSet>,
inlines: &'a InlinedProductionMap,
transitive_closure_additions: Vec<Vec<TransitiveClosureAddition<'a>>>,
}
@ -47,9 +46,9 @@ impl<'a> ParseItemSetBuilder<'a> {
let mut result = Self {
syntax_grammar,
lexical_grammar,
first_sets: HashMap::new(),
reserved_first_sets: HashMap::new(),
last_sets: HashMap::new(),
first_sets: FxHashMap::default(),
reserved_first_sets: FxHashMap::default(),
last_sets: FxHashMap::default(),
inlines,
transitive_closure_additions: vec![Vec::new(); syntax_grammar.variables.len()],
};
@ -92,7 +91,7 @@ impl<'a> ParseItemSetBuilder<'a> {
// Rather than computing these sets using recursion, we use an explicit stack
// called `symbols_to_process`.
let mut symbols_to_process = Vec::new();
let mut processed_non_terminals = HashSet::new();
let mut processed_non_terminals = FxHashSet::default();
for i in 0..syntax_grammar.variables.len() {
let symbol = Symbol::non_terminal(i);
let first_set = result.first_sets.entry(symbol).or_default();
@ -162,7 +161,7 @@ impl<'a> ParseItemSetBuilder<'a> {
// Rather than computing these additions recursively, we use an explicit stack.
let empty_lookaheads = TokenSet::new();
let mut stack = Vec::new();
let mut follow_set_info_by_non_terminal = HashMap::<usize, FollowSetInfo>::new();
let mut follow_set_info_by_non_terminal = FxHashMap::<usize, FollowSetInfo>::default();
for i in 0..syntax_grammar.variables.len() {
// First, build up a map whose keys are all of the non-terminals that can
// appear at the beginning of non-terminal `i`, and whose values store

View file

@ -1,8 +1,6 @@
use std::{
cmp::Ordering,
collections::{HashMap, HashSet},
mem,
};
use std::{cmp::Ordering, mem};
use rustc_hash::{FxHashMap, FxHashSet};
use log::debug;
@ -111,7 +109,7 @@ struct Minimizer<'a> {
impl Minimizer<'_> {
fn remove_unit_reductions(&mut self) {
let mut aliased_symbols = HashSet::new();
let mut aliased_symbols = FxHashSet::default();
for variable in &self.syntax_grammar.variables {
for production in &variable.productions {
for step in &production.steps {
@ -122,7 +120,7 @@ impl Minimizer<'_> {
}
}
let mut unit_reduction_symbols_by_state = HashMap::new();
let mut unit_reduction_symbols_by_state = FxHashMap::default();
for (i, state) in self.parse_table.states.iter().enumerate() {
let mut only_unit_reductions = true;
let mut unit_reduction_symbol = None;

View file

@ -1,4 +1,6 @@
use std::{cmp::Ordering, collections::HashSet, fmt};
use std::{cmp::Ordering, fmt};
use rustc_hash::FxHashSet;
use bitflags::bitflags;
@ -267,7 +269,7 @@ fn compute_conflict_status(
i: usize,
j: usize,
) -> (TokenConflictStatus, TokenConflictStatus) {
let mut visited_state_sets = HashSet::new();
let mut visited_state_sets = FxHashSet::default();
let mut state_set_queue = vec![vec![
grammar.variables[i].start_state,
grammar.variables[j].start_state,

View file

@ -1,4 +1,6 @@
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::collections::{BTreeMap, BTreeSet};
use rustc_hash::{FxHashMap, FxHashSet};
use serde::Serialize;
use thiserror::Error;
@ -22,7 +24,7 @@ pub struct FieldInfo {
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct VariableInfo {
pub fields: HashMap<String, FieldInfo>,
pub fields: FxHashMap<String, FieldInfo>,
pub children: FieldInfo,
pub children_without_fields: FieldInfo,
pub has_multi_step_production: bool,
@ -195,7 +197,7 @@ pub fn get_variable_info(
// immediately combined across all productions, but the child quantities must be
// recorded separately for each production.
for production in &variable.productions {
let mut production_field_quantities = HashMap::new();
let mut production_field_quantities = FxHashMap::default();
let mut production_children_quantity = ChildQuantity::zero();
let mut production_children_without_fields_quantity = ChildQuantity::zero();
let mut production_has_uninitialized_invisible_children = false;
@ -379,8 +381,8 @@ pub fn get_variable_info(
fn get_aliases_by_symbol(
syntax_grammar: &SyntaxGrammar,
default_aliases: &AliasMap,
) -> HashMap<Symbol, BTreeSet<Option<Alias>>> {
let mut aliases_by_symbol = HashMap::new();
) -> FxHashMap<Symbol, BTreeSet<Option<Alias>>> {
let mut aliases_by_symbol = FxHashMap::default();
for (symbol, alias) in default_aliases {
aliases_by_symbol.insert(*symbol, {
let mut aliases = BTreeSet::new();
@ -426,7 +428,7 @@ pub fn get_supertype_symbol_map(
let aliases_by_symbol = get_aliases_by_symbol(syntax_grammar, default_aliases);
let mut supertype_symbol_map = BTreeMap::new();
let mut symbols_by_alias = HashMap::new();
let mut symbols_by_alias = FxHashMap::default();
for (symbol, aliases) in &aliases_by_symbol {
for alias in aliases.iter().flatten() {
symbols_by_alias
@ -555,7 +557,7 @@ pub fn generate_node_types_json(
)
})
})
.collect::<HashSet<_>>();
.collect::<FxHashSet<_>>();
let mut subtype_map = Vec::new();
for (i, info) in variable_info.iter().enumerate() {
@ -1833,7 +1835,7 @@ mod tests {
}
)]
.into_iter()
.collect::<HashMap<_, _>>()
.collect::<FxHashMap<_, _>>()
);
assert_eq!(
@ -1853,7 +1855,7 @@ mod tests {
}
)]
.into_iter()
.collect::<HashMap<_, _>>()
.collect::<FxHashMap<_, _>>()
);
}
@ -1920,7 +1922,7 @@ mod tests {
}
)]
.into_iter()
.collect::<HashMap<_, _>>()
.collect::<FxHashMap<_, _>>()
);
}
@ -1981,7 +1983,7 @@ mod tests {
}
)]
.into_iter()
.collect::<HashMap<_, _>>()
.collect::<FxHashMap<_, _>>()
);
assert_eq!(
@ -2055,7 +2057,7 @@ mod tests {
}
)]
.into_iter()
.collect::<HashMap<_, _>>()
.collect::<FxHashMap<_, _>>()
);
}

View file

@ -1,4 +1,4 @@
use std::collections::HashSet;
use rustc_hash::FxHashSet;
use log::warn;
use regex::Regex;
@ -160,7 +160,7 @@ fn variable_is_used(
extras: &[Rule],
externals: &[Rule],
target_name: &str,
in_progress: &mut HashSet<String>,
in_progress: &mut FxHashSet<String>,
) -> bool {
let root = &grammar_rules.first().unwrap().0;
if target_name == root {
@ -241,7 +241,7 @@ pub(crate) fn parse_grammar(input: &str) -> ParseGrammarResult<InputGrammar> {
.map(|(n, r)| Ok((n, parse_rule(serde_json::from_value(r)?, false)?)))
.collect::<ParseGrammarResult<Vec<_>>>()?;
let mut in_progress = HashSet::new();
let mut in_progress = FxHashSet::default();
for (name, rule) in &rules {
if grammar_json.word.as_ref().is_none_or(|w| w != name)

View file

@ -8,7 +8,7 @@ mod process_inlines;
use std::{
cmp::Ordering,
collections::{BTreeSet, HashMap, HashSet, hash_map},
collections::{BTreeSet, hash_map},
mem,
};
@ -16,6 +16,7 @@ pub use expand_tokens::ExpandTokensError;
pub use extract_tokens::ExtractTokensError;
pub use flatten_grammar::FlattenGrammarError;
use indexmap::IndexMap;
use rustc_hash::{FxHashMap, FxHashSet};
pub use intern_symbols::InternSymbolsError;
pub use process_inlines::ProcessInlinesError;
use serde::Serialize;
@ -256,7 +257,7 @@ fn validate_precedences(grammar: &InputGrammar) -> ValidatePrecedenceResult<()>
fn validate(
rule_name: &str,
rule: &Rule,
names: &HashSet<&String>,
names: &FxHashSet<&String>,
) -> ValidatePrecedenceResult<()> {
match rule {
Rule::Repeat(rule) => validate(rule_name, rule, names),
@ -281,7 +282,7 @@ fn validate_precedences(grammar: &InputGrammar) -> ValidatePrecedenceResult<()>
// For any two precedence names `a` and `b`, if `a` comes before `b`
// in some list, then it cannot come *after* `b` in any list.
let mut pairs = HashMap::new();
let mut pairs = FxHashMap::default();
for list in &grammar.precedence_orderings {
for (i, mut entry1) in list.iter().enumerate() {
for mut entry2 in list.iter().skip(i + 1) {
@ -321,7 +322,7 @@ fn validate_precedences(grammar: &InputGrammar) -> ValidatePrecedenceResult<()>
None
}
})
.collect::<HashSet<&String>>();
.collect::<FxHashSet<&String>>();
for variable in &grammar.variables {
validate(&variable.name, &variable.rule, &precedence_names)?;
}

View file

@ -1,4 +1,6 @@
use std::{collections::HashMap, mem};
use std::mem;
use rustc_hash::FxHashMap;
use super::ExtractedSyntaxGrammar;
use crate::{
@ -11,7 +13,7 @@ struct Expander {
repeat_count_in_variable: usize,
preceding_symbol_count: usize,
auxiliary_variables: Vec<Variable>,
existing_repeats: HashMap<Rule, Symbol>,
existing_repeats: FxHashMap<Rule, Symbol>,
}
impl Expander {
@ -106,7 +108,7 @@ pub(super) fn expand_repeats(mut grammar: ExtractedSyntaxGrammar) -> ExtractedSy
repeat_count_in_variable: 0,
preceding_symbol_count: grammar.variables.len(),
auxiliary_variables: Vec::new(),
existing_repeats: HashMap::new(),
existing_repeats: FxHashMap::default(),
};
for (i, variable) in grammar.variables.iter_mut().enumerate() {

View file

@ -1,4 +1,4 @@
use std::collections::HashMap;
use rustc_hash::FxHashMap;
use serde::Serialize;
use thiserror::Error;
@ -89,7 +89,7 @@ pub(super) fn extract_tokens(
// will need to have their indices decremented.
let mut variables = Vec::with_capacity(grammar.variables.len());
let mut symbol_replacer = SymbolReplacer {
replacements: HashMap::new(),
replacements: FxHashMap::default(),
};
for (i, variable) in grammar.variables.into_iter().enumerate() {
if let Rule::Symbol(Symbol {
@ -268,7 +268,7 @@ struct TokenExtractor {
}
struct SymbolReplacer {
replacements: HashMap<usize, usize>,
replacements: FxHashMap<usize, usize>,
}
impl TokenExtractor {

View file

@ -1,4 +1,4 @@
use std::collections::HashMap;
use rustc_hash::FxHashMap;
use serde::Serialize;
use thiserror::Error;
@ -31,7 +31,7 @@ unless they are used only as the grammar's start rule.
struct RuleFlattener {
production: Production,
reserved_word_set_ids: HashMap<String, ReservedWordSetId>,
reserved_word_set_ids: FxHashMap<String, ReservedWordSetId>,
precedence_stack: Vec<Precedence>,
associativity_stack: Vec<Associativity>,
reserved_word_stack: Vec<ReservedWordSetId>,
@ -40,7 +40,7 @@ struct RuleFlattener {
}
impl RuleFlattener {
const fn new(reserved_word_set_ids: HashMap<String, ReservedWordSetId>) -> Self {
const fn new(reserved_word_set_ids: FxHashMap<String, ReservedWordSetId>) -> Self {
Self {
production: Production {
steps: Vec::new(),
@ -248,7 +248,7 @@ fn symbol_is_used(variables: &[SyntaxVariable], symbol: Symbol) -> bool {
pub(super) fn flatten_grammar(
grammar: ExtractedSyntaxGrammar,
) -> FlattenGrammarResult<SyntaxGrammar> {
let mut reserved_word_set_ids_by_name = HashMap::new();
let mut reserved_word_set_ids_by_name = FxHashMap::default();
for (ix, set) in grammar.reserved_word_sets.iter().enumerate() {
reserved_word_set_ids_by_name.insert(set.name.clone(), ReservedWordSetId(ix));
}
@ -307,7 +307,7 @@ mod tests {
#[test]
fn test_flatten_grammar() {
let mut flattener = RuleFlattener::new(HashMap::default());
let mut flattener = RuleFlattener::new(FxHashMap::default());
let result = flattener
.flatten_variable(Variable {
name: "test".to_string(),
@ -368,7 +368,7 @@ mod tests {
#[test]
fn test_flatten_grammar_with_maximum_dynamic_precedence() {
let mut flattener = RuleFlattener::new(HashMap::default());
let mut flattener = RuleFlattener::new(FxHashMap::default());
let result = flattener
.flatten_variable(Variable {
name: "test".to_string(),
@ -424,7 +424,7 @@ mod tests {
#[test]
fn test_flatten_grammar_with_final_precedence() {
let mut flattener = RuleFlattener::new(HashMap::default());
let mut flattener = RuleFlattener::new(FxHashMap::default());
let result = flattener
.flatten_variable(Variable {
name: "test".to_string(),
@ -474,7 +474,7 @@ mod tests {
#[test]
fn test_flatten_grammar_with_field_names() {
let mut flattener = RuleFlattener::new(HashMap::default());
let mut flattener = RuleFlattener::new(FxHashMap::default());
let result = flattener
.flatten_variable(Variable {
name: "test".to_string(),

View file

@ -1,4 +1,4 @@
use std::collections::HashMap;
use rustc_hash::FxHashMap;
use serde::Serialize;
use thiserror::Error;
@ -19,7 +19,7 @@ struct ProductionStepId {
}
struct InlinedProductionMapBuilder {
production_indices_by_step_id: HashMap<ProductionStepId, Vec<usize>>,
production_indices_by_step_id: FxHashMap<ProductionStepId, Vec<usize>>,
productions: Vec<Production>,
}
@ -227,7 +227,7 @@ pub(super) fn process_inlines(
Ok(InlinedProductionMapBuilder {
productions: Vec::new(),
production_indices_by_step_id: HashMap::new(),
production_indices_by_step_id: FxHashMap::default(),
}
.build(grammar))
}

View file

@ -1,5 +1,4 @@
use std::{
collections::HashMap,
path::{Path, PathBuf},
sync::{LazyLock, Mutex},
};
@ -9,6 +8,7 @@ use rquickjs::{
Context, Ctx, Function, Module, Object, Runtime, Type, Value,
loader::{FileResolver, ScriptLoader},
};
use rustc_hash::FxHashMap;
use super::{IoError, JSError, JSResult};
@ -49,8 +49,8 @@ fn format_js_exception(v: Value) -> JSError {
}
}
static FILE_CACHE: LazyLock<Mutex<HashMap<String, String>>> =
LazyLock::new(|| Mutex::new(HashMap::new()));
static FILE_CACHE: LazyLock<Mutex<FxHashMap<String, String>>> =
LazyLock::new(|| Mutex::new(FxHashMap::default()));
#[rquickjs::function]
fn load_file(path: String) -> rquickjs::Result<String> {

View file

@ -1,10 +1,12 @@
use std::{
cmp,
collections::{BTreeMap, BTreeSet, HashMap, HashSet},
collections::{BTreeMap, BTreeSet},
fmt::Write,
mem::swap,
};
use rustc_hash::{FxHashMap, FxHashSet};
use crate::LANGUAGE_VERSION;
use indoc::indoc;
use serde::Serialize;
@ -90,11 +92,11 @@ struct Generator {
syntax_grammar: SyntaxGrammar,
lexical_grammar: LexicalGrammar,
default_aliases: AliasMap,
symbol_order: HashMap<Symbol, usize>,
symbol_ids: HashMap<Symbol, String>,
alias_ids: HashMap<Alias, String>,
symbol_order: FxHashMap<Symbol, usize>,
symbol_ids: FxHashMap<Symbol, String>,
alias_ids: FxHashMap<Alias, String>,
unique_aliases: Vec<Alias>,
symbol_map: HashMap<Symbol, Symbol>,
symbol_map: FxHashMap<Symbol, Symbol>,
reserved_word_sets: Vec<TokenSet>,
reserved_word_set_ids_by_parse_state: Vec<usize>,
field_names: Vec<String>,
@ -187,7 +189,7 @@ impl Generator {
}
fn init(&mut self) {
let mut symbol_identifiers = HashSet::new();
let mut symbol_identifiers = FxHashSet::default();
for i in 0..self.parse_table.symbols.len() {
self.assign_symbol_id(self.parse_table.symbols[i], &mut symbol_identifiers);
}
@ -196,7 +198,7 @@ impl Generator {
self.symbol_ids[&Symbol::end()].clone(),
);
self.symbol_map = HashMap::new();
self.symbol_map = FxHashMap::default();
for symbol in &self.parse_table.symbols {
let mut mapping = symbol;
@ -610,7 +612,7 @@ impl Generator {
}
fn add_non_terminal_alias_map(&mut self) {
let mut alias_ids_by_symbol = HashMap::new();
let mut alias_ids_by_symbol = FxHashMap::default();
for variable in &self.syntax_grammar.variables {
for production in &variable.productions {
for step in &production.steps {
@ -666,7 +668,7 @@ impl Generator {
"static const TSStateId ts_primary_state_ids[STATE_COUNT] = {{"
);
indent!(self);
let mut first_state_for_each_core_id = HashMap::new();
let mut first_state_for_each_core_id = FxHashMap::default();
for (idx, state) in self.parse_table.states.iter().enumerate() {
let primary_state = first_state_for_each_core_id
.entry(state.core_id)
@ -1287,7 +1289,7 @@ impl Generator {
}
fn add_parse_table(&mut self) -> RenderResult<()> {
let mut parse_table_entries = HashMap::new();
let mut parse_table_entries = FxHashMap::default();
let mut next_parse_action_list_index = 0;
// Parse action lists zero is for the default value, when a symbol is not valid.
@ -1368,7 +1370,7 @@ impl Generator {
.len()
.saturating_sub(self.large_state_count),
);
let mut symbols_by_value = HashMap::<(usize, SymbolType), Vec<Symbol>>::new();
let mut symbols_by_value = FxHashMap::<(usize, SymbolType), Vec<Symbol>>::default();
for state in self.parse_table.states.iter().skip(self.large_state_count) {
small_state_indices.push(next_table_index);
symbols_by_value.clear();
@ -1689,7 +1691,7 @@ impl Generator {
fn get_parse_action_list_id(
entry: &ParseTableEntry,
parse_table_entries: &mut HashMap<ParseTableEntry, usize>,
parse_table_entries: &mut FxHashMap<ParseTableEntry, usize>,
next_parse_action_list_index: &mut usize,
) -> usize {
if let Some(&index) = parse_table_entries.get(entry) {
@ -1724,7 +1726,7 @@ impl Generator {
)
}
fn assign_symbol_id(&mut self, symbol: Symbol, used_identifiers: &mut HashSet<String>) {
fn assign_symbol_id(&mut self, symbol: Symbol, used_identifiers: &mut FxHashSet<String>) {
let mut id;
if symbol == Symbol::end() {
id = "ts_builtin_sym_end".to_string();