@@ -190,6 +190,11 @@ pub struct SourceMap {
190
190
/// The address space below this value is currently used by the files in the source map.
191
191
used_address_space : AtomicU32 ,
192
192
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
+
193
198
files : RwLock < SourceMapFiles > ,
194
199
file_loader : IntoDynSyncSend < Box < dyn FileLoader + Sync + Send > > ,
195
200
// This is used to apply the file path remapping as specified via
@@ -216,6 +221,7 @@ impl SourceMap {
216
221
) -> SourceMap {
217
222
SourceMap {
218
223
used_address_space : AtomicU32 :: new ( 0 ) ,
224
+ sorted_files : Default :: default ( ) ,
219
225
files : Default :: default ( ) ,
220
226
file_loader : IntoDynSyncSend ( file_loader) ,
221
227
path_mapping,
@@ -327,17 +333,39 @@ impl SourceMap {
327
333
// the ID we generate for the SourceFile we just created.
328
334
debug_assert_eq ! ( StableSourceFileId :: new( & source_file) , file_id) ;
329
335
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) ;
334
337
335
338
source_file
336
339
}
337
340
} ;
338
341
Ok ( lrc_sf)
339
342
}
340
343
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
+
341
369
/// Allocates a new `SourceFile` representing a source file from an external
342
370
/// crate. The source code of such an "imported `SourceFile`" is not available,
343
371
/// but we still know enough to generate accurate debuginfo location
@@ -411,12 +439,7 @@ impl SourceMap {
411
439
cnum,
412
440
} ) ;
413
441
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) ) ;
420
443
421
444
source_file
422
445
}
@@ -1082,7 +1105,9 @@ impl SourceMap {
1082
1105
/// This index is guaranteed to be valid for the lifetime of this `SourceMap`,
1083
1106
/// since `source_files` is a `MonotonicVec`
1084
1107
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
1086
1111
}
1087
1112
1088
1113
pub fn count_lines ( & self ) -> usize {
0 commit comments