Skip to content

Commit

Permalink
perf(semantic): use Atom instead of CompactStr for unresolved_references
Browse files Browse the repository at this point in the history
  • Loading branch information
Dunqing committed Jul 21, 2024
1 parent 468852f commit d9315ff
Showing 1 changed file with 19 additions and 11 deletions.
30 changes: 19 additions & 11 deletions crates/oxc_semantic/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ use oxc_cfg::{
IterationInstructionKind, ReturnInstructionKind,
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_span::{CompactStr, SourceType, Span};
use oxc_span::{Atom, CompactStr, SourceType, Span};
use oxc_syntax::{module_record::ModuleRecord, operator::AssignmentOperator};
use rustc_hash::FxHashMap;

use crate::{
binder::Binder,
Expand All @@ -26,7 +27,7 @@ use crate::{
module_record::ModuleRecordBuilder,
node::{AstNodeId, AstNodes, NodeFlags},
reference::{Reference, ReferenceFlag, ReferenceId},
scope::{ScopeFlags, ScopeId, ScopeTree, UnresolvedReferences},
scope::{ScopeFlags, ScopeId, ScopeTree, UnresolvedReference, UnresolvedReferences},
symbol::{SymbolFlags, SymbolId, SymbolTable},
JSDocFinder, Semantic,
};
Expand Down Expand Up @@ -77,7 +78,7 @@ pub struct SemanticBuilder<'a> {
// Indexed by scope depth. We recycle `UnresolvedReferences` instances during traversal
// to reduce allocations, so the stack grows to maximum scope depth, but never shrinks.
// See: <https://github.com/oxc-project/oxc/issues/4169>
unresolved_references: Vec<UnresolvedReferences>,
unresolved_references: Vec<FxHashMap<Atom<'a>, Vec<UnresolvedReference>>>,

pub(crate) module_record: Arc<ModuleRecord>,

Expand Down Expand Up @@ -201,8 +202,15 @@ impl<'a> SemanticBuilder<'a> {
}

debug_assert_eq!(self.current_scope_depth, 1);
self.scope.root_unresolved_references =
self.unresolved_references.into_iter().next().unwrap();

self.scope.root_unresolved_references = self
.unresolved_references
.into_iter()
.next()
.unwrap()
.into_iter()
.map(|(k, v)| (k.into(), v))
.collect::<UnresolvedReferences>();

let jsdoc = if self.build_jsdoc { self.jsdoc.build() } else { JSDocFinder::default() };

Expand Down Expand Up @@ -351,12 +359,12 @@ impl<'a> SemanticBuilder<'a> {
/// Declare an unresolved reference in the current scope.
///
/// # Panics
pub fn declare_reference(&mut self, name: &str, reference: Reference) -> ReferenceId {
pub fn declare_reference(&mut self, name: &Atom<'a>, reference: Reference) -> ReferenceId {
let reference_flag = *reference.flag();
let reference_id = self.symbols.create_reference(reference);

self.unresolved_references[self.current_scope_depth]
.entry(CompactStr::from(name))
.entry(name.clone())
.or_default()
.push((reference_id, reference_flag));
reference_id
Expand Down Expand Up @@ -389,7 +397,7 @@ impl<'a> SemanticBuilder<'a> {
// Try to resolve a reference.
// If unresolved, transfer it to parent scope's unresolved references.
let bindings = self.scope.get_bindings(self.current_scope_id);
if let Some(symbol_id) = bindings.get(&name).copied() {
if let Some(symbol_id) = bindings.get(name.as_str()).copied() {
let symbol_flag = self.symbols.get_flag(symbol_id);

let resolved_references: &mut Vec<_> =
Expand Down Expand Up @@ -484,7 +492,7 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
// `self.unresolved_references[self.current_scope_depth]` is initialized
self.current_scope_depth += 1;
if self.unresolved_references.len() <= self.current_scope_depth {
self.unresolved_references.push(UnresolvedReferences::default());
self.unresolved_references.push(FxHashMap::default());
}
}

Expand Down Expand Up @@ -1894,7 +1902,7 @@ impl<'a> SemanticBuilder<'a> {
}
}

fn reference_identifier(&mut self, ident: &IdentifierReference) {
fn reference_identifier(&mut self, ident: &IdentifierReference<'a>) {
let flag = self.resolve_reference_usages();
let reference = Reference::new(ident.span, self.current_node_id, flag);
let reference_id = self.declare_reference(&ident.name, reference);
Expand All @@ -1910,7 +1918,7 @@ impl<'a> SemanticBuilder<'a> {
}
}

fn reference_jsx_identifier(&mut self, ident: &JSXIdentifier) {
fn reference_jsx_identifier(&mut self, ident: &JSXIdentifier<'a>) {
match self.nodes.parent_kind(self.current_node_id) {
Some(AstKind::JSXElementName(_)) => {
if !ident.name.chars().next().is_some_and(char::is_uppercase) {
Expand Down

0 comments on commit d9315ff

Please sign in to comment.