Skip to content

Commit

Permalink
feat: 🎸 make data in arena cloneable
Browse files Browse the repository at this point in the history
  • Loading branch information
IWANABETHATGUY committed Jan 20, 2025
1 parent 259a47b commit 153e7b4
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 28 deletions.
7 changes: 6 additions & 1 deletion crates/oxc_allocator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ pub use vec::Vec;
pub struct Allocator {
bump: Bump,
}

impl Allocator {
/// Allocate an object in this [`Allocator`] and return an exclusive reference to it.
///
Expand Down Expand Up @@ -189,6 +188,12 @@ impl Allocator {
}
}

impl Allocator {
/// Create a new bump-allocated memory arena.
pub fn with_capacity(size: usize) -> Self {
Self { bump: Bump::with_capacity(size) }
}
}
/// SAFETY: Not actually safe, but for enabling `Send` for downstream crates.
unsafe impl Send for Allocator {}
/// SAFETY: Not actually safe, but for enabling `Sync` for downstream crates.
Expand Down
13 changes: 0 additions & 13 deletions crates/oxc_ast/src/ast/js.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ pub struct Program<'a> {
pub directives: Vec<'a, Directive<'a>>,
pub body: Vec<'a, Statement<'a>>,
#[estree(skip)]
#[clone_in(default)]
pub scope_id: Cell<Option<ScopeId>>,
}

Expand Down Expand Up @@ -227,7 +226,6 @@ pub struct IdentifierReference<'a> {
/// set in the bind step of semantic analysis, and will always be [`None`]
/// immediately after parsing.
#[estree(skip)]
#[clone_in(default)]
pub reference_id: Cell<Option<ReferenceId>>,
}

Expand All @@ -251,7 +249,6 @@ pub struct BindingIdentifier<'a> {
///
/// [`semantic analysis`]: <https://docs.rs/oxc_semantic/latest/oxc_semantic/struct.SemanticBuilder.html>
#[estree(skip)]
#[clone_in(default)]
pub symbol_id: Cell<Option<SymbolId>>,
}

Expand Down Expand Up @@ -1043,7 +1040,6 @@ pub struct BlockStatement<'a> {
pub span: Span,
pub body: Vec<'a, Statement<'a>>,
#[estree(skip)]
#[clone_in(default)]
pub scope_id: Cell<Option<ScopeId>>,
}

Expand Down Expand Up @@ -1187,7 +1183,6 @@ pub struct ForStatement<'a> {
pub update: Option<Expression<'a>>,
pub body: Statement<'a>,
#[estree(skip)]
#[clone_in(default)]
pub scope_id: Cell<Option<ScopeId>>,
}

Expand Down Expand Up @@ -1218,7 +1213,6 @@ pub struct ForInStatement<'a> {
pub right: Expression<'a>,
pub body: Statement<'a>,
#[estree(skip)]
#[clone_in(default)]
pub scope_id: Cell<Option<ScopeId>>,
}

Expand Down Expand Up @@ -1249,7 +1243,6 @@ pub struct ForOfStatement<'a> {
pub right: Expression<'a>,
pub body: Statement<'a>,
#[estree(skip)]
#[clone_in(default)]
pub scope_id: Cell<Option<ScopeId>>,
}

Expand Down Expand Up @@ -1301,7 +1294,6 @@ pub struct SwitchStatement<'a> {
#[scope(enter_before)]
pub cases: Vec<'a, SwitchCase<'a>>,
#[estree(skip)]
#[clone_in(default)]
pub scope_id: Cell<Option<ScopeId>>,
}

Expand Down Expand Up @@ -1391,7 +1383,6 @@ pub struct CatchClause<'a> {
/// The statements run when an error is caught
pub body: Box<'a, BlockStatement<'a>>,
#[estree(skip)]
#[clone_in(default)]
pub scope_id: Cell<Option<ScopeId>>,
}

Expand Down Expand Up @@ -1625,7 +1616,6 @@ pub struct Function<'a> {
/// ```
pub body: Option<Box<'a, FunctionBody<'a>>>,
#[estree(skip)]
#[clone_in(default)]
pub scope_id: Cell<Option<ScopeId>>,
}

Expand Down Expand Up @@ -1717,7 +1707,6 @@ pub struct ArrowFunctionExpression<'a> {
/// See `expression` for whether this arrow expression returns an expression.
pub body: Box<'a, FunctionBody<'a>>,
#[estree(skip)]
#[clone_in(default)]
pub scope_id: Cell<Option<ScopeId>>,
}

Expand Down Expand Up @@ -1804,7 +1793,6 @@ pub struct Class<'a> {
/// Id of the scope created by the [`Class`], including type parameters and
/// statements within the [`ClassBody`].
#[estree(skip)]
#[clone_in(default)]
pub scope_id: Cell<Option<ScopeId>>,
}

Expand Down Expand Up @@ -2056,7 +2044,6 @@ pub struct StaticBlock<'a> {
pub span: Span,
pub body: Vec<'a, Statement<'a>>,
#[estree(skip)]
#[clone_in(default)]
pub scope_id: Cell<Option<ScopeId>>,
}

Expand Down
26 changes: 13 additions & 13 deletions crates/oxc_ast/src/generated/derive_clone_in.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ impl<'new_alloc> CloneIn<'new_alloc> for Program<'_> {
hashbang: CloneIn::clone_in(&self.hashbang, allocator),
directives: CloneIn::clone_in(&self.directives, allocator),
body: CloneIn::clone_in(&self.body, allocator),
scope_id: Default::default(),
scope_id: CloneIn::clone_in(&self.scope_id, allocator),
}
}
}
Expand Down Expand Up @@ -244,7 +244,7 @@ impl<'new_alloc> CloneIn<'new_alloc> for IdentifierReference<'_> {
IdentifierReference {
span: CloneIn::clone_in(&self.span, allocator),
name: CloneIn::clone_in(&self.name, allocator),
reference_id: Default::default(),
reference_id: CloneIn::clone_in(&self.reference_id, allocator),
}
}
}
Expand All @@ -255,7 +255,7 @@ impl<'new_alloc> CloneIn<'new_alloc> for BindingIdentifier<'_> {
BindingIdentifier {
span: CloneIn::clone_in(&self.span, allocator),
name: CloneIn::clone_in(&self.name, allocator),
symbol_id: Default::default(),
symbol_id: CloneIn::clone_in(&self.symbol_id, allocator),
}
}
}
Expand Down Expand Up @@ -1345,7 +1345,7 @@ impl<'new_alloc> CloneIn<'new_alloc> for BlockStatement<'_> {
BlockStatement {
span: CloneIn::clone_in(&self.span, allocator),
body: CloneIn::clone_in(&self.body, allocator),
scope_id: Default::default(),
scope_id: CloneIn::clone_in(&self.scope_id, allocator),
}
}
}
Expand Down Expand Up @@ -1480,7 +1480,7 @@ impl<'new_alloc> CloneIn<'new_alloc> for ForStatement<'_> {
test: CloneIn::clone_in(&self.test, allocator),
update: CloneIn::clone_in(&self.update, allocator),
body: CloneIn::clone_in(&self.body, allocator),
scope_id: Default::default(),
scope_id: CloneIn::clone_in(&self.scope_id, allocator),
}
}
}
Expand Down Expand Up @@ -1624,7 +1624,7 @@ impl<'new_alloc> CloneIn<'new_alloc> for ForInStatement<'_> {
left: CloneIn::clone_in(&self.left, allocator),
right: CloneIn::clone_in(&self.right, allocator),
body: CloneIn::clone_in(&self.body, allocator),
scope_id: Default::default(),
scope_id: CloneIn::clone_in(&self.scope_id, allocator),
}
}
}
Expand Down Expand Up @@ -1682,7 +1682,7 @@ impl<'new_alloc> CloneIn<'new_alloc> for ForOfStatement<'_> {
left: CloneIn::clone_in(&self.left, allocator),
right: CloneIn::clone_in(&self.right, allocator),
body: CloneIn::clone_in(&self.body, allocator),
scope_id: Default::default(),
scope_id: CloneIn::clone_in(&self.scope_id, allocator),
}
}
}
Expand Down Expand Up @@ -1735,7 +1735,7 @@ impl<'new_alloc> CloneIn<'new_alloc> for SwitchStatement<'_> {
span: CloneIn::clone_in(&self.span, allocator),
discriminant: CloneIn::clone_in(&self.discriminant, allocator),
cases: CloneIn::clone_in(&self.cases, allocator),
scope_id: Default::default(),
scope_id: CloneIn::clone_in(&self.scope_id, allocator),
}
}
}
Expand Down Expand Up @@ -1791,7 +1791,7 @@ impl<'new_alloc> CloneIn<'new_alloc> for CatchClause<'_> {
span: CloneIn::clone_in(&self.span, allocator),
param: CloneIn::clone_in(&self.param, allocator),
body: CloneIn::clone_in(&self.body, allocator),
scope_id: Default::default(),
scope_id: CloneIn::clone_in(&self.scope_id, allocator),
}
}
}
Expand Down Expand Up @@ -1915,7 +1915,7 @@ impl<'new_alloc> CloneIn<'new_alloc> for Function<'_> {
params: CloneIn::clone_in(&self.params, allocator),
return_type: CloneIn::clone_in(&self.return_type, allocator),
body: CloneIn::clone_in(&self.body, allocator),
scope_id: Default::default(),
scope_id: CloneIn::clone_in(&self.scope_id, allocator),
}
}
}
Expand Down Expand Up @@ -1992,7 +1992,7 @@ impl<'new_alloc> CloneIn<'new_alloc> for ArrowFunctionExpression<'_> {
params: CloneIn::clone_in(&self.params, allocator),
return_type: CloneIn::clone_in(&self.return_type, allocator),
body: CloneIn::clone_in(&self.body, allocator),
scope_id: Default::default(),
scope_id: CloneIn::clone_in(&self.scope_id, allocator),
}
}
}
Expand Down Expand Up @@ -2023,7 +2023,7 @@ impl<'new_alloc> CloneIn<'new_alloc> for Class<'_> {
body: CloneIn::clone_in(&self.body, allocator),
r#abstract: CloneIn::clone_in(&self.r#abstract, allocator),
declare: CloneIn::clone_in(&self.declare, allocator),
scope_id: Default::default(),
scope_id: CloneIn::clone_in(&self.scope_id, allocator),
}
}
}
Expand Down Expand Up @@ -2160,7 +2160,7 @@ impl<'new_alloc> CloneIn<'new_alloc> for StaticBlock<'_> {
StaticBlock {
span: CloneIn::clone_in(&self.span, allocator),
body: CloneIn::clone_in(&self.body, allocator),
scope_id: Default::default(),
scope_id: CloneIn::clone_in(&self.scope_id, allocator),
}
}
}
Expand Down
28 changes: 27 additions & 1 deletion crates/oxc_semantic/src/symbol.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{fmt, mem};

use oxc_allocator::{Allocator, FromIn, Vec as ArenaVec};
use oxc_allocator::{Allocator, CloneIn, FromIn, Vec as ArenaVec};
use oxc_ast::ast::{Expression, IdentifierReference};
use oxc_index::{Idx, IndexVec};
use oxc_span::{Atom, Span};
Expand Down Expand Up @@ -320,6 +320,32 @@ impl SymbolTable {
});
self.references.reserve(additional_references);
}

/// Clone the `[SymbolTable]` with another `Allocator`.
/// and copy rest fields, this is used to cache the Ast in incremental compilation
/// use another `Allocator` to avoid memory leak
#[must_use]
pub fn clone_with_another_arena(&self) -> SymbolTable {
let allocator = self.inner.with_dependent(|alloc, _| {
Allocator::with_capacity(alloc.allocated_bytes_including_metadata())
});
Self {
spans: self.spans.clone(),
flags: self.flags.clone(),
scope_ids: self.scope_ids.clone(),
declarations: self.declarations.clone(),
redeclarations: self.redeclarations.clone(),
references: self.references.clone(),
inner: SymbolTableCell::new(allocator, |allocator| {
self.inner.with_dependent(|_allocator, inner| {
let names = inner.names.clone_in(&allocator);
let redeclaration_spans = inner.redeclaration_spans.clone_in(&allocator);
let resolved_references = inner.resolved_references.clone_in(&allocator);
SymbolTableInner { names, redeclaration_spans, resolved_references }
})
}),
}
}
}

/// Checks whether the a identifier reference is a global value or not.
Expand Down
8 changes: 8 additions & 0 deletions crates/oxc_syntax/src/reference.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@ use crate::{node::NodeId, symbol::SymbolId};
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct ReferenceId(NonMaxU32);

impl<'alloc> CloneIn<'alloc> for ReferenceId {
type Cloned = Self;

fn clone_in(&self, _: &'alloc oxc_allocator::Allocator) -> Self::Cloned {
*self
}
}

impl Idx for ReferenceId {
#[allow(clippy::cast_possible_truncation)]
fn from_usize(idx: usize) -> Self {
Expand Down

0 comments on commit 153e7b4

Please sign in to comment.