oxc-project / oxc-project/backlog

Prevent dummy nodes being allocated temporarily when replacing

Open
#41 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
No language data
Stars
7
Forks
0
PR merge metrics
No merged PRs in 30d

Description

AstBuilder::move_expression allocates a dummy NullLiteral node into arena. It's typically used when replacing an Expression with a new one, but where need an owned copy of the original. The temp node is always discarded again. Unfortunately there is no Expression variant which doesn't contain a Box, so it always causes an unnecessary allocation.

Ditto AstBuilder::move_statement which allocates a temp EmptyStatement.

Neither method is much used, but this same pattern is used elsewhere without move_expression / move_statement. It'll also become much more common when we remove the unsound method AstBuilder::copy (https://github.com/oxc-project/oxc/issues/3483).

I think we could achieve the same thing without allocation by adding replace_expression + replace_statement methods:

Instead of:

fn strip_parenthesized_expression(self, expr: &mut Expression<'a>) {
  if let Expression::ParenthesizedExpression(paren_expr) = expr {
    *expr = self.ast.move_expression(&mut paren_expr.expression);
  }
}
fn strip_parenthesized_expression(self, expr: &mut Expression<'a>) {
  self.ast.replace_expression(
    expr,
    |expr| { // `expr` here is owned `Expression<'a>`
      match expr {
        Expression::ParenthesizedExpression(paren_expr) => paren_expr.expression,
        _ => expr,
      }
    }
  );
}

replace_expression + replace_statement methods would need to use unsafe code (transmute_copy) internally, but could present a safe interface to the caller.

Maybe API above is not ideal. Does it produce a pointless noop write operation when expr is not a ParenthesizedExpression? But the general principle of avoiding unnecessary allocations I think is good.

NB: In current code, I don't think compiler will be able to see the allocation is pointless and elide it because it has side effect of altering global state (moving the arena's bump pointer), which compiler does not know is not a significant action that needs to be retained. But should check this assumption.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading AstBuilder::move_expression and AstBuilder::move_statement, then inspect the other call sites that use the same temporary-node pattern. Compare the proposed replacement API with the planned removal of AstBuilder::copy in issue #3483; done means avoiding temporary arena allocations while preserving expression and statement replacement behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
performance
Issue type
Refactor
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.