Skip to content

Commit

Permalink
perf(transformer): nullish coalescing operator transform use `SparseS…
Browse files Browse the repository at this point in the history
…tack`
  • Loading branch information
overlookmotel committed Sep 21, 2024
1 parent d00d939 commit 0f48e19
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 12 deletions.
24 changes: 12 additions & 12 deletions crates/oxc_transformer/src/es2020/nullish_coalescing_operator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,22 +35,26 @@ use oxc_span::SPAN;
use oxc_syntax::operator::{AssignmentOperator, BinaryOperator, LogicalOperator};
use oxc_traverse::{Ancestor, Traverse, TraverseCtx};

use crate::context::Ctx;
use crate::{context::Ctx, helpers::stack::SparseStack};

pub struct NullishCoalescingOperator<'a> {
_ctx: Ctx<'a>,
var_declarations: std::vec::Vec<Vec<'a, VariableDeclarator<'a>>>,
var_declarations: SparseStack<Vec<'a, VariableDeclarator<'a>>>,
}

impl<'a> NullishCoalescingOperator<'a> {
pub fn new(ctx: Ctx<'a>) -> Self {
Self { _ctx: ctx, var_declarations: vec![] }
Self { _ctx: ctx, var_declarations: SparseStack::new() }
}
}

impl<'a> Traverse<'a> for NullishCoalescingOperator<'a> {
fn enter_statements(&mut self, _stmts: &mut Vec<'a, Statement<'a>>, ctx: &mut TraverseCtx<'a>) {
self.var_declarations.push(ctx.ast.vec());
fn enter_statements(
&mut self,
_stmts: &mut Vec<'a, Statement<'a>>,
_ctx: &mut TraverseCtx<'a>,
) {
self.var_declarations.push_empty();
}

fn exit_statements(
Expand All @@ -59,9 +63,6 @@ impl<'a> Traverse<'a> for NullishCoalescingOperator<'a> {
ctx: &mut TraverseCtx<'a>,
) {
if let Some(declarations) = self.var_declarations.pop() {
if declarations.is_empty() {
return;
}
let variable = ctx.ast.alloc_variable_declaration(
SPAN,
VariableDeclarationKind::Var,
Expand Down Expand Up @@ -150,10 +151,9 @@ impl<'a> Traverse<'a> for NullishCoalescingOperator<'a> {
new_expr = ctx.ast.expression_call(SPAN, arrow_function, NONE, ctx.ast.vec(), false);
} else {
let kind = VariableDeclarationKind::Var;
self.var_declarations
.last_mut()
.unwrap()
.push(ctx.ast.variable_declarator(SPAN, kind, id, None, false));

let var_declarations = self.var_declarations.get_mut_or_init(|| ctx.ast.vec());
var_declarations.push(ctx.ast.variable_declarator(SPAN, kind, id, None, false));
}

*expr = new_expr;
Expand Down
19 changes: 19 additions & 0 deletions crates/oxc_transformer/src/helpers/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,25 @@ impl<T> SparseStack<T> {
unsafe { self.values.last().unwrap_unchecked() }
}

/// Initialize the value for top entry on the stack, if it has no value already.
/// Returns mutable reference to value.
///
/// # Panics
/// Panics if the stack is empty.
pub fn get_mut_or_init<I: FnMut() -> T>(&mut self, mut init: I) -> &mut T {
let has_value = self.has_values.last_mut().unwrap();
if !*has_value {
*has_value = true;
self.values.push(init());
}

// SAFETY: `self.exists` only contains `true` if there's a corresponding value
// in `self.values`. This invariant is maintained in `push` and `pop`.
// Here either `self.exists` was already `true`, or it's just been set to `true`
// and a value pushed to `self.values` above.
unsafe { self.values.last_mut().unwrap_unchecked() }
}

/// Get number of entries on the stack.
pub fn len(&self) -> usize {
self.has_values.len()
Expand Down

0 comments on commit 0f48e19

Please sign in to comment.