@@ -12,10 +12,12 @@ pub use crate::*;
1212
1313use rustc_data_structures:: fx:: FxHashMap ;
1414use rustc_data_structures:: stable_hasher:: StableHasher ;
15- use rustc_data_structures:: sync:: { Lock , LockGuard , Lrc , MappedLockGuard } ;
15+ use rustc_data_structures:: sync:: { AtomicU32 , Lock , LockGuard , Lrc , MappedLockGuard } ;
1616use std:: cmp;
17+ use std:: convert:: TryFrom ;
1718use std:: hash:: Hash ;
1819use std:: path:: { Path , PathBuf } ;
20+ use std:: sync:: atomic:: Ordering ;
1921
2022use log:: debug;
2123use std:: env;
@@ -131,6 +133,9 @@ pub(super) struct SourceMapFiles {
131133}
132134
133135pub struct SourceMap {
136+ /// The address space below this value is currently used by the files in the source map.
137+ used_address_space : AtomicU32 ,
138+
134139 files : Lock < SourceMapFiles > ,
135140 file_loader : Box < dyn FileLoader + Sync + Send > ,
136141 // This is used to apply the file path remapping as specified via
@@ -140,14 +145,24 @@ pub struct SourceMap {
140145
141146impl SourceMap {
142147 pub fn new ( path_mapping : FilePathMapping ) -> SourceMap {
143- SourceMap { files : Default :: default ( ) , file_loader : Box :: new ( RealFileLoader ) , path_mapping }
148+ SourceMap {
149+ used_address_space : AtomicU32 :: new ( 0 ) ,
150+ files : Default :: default ( ) ,
151+ file_loader : Box :: new ( RealFileLoader ) ,
152+ path_mapping,
153+ }
144154 }
145155
146156 pub fn with_file_loader (
147157 file_loader : Box < dyn FileLoader + Sync + Send > ,
148158 path_mapping : FilePathMapping ,
149159 ) -> SourceMap {
150- SourceMap { files : Default :: default ( ) , file_loader, path_mapping }
160+ SourceMap {
161+ used_address_space : AtomicU32 :: new ( 0 ) ,
162+ files : Default :: default ( ) ,
163+ file_loader,
164+ path_mapping,
165+ }
151166 }
152167
153168 pub fn path_mapping ( & self ) -> & FilePathMapping {
@@ -194,12 +209,25 @@ impl SourceMap {
194209 self . files . borrow ( ) . stable_id_to_source_file . get ( & stable_id) . map ( |sf| sf. clone ( ) )
195210 }
196211
197- fn next_start_pos ( & self ) -> usize {
198- match self . files . borrow ( ) . source_files . last ( ) {
199- None => 0 ,
200- // Add one so there is some space between files. This lets us distinguish
201- // positions in the `SourceMap`, even in the presence of zero-length files.
202- Some ( last) => last. end_pos . to_usize ( ) + 1 ,
212+ fn allocate_address_space ( & self , size : usize ) -> Result < usize , OffsetOverflowError > {
213+ let size = u32:: try_from ( size) . map_err ( |_| OffsetOverflowError ) ?;
214+
215+ loop {
216+ let current = self . used_address_space . load ( Ordering :: Relaxed ) ;
217+ let next = current
218+ . checked_add ( size)
219+ // Add one so there is some space between files. This lets us distinguish
220+ // positions in the `SourceMap`, even in the presence of zero-length files.
221+ . and_then ( |next| next. checked_add ( 1 ) )
222+ . ok_or ( OffsetOverflowError ) ?;
223+
224+ if self
225+ . used_address_space
226+ . compare_exchange ( current, next, Ordering :: Relaxed , Ordering :: Relaxed )
227+ . is_ok ( )
228+ {
229+ return Ok ( usize:: try_from ( current) . unwrap ( ) ) ;
230+ }
203231 }
204232 }
205233
@@ -218,8 +246,6 @@ impl SourceMap {
218246 filename : FileName ,
219247 src : String ,
220248 ) -> Result < Lrc < SourceFile > , OffsetOverflowError > {
221- let start_pos = self . next_start_pos ( ) ;
222-
223249 // The path is used to determine the directory for loading submodules and
224250 // include files, so it must be before remapping.
225251 // Note that filename may not be a valid path, eg it may be `<anon>` etc,
@@ -241,13 +267,15 @@ impl SourceMap {
241267 let lrc_sf = match self . source_file_by_stable_id ( file_id) {
242268 Some ( lrc_sf) => lrc_sf,
243269 None => {
270+ let start_pos = self . allocate_address_space ( src. len ( ) ) ?;
271+
244272 let source_file = Lrc :: new ( SourceFile :: new (
245273 filename,
246274 was_remapped,
247275 unmapped_path,
248276 src,
249277 Pos :: from_usize ( start_pos) ,
250- ) ? ) ;
278+ ) ) ;
251279
252280 let mut files = self . files . borrow_mut ( ) ;
253281
@@ -277,7 +305,9 @@ impl SourceMap {
277305 mut file_local_non_narrow_chars : Vec < NonNarrowChar > ,
278306 mut file_local_normalized_pos : Vec < NormalizedPos > ,
279307 ) -> Lrc < SourceFile > {
280- let start_pos = self . next_start_pos ( ) ;
308+ let start_pos = self
309+ . allocate_address_space ( source_len)
310+ . expect ( "not enough address space for imported source file" ) ;
281311
282312 let end_pos = Pos :: from_usize ( start_pos + source_len) ;
283313 let start_pos = Pos :: from_usize ( start_pos) ;
0 commit comments