Skip to content

Commit c03118e

Browse files
committed
Ensure lookup_source_file_idx has a sorted list of source files to use
1 parent c587fd4 commit c03118e

File tree

2 files changed

+37
-11
lines changed

2 files changed

+37
-11
lines changed

compiler/rustc_span/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#![feature(round_char_boundary)]
2424
#![feature(read_buf)]
2525
#![feature(new_uninit)]
26+
#![feature(is_sorted)]
2627
#![deny(rustc::untranslatable_diagnostic)]
2728
#![deny(rustc::diagnostic_outside_of_impl)]
2829
#![allow(internal_features)]

compiler/rustc_span/src/source_map.rs

+36-11
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,11 @@ pub struct SourceMap {
190190
/// The address space below this value is currently used by the files in the source map.
191191
used_address_space: AtomicU32,
192192

193+
/// A list of source files starting positions along with their index in `self.files` sorted
194+
/// by the starting positions. This is used for fast lookup of a position in
195+
/// `lookup_source_file_idx`.
196+
sorted_files: Lock<Vec<(BytePos, usize)>>,
197+
193198
files: RwLock<SourceMapFiles>,
194199
file_loader: IntoDynSyncSend<Box<dyn FileLoader + Sync + Send>>,
195200
// This is used to apply the file path remapping as specified via
@@ -216,6 +221,7 @@ impl SourceMap {
216221
) -> SourceMap {
217222
SourceMap {
218223
used_address_space: AtomicU32::new(0),
224+
sorted_files: Default::default(),
219225
files: Default::default(),
220226
file_loader: IntoDynSyncSend(file_loader),
221227
path_mapping,
@@ -327,17 +333,39 @@ impl SourceMap {
327333
// the ID we generate for the SourceFile we just created.
328334
debug_assert_eq!(StableSourceFileId::new(&source_file), file_id);
329335

330-
let mut files = self.files.borrow_mut();
331-
332-
files.source_files.push(source_file.clone());
333-
files.stable_id_to_source_file.insert(file_id, source_file.clone());
336+
self.insert_source_file(&source_file, file_id);
334337

335338
source_file
336339
}
337340
};
338341
Ok(lrc_sf)
339342
}
340343

344+
fn insert_source_file(&self, file: &Lrc<SourceFile>, file_id: StableSourceFileId) {
345+
let file_idx = {
346+
let mut files = self.files.borrow_mut();
347+
348+
let file_idx = files.source_files.len();
349+
files.source_files.push(file.clone());
350+
files.stable_id_to_source_file.insert(file_id, file.clone());
351+
352+
file_idx
353+
};
354+
355+
{
356+
let mut sorted_files = self.sorted_files.lock();
357+
let idx = sorted_files.partition_point(|&(start_pos, _)| start_pos < file.start_pos);
358+
sorted_files.insert(idx, (file.start_pos, file_idx));
359+
debug_assert!(sorted_files.iter().map(|&(start_pos, _)| start_pos).is_sorted());
360+
}
361+
362+
// Ensure both start and end belong to the new source file
363+
debug_assert!(
364+
Lrc::as_ptr(&self.lookup_byte_offset(file.start_pos).sf) == Lrc::as_ptr(file)
365+
);
366+
debug_assert!(Lrc::as_ptr(&self.lookup_byte_offset(file.end_pos).sf) == Lrc::as_ptr(file));
367+
}
368+
341369
/// Allocates a new `SourceFile` representing a source file from an external
342370
/// crate. The source code of such an "imported `SourceFile`" is not available,
343371
/// but we still know enough to generate accurate debuginfo location
@@ -411,12 +439,7 @@ impl SourceMap {
411439
cnum,
412440
});
413441

414-
let mut files = self.files.borrow_mut();
415-
416-
files.source_files.push(source_file.clone());
417-
files
418-
.stable_id_to_source_file
419-
.insert(StableSourceFileId::new(&source_file), source_file.clone());
442+
self.insert_source_file(&source_file, StableSourceFileId::new(&source_file));
420443

421444
source_file
422445
}
@@ -1082,7 +1105,9 @@ impl SourceMap {
10821105
/// This index is guaranteed to be valid for the lifetime of this `SourceMap`,
10831106
/// since `source_files` is a `MonotonicVec`
10841107
pub fn lookup_source_file_idx(&self, pos: BytePos) -> usize {
1085-
self.files.borrow().source_files.partition_point(|x| x.start_pos <= pos) - 1
1108+
let sorted_files = self.sorted_files.lock();
1109+
let idx = sorted_files.partition_point(|&(start_pos, _)| start_pos <= pos) - 1;
1110+
sorted_files[idx].1
10861111
}
10871112

10881113
pub fn count_lines(&self) -> usize {

0 commit comments

Comments
 (0)