perf(codegen): avoid allocations for single comment anchors (#25598)

This commit is contained in:
camc314 committed 2026-08-24 02:47:08 +00:00
1 parent a237666359
commit fe444cc10a
3 files changed
+18 -3

No files matched your search

Generated
+1
View File
@@ -1905,6 +1905,7 @@ dependencies = [
"oxc_syntax",
"pico-args",
"rustc-hash",
"smallvec",
]
[[package]]
+1
View File
@@ -34,6 +34,7 @@ oxc_syntax = { workspace = true }
bitflags = { workspace = true }
cow-utils = { workspace = true }
rustc-hash = { workspace = true }
smallvec = { workspace = true }
[dev-dependencies]
insta = { workspace = true }
+16 -3
View File
@@ -1,6 +1,7 @@
use std::borrow::Cow;
use rustc_hash::{FxHashMap, FxHashSet};
use smallvec::SmallVec;
use oxc_ast::{
Comment, CommentKind,
@@ -11,7 +12,9 @@ use oxc_syntax::line_terminator::LineTerminatorSplitter;
use crate::{Codegen, LegalComment, options::CommentOptions};
pub type CommentsMap = FxHashMap</* attached_to */ u32, Vec<Comment>>;
type CommentList = SmallVec<[Comment; 1]>;
pub type CommentsMap = FxHashMap</* attached_to */ u32, CommentList>;
/// Whether a comment remains meaningful if its original AST anchor is removed.
fn preserve_when_orphaned(comment: Comment) -> bool {
@@ -72,6 +75,9 @@ impl Codegen<'_> {
if self.options.comments == CommentOptions::disabled() {
return;
}
// Each retained comment can create at most one map entry. Reserving
// this upper bound avoids incremental map growth while preprocessing.
self.comments.reserve(comments.len());
for comment in comments {
// Stash pure / no-side-effects comments by `attached_to` so the
// emission site can recover the verbatim source text instead of
@@ -158,7 +164,7 @@ impl Codegen<'_> {
}
}
pub(crate) fn get_comments(&mut self, start: u32) -> Option<Vec<Comment>> {
pub(crate) fn get_comments(&mut self, start: u32) -> Option<CommentList> {
if self.comments.is_empty() {
return None;
}
@@ -283,7 +289,14 @@ impl Codegen<'_> {
for k in self.orphan_comment_keys.drain(..idx) {
let Some(entry) = comments.get_mut(&k) else { continue };
debug_assert!(entry.iter().any(|c| preserve_when_orphaned(*c)));
orphans.extend(entry.extract_if(.., |c| preserve_when_orphaned(*c)));
entry.retain(|comment| {
if preserve_when_orphaned(*comment) {
orphans.push(*comment);
false
} else {
true
}
});
if entry.is_empty() {
comments.remove(&k);
}