Skip to content

refactor(scan_stage): remove stmt_infos field from EcmaView#9276

Merged
graphite-app[bot] merged 1 commit into
mainfrom
04-30-remove_stmt_infos_from_ecmaview
May 5, 2026
Merged

refactor(scan_stage): remove stmt_infos field from EcmaView#9276
graphite-app[bot] merged 1 commit into
mainfrom
04-30-remove_stmt_infos_from_ecmaview

Conversation

@IWANABETHATGUY

@IWANABETHATGUY IWANABETHATGUY commented Apr 30, 2026

Copy link
Copy Markdown
Member

related to #9242

Stacked on #9274.

Routes per-module StmtInfos through a side IndexVec<ModuleIdx, StmtInfos> on ScanStageOutput / NormalizedScanStageOutput (carried via EcmaRelated and RuntimeModuleTaskResult) instead of storing it on each EcmaView.

After #9274, EcmaView.stmt_infos was just an empty StmtInfos::new() placeholder for the entire link/generate lifetime — LinkStage::new mem::replaced the real value out into LinkStage.stmt_infos immediately, and every reader went through the side table. This PR removes the field entirely.

Changes:

  • EcmaRelated and RuntimeModuleTaskResult carry stmt_infos: StmtInfos.
  • IntermediateNormalModules collects per-module stmt_infos parallel to index_ecma_ast; the module loader builds a side HybridIndexVec<ModuleIdx, StmtInfos> at output time (external modules get an empty StmtInfos::new() placeholder).
  • ScanStageOutput / NormalizedScanStageOutput carry the side table; ScanStageCache::merge and create_output thread it through.
  • LinkStage::new mem::takes scan_stage_output.stmt_infos directly (no per-module mem::replace walk).
  • defer_sync_scan_data reads &scan_stage_output.stmt_infos[module_idx] instead of &normal.stmt_infos.
  • EcmaView.stmt_infos field removed.

IWANABETHATGUY commented Apr 30, 2026

Copy link
Copy Markdown
Member Author

How to use the Graphite Merge Queue

Add the label graphite: merge-when-ready to this PR to add it to the merge queue.

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@codspeed-hq

codspeed-hq Bot commented Apr 30, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 4 untouched benchmarks
⏩ 10 skipped benchmarks1


Comparing 04-30-remove_stmt_infos_from_ecmaview (b01d243) with main (fb0d3b6)

Open in CodSpeed

Footnotes

  1. 10 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@graphite-app
graphite-app Bot changed the base branch from 04-30-detach_stmt_info to graphite-base/9276 April 30, 2026 07:53
@graphite-app
graphite-app Bot force-pushed the 04-30-remove_stmt_infos_from_ecmaview branch from 5f96fd2 to ef6e6ca Compare April 30, 2026 07:57
@graphite-app
graphite-app Bot force-pushed the graphite-base/9276 branch from 82b35fe to 55b8525 Compare April 30, 2026 07:57
@graphite-app
graphite-app Bot changed the base branch from graphite-base/9276 to main April 30, 2026 07:58
@graphite-app
graphite-app Bot force-pushed the 04-30-remove_stmt_infos_from_ecmaview branch from ef6e6ca to 8287925 Compare April 30, 2026 07:58
@netlify

netlify Bot commented Apr 30, 2026

Copy link
Copy Markdown

Deploy Preview for rolldown-rs canceled.

Name Link
🔨 Latest commit 45adf2b
🔍 Latest deploy log https://app.netlify.com/projects/rolldown-rs/deploys/69f9877db0a87e00089b12ec

IWANABETHATGUY commented May 5, 2026

Copy link
Copy Markdown
Member Author

Merge activity

  • May 5, 5:59 AM UTC: The merge label 'graphite: merge-when-ready' was detected. This PR will be added to the Graphite merge queue once it meets the requirements.
  • May 5, 5:59 AM UTC: IWANABETHATGUY added this pull request to the Graphite merge queue.
  • May 5, 6:04 AM UTC: Merged by the Graphite merge queue.

related to #9242

Stacked on #9274.

Routes per-module `StmtInfos` through a side `IndexVec<ModuleIdx, StmtInfos>` on `ScanStageOutput` / `NormalizedScanStageOutput` (carried via `EcmaRelated` and `RuntimeModuleTaskResult`) instead of storing it on each `EcmaView`.

After #9274, `EcmaView.stmt_infos` was just an empty `StmtInfos::new()` placeholder for the entire link/generate lifetime — `LinkStage::new` `mem::replace`d the real value out into `LinkStage.stmt_infos` immediately, and every reader went through the side table. This PR removes the field entirely.

Changes:
- `EcmaRelated` and `RuntimeModuleTaskResult` carry `stmt_infos: StmtInfos`.
- `IntermediateNormalModules` collects per-module `stmt_infos` parallel to `index_ecma_ast`; the module loader builds a side `HybridIndexVec<ModuleIdx, StmtInfos>` at output time (external modules get an empty `StmtInfos::new()` placeholder).
- `ScanStageOutput` / `NormalizedScanStageOutput` carry the side table; `ScanStageCache::merge` and `create_output` thread it through.
- `LinkStage::new` `mem::take`s `scan_stage_output.stmt_infos` directly (no per-module `mem::replace` walk).
- `defer_sync_scan_data` reads `&scan_stage_output.stmt_infos[module_idx]` instead of `&normal.stmt_infos`.
- `EcmaView.stmt_infos` field removed.
@graphite-app
graphite-app Bot force-pushed the 04-30-remove_stmt_infos_from_ecmaview branch from b01d243 to 45adf2b Compare May 5, 2026 06:00
@graphite-app
graphite-app Bot merged commit 45adf2b into main May 5, 2026
33 checks passed
@graphite-app
graphite-app Bot deleted the 04-30-remove_stmt_infos_from_ecmaview branch May 5, 2026 06:04
graphite-app Bot pushed a commit that referenced this pull request May 5, 2026
#9278)

Stacked on #9276.

Closed #9242

Replaces `EcmaAst::allocator(&self) -> &Allocator` with `with_fields(&mut self, |fields| ...)`, a closure-based accessor that bundles read-only access to `source`/`source_type`/`allocator`/`comments`/`program`. The `&mut self` receiver makes the soundness invariant of `unsafe impl Sync for EcmaAst` locally checkable.

## Why

`oxc::allocator::Allocator` is `!Sync` (it holds `Cell<NonNull<u8>>` and `Cell<Option<NonNull<ChunkFooter>>>` for bumpalo''s bump pointer). The `unsafe impl Sync for EcmaAst {}` is sound only by convention: `&EcmaAst` is treated as read-only at runtime. But `pub fn allocator(&self) -> &Allocator` punched a hole in that — anyone with a shared `&EcmaAst` (e.g., a rayon `par_iter` worker) could call `ast.allocator()` and then `Allocator::alloc` (which mutates internal `Cell`s through `&self`), racing with another worker.

`Sync` cannot be removed — it''s required by parallel chunk rendering in `render_chunk_to_assets.rs` and indirectly by `anyhow::Error::new(SendError<ModuleLoaderMsg>)` in `file_emitter.rs`. So the goal is to make the unsoundness statically harder to reach.

## Changes

- `EcmaAst::with_fields(&mut self, |fields| ...)` is the only public way to obtain `&Allocator`. Built on the existing `ProgramCell::with_mut`, reborrowed `&mut Program → &Program`.
- `pub fn allocator(&self)` removed. The 3 callers all migrate cleanly:
  - `clone_with_another_arena` reads `self.program.borrow_owner().allocator.used_bytes()` directly.
  - `ecma_module_view_factory::create_ecma_view` wraps the `AstScanner::new` + `scanner.scan` block in `ast.with_fields(...)`.
  - `runtime_module_task::make_ecma_ast` does the same.
- `unsafe impl Send for EcmaAst {}` and `unsafe impl Sync for EcmaAst {}` now have `// SAFETY:` blocks spelling out the invariant and naming the call sites that depend on `Sync`.

## Verification

- `cargo check --workspace --all-targets` clean.
- `cargo clippy --workspace --all-targets -- --deny warnings` clean.
- `cargo test -p rolldown --test integration -- --skip ''hmr''` — all 1666 non-HMR integration tests pass.
- `rg -n ''ast\.allocator\(\)'' crates/` — zero results.
This was referenced May 6, 2026
@shulaoda shulaoda mentioned this pull request May 7, 2026
shulaoda added a commit that referenced this pull request May 7, 2026
## [1.0.0] - 2026-05-07

### 🐛 Bug Fixes

- dev/lazy: lazily compiled modules should be watched (#9301) by @h-a-n-a
- implement dynamic dominator merge logic (#9270) by @TheAlexLichter
- dev: apply __toCommonJS interop when CJS requires ESM in HMR finalizer (#9261) by @h-a-n-a

### 🚜 Refactor

- ecma_ast: tighten allocator access to enforce Sync invariant (#9278) by @IWANABETHATGUY
- scan_stage: remove stmt_infos field from EcmaView (#9276) by @IWANABETHATGUY
- link_stage: detach stmt_infos from EcmaView (#9274) by @IWANABETHATGUY
- link_stage: detach depended_runtime_helper from EcmaView to remove unsafe (#9265) by @IWANABETHATGUY
- link_stage: remove unsafe in determine_module_exports_kind (#9253) by @IWANABETHATGUY

### 📚 Documentation

- getting-started: remove RC warning for 1.0.0 release (#9310) by @shulaoda
- getting-started: update version references for 1.0.0 release (#9309) by @shulaoda
- add Vite+ tab to getting-started snippets (#9285) by @shulaoda
- lazy-barrel: clarify own-exports behavior for import-then-export records (#9298) by @shulaoda
- restructure top navigation around Learn vs Reference (#9284) by @shulaoda
- builtin-plugins: add bundle analyzer plugin docs (#9292) by @shulaoda
- design doc for reference_needed_symbols (#9264) by @IWANABETHATGUY

### ⚡ Performance

- devtools: write logs on a background thread (#9219) by @IWANABETHATGUY

### ⚙️ Miscellaneous Tasks

- mark esbuild/ts/parameter_props_use_define_for_class_fields_true as passed (#9308) by @sapphi-red
- deps: upgrade oxc to 0.129.0 (#9297) by @shulaoda
- deps: update rollup submodule for tests to v4.60.3 (#9294) by @sapphi-red
- deps: update test262 submodule for tests (#9295) by @sapphi-red
- ai: add rolldown REPL decode skill (#9245) by @Dunqing
pull Bot pushed a commit to olrtg/rolldown that referenced this pull request May 7, 2026
## [1.0.0] - 2026-05-07

### 🐛 Bug Fixes

- dev/lazy: lazily compiled modules should be watched (rolldown#9301) by @h-a-n-a
- implement dynamic dominator merge logic (rolldown#9270) by @TheAlexLichter
- dev: apply __toCommonJS interop when CJS requires ESM in HMR finalizer (rolldown#9261) by @h-a-n-a

### 🚜 Refactor

- ecma_ast: tighten allocator access to enforce Sync invariant (rolldown#9278) by @IWANABETHATGUY
- scan_stage: remove stmt_infos field from EcmaView (rolldown#9276) by @IWANABETHATGUY
- link_stage: detach stmt_infos from EcmaView (rolldown#9274) by @IWANABETHATGUY
- link_stage: detach depended_runtime_helper from EcmaView to remove unsafe (rolldown#9265) by @IWANABETHATGUY
- link_stage: remove unsafe in determine_module_exports_kind (rolldown#9253) by @IWANABETHATGUY

### 📚 Documentation

- getting-started: remove RC warning for 1.0.0 release (rolldown#9310) by @shulaoda
- getting-started: update version references for 1.0.0 release (rolldown#9309) by @shulaoda
- add Vite+ tab to getting-started snippets (rolldown#9285) by @shulaoda
- lazy-barrel: clarify own-exports behavior for import-then-export records (rolldown#9298) by @shulaoda
- restructure top navigation around Learn vs Reference (rolldown#9284) by @shulaoda
- builtin-plugins: add bundle analyzer plugin docs (rolldown#9292) by @shulaoda
- design doc for reference_needed_symbols (rolldown#9264) by @IWANABETHATGUY

### ⚡ Performance

- devtools: write logs on a background thread (rolldown#9219) by @IWANABETHATGUY

### ⚙️ Miscellaneous Tasks

- mark esbuild/ts/parameter_props_use_define_for_class_fields_true as passed (rolldown#9308) by @sapphi-red
- deps: upgrade oxc to 0.129.0 (rolldown#9297) by @shulaoda
- deps: update rollup submodule for tests to v4.60.3 (rolldown#9294) by @sapphi-red
- deps: update test262 submodule for tests (rolldown#9295) by @sapphi-red
- ai: add rolldown REPL decode skill (rolldown#9245) by @Dunqing

Co-authored-by: shulaoda <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants