@@ -12,10 +12,12 @@ pub use crate::*;
12
12
13
13
use rustc_data_structures:: fx:: FxHashMap ;
14
14
use 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 } ;
16
16
use std:: cmp;
17
+ use std:: convert:: TryFrom ;
17
18
use std:: hash:: Hash ;
18
19
use std:: path:: { Path , PathBuf } ;
20
+ use std:: sync:: atomic:: Ordering ;
19
21
20
22
use log:: debug;
21
23
use std:: env;
@@ -131,6 +133,9 @@ pub(super) struct SourceMapFiles {
131
133
}
132
134
133
135
pub 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
+
134
139
files : Lock < SourceMapFiles > ,
135
140
file_loader : Box < dyn FileLoader + Sync + Send > ,
136
141
// This is used to apply the file path remapping as specified via
@@ -140,14 +145,24 @@ pub struct SourceMap {
140
145
141
146
impl SourceMap {
142
147
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
+ }
144
154
}
145
155
146
156
pub fn with_file_loader (
147
157
file_loader : Box < dyn FileLoader + Sync + Send > ,
148
158
path_mapping : FilePathMapping ,
149
159
) -> 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
+ }
151
166
}
152
167
153
168
pub fn path_mapping ( & self ) -> & FilePathMapping {
@@ -194,12 +209,25 @@ impl SourceMap {
194
209
self . files . borrow ( ) . stable_id_to_source_file . get ( & stable_id) . map ( |sf| sf. clone ( ) )
195
210
}
196
211
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
+ }
203
231
}
204
232
}
205
233
@@ -218,8 +246,6 @@ impl SourceMap {
218
246
filename : FileName ,
219
247
src : String ,
220
248
) -> Result < Lrc < SourceFile > , OffsetOverflowError > {
221
- let start_pos = self . next_start_pos ( ) ;
222
-
223
249
// The path is used to determine the directory for loading submodules and
224
250
// include files, so it must be before remapping.
225
251
// Note that filename may not be a valid path, eg it may be `<anon>` etc,
@@ -241,13 +267,15 @@ impl SourceMap {
241
267
let lrc_sf = match self . source_file_by_stable_id ( file_id) {
242
268
Some ( lrc_sf) => lrc_sf,
243
269
None => {
270
+ let start_pos = self . allocate_address_space ( src. len ( ) ) ?;
271
+
244
272
let source_file = Lrc :: new ( SourceFile :: new (
245
273
filename,
246
274
was_remapped,
247
275
unmapped_path,
248
276
src,
249
277
Pos :: from_usize ( start_pos) ,
250
- ) ? ) ;
278
+ ) ) ;
251
279
252
280
let mut files = self . files . borrow_mut ( ) ;
253
281
@@ -277,7 +305,9 @@ impl SourceMap {
277
305
mut file_local_non_narrow_chars : Vec < NonNarrowChar > ,
278
306
mut file_local_normalized_pos : Vec < NormalizedPos > ,
279
307
) -> 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" ) ;
281
311
282
312
let end_pos = Pos :: from_usize ( start_pos + source_len) ;
283
313
let start_pos = Pos :: from_usize ( start_pos) ;
0 commit comments