Skip to content

Commit

Permalink
refactor(semantic): allocate data in Allocator
Browse files Browse the repository at this point in the history
  • Loading branch information
Boshen committed Dec 19, 2024
1 parent 0a38eea commit b86d84c
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 60 deletions.
4 changes: 1 addition & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 2 additions & 5 deletions crates/oxc_semantic/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,7 @@ indexmap = { workspace = true }
itertools = { workspace = true }
phf = { workspace = true, features = ["macros"] }
rustc-hash = { workspace = true }

serde = { workspace = true, features = ["derive"], optional = true }
tsify = { workspace = true, optional = true }
wasm-bindgen = { workspace = true, optional = true }
self_cell = { workspace = true }

[dev-dependencies]
oxc_parser = { workspace = true }
Expand All @@ -50,4 +47,4 @@ serde_json = { workspace = true }

[features]
default = []
serialize = ["dep:serde", "dep:tsify", "dep:wasm-bindgen", "oxc_span/serialize", "oxc_syntax/serialize"]
serialize = ["oxc_span/serialize", "oxc_syntax/serialize"]
2 changes: 1 addition & 1 deletion crates/oxc_semantic/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -524,7 +524,7 @@ impl<'a> SemanticBuilder<'a> {
*flags = ReferenceFlags::Type;
}
reference.set_symbol_id(symbol_id);
self.symbols.resolved_references[symbol_id].push(reference_id);
self.symbols.add_resolved_reference(symbol_id, reference_id);

false
});
Expand Down
7 changes: 0 additions & 7 deletions crates/oxc_semantic/src/reference.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
#[cfg(feature = "serialize")]
use serde::Serialize;
#[cfg(feature = "serialize")]
use tsify::Tsify;

use oxc_syntax::{node::NodeId, reference::ReferenceFlags, symbol::SymbolId};

/// Describes where and how a Symbol is used in the AST.
Expand All @@ -26,8 +21,6 @@ use oxc_syntax::{node::NodeId, reference::ReferenceFlags, symbol::SymbolId};
///
/// [`IdentifierReference`]: oxc_ast::ast::IdentifierReference
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
#[cfg_attr(feature = "serialize", serde(rename_all = "camelCase"))]
pub struct Reference {
/// The AST node making the reference.
node_id: NodeId,
Expand Down
103 changes: 67 additions & 36 deletions crates/oxc_semantic/src/symbol.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
use std::mem;

#[cfg(feature = "serialize")]
use serde::Serialize;
#[cfg(feature = "serialize")]
use tsify::Tsify;

use oxc_allocator::{Allocator, Vec as ArenaVec};
use oxc_ast::ast::{Expression, IdentifierReference};
use oxc_index::IndexVec;
use oxc_index::{Idx, IndexVec};
use oxc_span::{CompactStr, Span};
use oxc_syntax::{
node::NodeId,
Expand All @@ -17,35 +13,57 @@ use oxc_syntax::{

use crate::reference::Reference;

#[cfg(feature = "serialize")]
#[wasm_bindgen::prelude::wasm_bindgen(typescript_custom_section)]
const TS_APPEND_CONTENT: &'static str = r#"
export type IndexVec<I, T> = Array<T>;
export type CompactStr = string;
"#;

/// Symbol Table
///
/// `SoA` (Struct of Arrays) for memory efficiency.
///
/// Most symbols won't have redeclarations, so instead of storing `Vec<Span>` directly in
/// `redeclare_variables` (32 bytes per symbol), store `Option<RedeclarationId>` (4 bytes).
/// That ID indexes into `redeclarations` where the actual `Vec<Span>` is stored.
#[derive(Debug, Default)]
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify), serde(rename_all = "camelCase"))]
pub struct SymbolTable {
pub(crate) spans: IndexVec<SymbolId, Span>,
pub(crate) names: IndexVec<SymbolId, CompactStr>,
pub(crate) flags: IndexVec<SymbolId, SymbolFlags>,
pub(crate) scope_ids: IndexVec<SymbolId, ScopeId>,
/// Pointer to the AST Node where this symbol is declared
pub(crate) declarations: IndexVec<SymbolId, NodeId>,
pub resolved_references: IndexVec<SymbolId, Vec<ReferenceId>>,
redeclarations: IndexVec<SymbolId, Option<RedeclarationId>>,

redeclaration_spans: IndexVec<RedeclarationId, Vec<Span>>,

pub references: IndexVec<ReferenceId, Reference>,

inner: SymbolTableCell,
}

impl Default for SymbolTable {
fn default() -> Self {
let allocator = Allocator::default();
Self {
spans: IndexVec::new(),
names: IndexVec::new(),
flags: IndexVec::new(),
scope_ids: IndexVec::new(),
declarations: IndexVec::new(),
redeclarations: IndexVec::new(),
references: IndexVec::new(),
inner: SymbolTableCell::new(allocator, |allocator| SymbolTableInner {
resolved_references: ArenaVec::new_in(allocator),
redeclaration_spans: ArenaVec::new_in(allocator),
}),
}
}
}

self_cell::self_cell!(
struct SymbolTableCell {
owner: Allocator,
#[covariant]
dependent: SymbolTableInner,
}
);

struct SymbolTableInner<'a> {
resolved_references: ArenaVec<'a, ArenaVec<'a, ReferenceId>>,
redeclaration_spans: ArenaVec<'a, ArenaVec<'a, Span>>,
}

impl SymbolTable {
Expand All @@ -65,8 +83,8 @@ impl SymbolTable {
self.names.iter()
}

pub fn resolved_references(&self) -> impl Iterator<Item = &Vec<ReferenceId>> + '_ {
self.resolved_references.iter()
pub fn resolved_references(&self) -> impl Iterator<Item = &ArenaVec<'_, ReferenceId>> + '_ {
self.inner.borrow_dependent().resolved_references.iter()
}

/// Iterate over all symbol IDs in this table.
Expand Down Expand Up @@ -134,7 +152,7 @@ impl SymbolTable {
#[inline]
pub fn get_redeclarations(&self, symbol_id: SymbolId) -> &[Span] {
if let Some(redeclaration_id) = self.redeclarations[symbol_id] {
&self.redeclaration_spans[redeclaration_id]
&self.inner.borrow_dependent().redeclaration_spans[redeclaration_id.index()]
} else {
static EMPTY: &[Span] = &[];
EMPTY
Expand Down Expand Up @@ -184,16 +202,26 @@ impl SymbolTable {
self.flags.push(flags);
self.scope_ids.push(scope_id);
self.declarations.push(node_id);
self.resolved_references.push(vec![]);
self.inner.with_dependent_mut(|allocator, inner| {
inner.resolved_references.push(ArenaVec::new_in(allocator));
});
self.redeclarations.push(None)
}

pub fn add_redeclaration(&mut self, symbol_id: SymbolId, span: Span) {
if let Some(redeclaration_id) = self.redeclarations[symbol_id] {
self.redeclaration_spans[redeclaration_id].push(span);
self.inner.with_dependent_mut(|_, inner| {
inner.redeclaration_spans[redeclaration_id.index()].push(span);
});
} else {
let redeclaration_id = self.redeclaration_spans.push(vec![span]);
self.redeclarations[symbol_id] = Some(redeclaration_id);
self.inner.with_dependent_mut(|allocator, inner| {
let mut v = ArenaVec::new_in(allocator);
v.push(span);
inner.redeclaration_spans.push(v);
let redeclaration_id = inner.redeclaration_spans.len();
self.redeclarations[symbol_id] =
Some(RedeclarationId::from_usize(redeclaration_id));
});
};
}

Expand Down Expand Up @@ -228,16 +256,16 @@ impl SymbolTable {
/// If you want direct access to a symbol's [`Reference`]s, use
/// [`SymbolTable::get_resolved_references`].
#[inline]
pub fn get_resolved_reference_ids(&self, symbol_id: SymbolId) -> &Vec<ReferenceId> {
&self.resolved_references[symbol_id]
pub fn get_resolved_reference_ids(&self, symbol_id: SymbolId) -> &ArenaVec<'_, ReferenceId> {
&self.inner.borrow_dependent().resolved_references[symbol_id.index()]
}

/// Find [`Reference`]s resolved to a symbol.
pub fn get_resolved_references(
&self,
symbol_id: SymbolId,
) -> impl DoubleEndedIterator<Item = &Reference> + '_ {
self.resolved_references[symbol_id]
self.get_resolved_reference_ids(symbol_id)
.iter()
.map(|&reference_id| &self.references[reference_id])
}
Expand All @@ -256,18 +284,21 @@ impl SymbolTable {

/// Add a reference to a symbol.
pub fn add_resolved_reference(&mut self, symbol_id: SymbolId, reference_id: ReferenceId) {
let reference_ids = &mut self.resolved_references[symbol_id];
reference_ids.push(reference_id);
self.inner.with_dependent_mut(|_allocator, inner| {
inner.resolved_references[symbol_id.index()].push(reference_id);
});
}

/// Delete a reference to a symbol.
///
/// # Panics
/// Panics if provided `reference_id` is not a resolved reference for `symbol_id`.
pub fn delete_resolved_reference(&mut self, symbol_id: SymbolId, reference_id: ReferenceId) {
let reference_ids = &mut self.resolved_references[symbol_id];
let index = reference_ids.iter().position(|&id| id == reference_id).unwrap();
reference_ids.swap_remove(index);
self.inner.with_dependent_mut(|_allocator, inner| {
let reference_ids = &mut inner.resolved_references[symbol_id.index()];
let index = reference_ids.iter().position(|&id| id == reference_id).unwrap();
reference_ids.swap_remove(index);
});
}

pub fn reserve(&mut self, additional_symbols: usize, additional_references: usize) {
Expand All @@ -276,9 +307,9 @@ impl SymbolTable {
self.flags.reserve(additional_symbols);
self.scope_ids.reserve(additional_symbols);
self.declarations.reserve(additional_symbols);
self.resolved_references.reserve(additional_symbols);
self.redeclarations.reserve(additional_symbols);

self.inner.with_dependent_mut(|_allocator, inner| {
inner.resolved_references.reserve(additional_symbols);
});
self.references.reserve(additional_references);
}
}
Expand Down
12 changes: 5 additions & 7 deletions crates/oxc_wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,13 +234,11 @@ impl Oxc {

let (symbols, scopes) = semantic.into_symbol_table_and_scope_tree();

if !source_type.is_typescript_definition() {
if run_options.scope.unwrap_or_default() {
self.scope_text = Self::get_scope_text(&program, &symbols, &scopes);
}
if run_options.symbol.unwrap_or_default() {
self.symbols = symbols.serialize(&self.serializer)?;
}
if !source_type.is_typescript_definition() && run_options.scope.unwrap_or_default() {
self.scope_text = Self::get_scope_text(&program, &symbols, &scopes);
// if run_options.symbol.unwrap_or_default() {
// self.symbols = symbols.serialize(&self.serializer)?;
// }
}

if run_options.transform.unwrap_or_default() {
Expand Down
7 changes: 6 additions & 1 deletion tasks/transform_checker/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,12 @@ impl PostTransformChecker<'_, '_> {

// Check resolved references match
let reference_ids = self.get_pair(symbol_ids, |scoping, symbol_id| {
scoping.symbols.get_resolved_reference_ids(symbol_id).clone()
scoping
.symbols
.get_resolved_reference_ids(symbol_id)
.iter()
.copied()
.collect::<Vec<_>>()
});
if self.remap_reference_ids_sets(&reference_ids).is_mismatch() {
self.errors.push_mismatch(
Expand Down

0 comments on commit b86d84c

Please sign in to comment.