Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 53 additions & 17 deletions src/concat_sourcemap_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,35 +107,71 @@ impl<'a> ConcatSourceMapBuilder<'a> {

// Extend `tokens`, skipping the first token if it duplicates the last existing one.
//
// Compute the offset-adjusted source/name ids BEFORE building the token,
// and only commit them to `self.token_chunk_prev_*` once we've decided
// to actually push the token. Updating the prev-id state for a token
// that gets skipped by the dedup `continue` below would pollute the
// next sourcemap's TokenChunk header.
// Two optimizations vs. the original loop:
//
// 1. Track `last_source_id` / `last_name_id` in plain locals instead
// of writing back to `self.token_chunk_prev_*` on every iteration.
// The closure-based version captured `&mut self`, forcing a store
// to memory per-token; with locals the optimizer can keep them in
// registers and write back once at the end.
//
// 2. Hoist the `i == 0` dedup check out of the hot loop by handling
// the first token separately.
//
// Correctness: only commit the per-token id updates to `last_*` when
// the token is actually pushed. Updating the prev-id state for a
// token that gets dropped by dedup would pollute the next
// sourcemap's TokenChunk header.
let mut last_source_id = self.token_chunk_prev_source_id;
let mut last_name_id = self.token_chunk_prev_name_id;

self.tokens.reserve(sourcemap.tokens.len());
for (i, token) in sourcemap.get_tokens().enumerate() {
let source_id_offset = token.get_source_id().map(|x| x + source_offset);
let name_id_offset = token.get_name_id().map(|x| x + name_offset);

let mut iter = sourcemap.get_tokens();
if let Some(first) = iter.next() {
let source_id_offset = first.get_source_id().map(|x| x + source_offset);
let name_id_offset = first.get_name_id().map(|x| x + name_offset);
let new_token = Token::new(
token.get_dst_line() + line_offset,
token.get_dst_col(),
token.get_src_line(),
token.get_src_col(),
first.get_dst_line() + line_offset,
first.get_dst_col(),
first.get_src_line(),
first.get_src_col(),
source_id_offset,
name_id_offset,
);
if i == 0 && self.tokens.last() == Some(&new_token) {
continue;
if self.tokens.last() != Some(&new_token) {
if let Some(s) = source_id_offset {
last_source_id = s;
}
if let Some(n) = name_id_offset {
last_name_id = n;
}
self.tokens.push(new_token);
}
}

for token in iter {
let source_id_offset = token.get_source_id().map(|x| x + source_offset);
let name_id_offset = token.get_name_id().map(|x| x + name_offset);
if let Some(s) = source_id_offset {
self.token_chunk_prev_source_id = s;
last_source_id = s;
}
if let Some(n) = name_id_offset {
self.token_chunk_prev_name_id = n;
last_name_id = n;
}
self.tokens.push(new_token);
self.tokens.push(Token::new(
token.get_dst_line() + line_offset,
token.get_dst_col(),
token.get_src_line(),
token.get_src_col(),
source_id_offset,
name_id_offset,
));
}

self.token_chunk_prev_source_id = last_source_id;
self.token_chunk_prev_name_id = last_name_id;

// Add `token_chunks` after tokens are added so we know the actual end index
let end_token_idx = self.tokens.len() as u32;

Expand Down
Loading