Auto merge of #48904 - Zoxc:code-and-file-maps, r=michaelwoerister

Make CodeMap and FileMap thread-safe

r? @michaelwoerister
This commit is contained in:
bors 2018-03-17 08:54:22 +00:00
commit c3fd5d0dde
8 changed files with 112 additions and 99 deletions

View file

@ -24,8 +24,7 @@ pub use self::ExpnFormat::*;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::StableHasher;
use rustc_data_structures::sync::Lrc;
use std::cell::{RefCell, Ref};
use rustc_data_structures::sync::{Lrc, Lock, LockGuard};
use std::cmp;
use std::hash::Hash;
use std::path::{Path, PathBuf};
@ -125,13 +124,17 @@ impl StableFilemapId {
// CodeMap
//
pub(super) struct CodeMapFiles {
pub(super) file_maps: Vec<Lrc<FileMap>>,
stable_id_to_filemap: FxHashMap<StableFilemapId, Lrc<FileMap>>
}
pub struct CodeMap {
pub(super) files: RefCell<Vec<Lrc<FileMap>>>,
file_loader: Box<FileLoader>,
pub(super) files: Lock<CodeMapFiles>,
file_loader: Box<FileLoader + Sync + Send>,
// This is used to apply the file path remapping as specified via
// --remap-path-prefix to all FileMaps allocated within this CodeMap.
path_mapping: FilePathMapping,
stable_id_to_filemap: RefCell<FxHashMap<StableFilemapId, Lrc<FileMap>>>,
/// In case we are in a doctest, replace all file names with the PathBuf,
/// and add the given offsets to the line info
doctest_offset: Option<(FileName, isize)>,
@ -140,10 +143,12 @@ pub struct CodeMap {
impl CodeMap {
pub fn new(path_mapping: FilePathMapping) -> CodeMap {
CodeMap {
files: RefCell::new(Vec::new()),
files: Lock::new(CodeMapFiles {
file_maps: Vec::new(),
stable_id_to_filemap: FxHashMap(),
}),
file_loader: Box::new(RealFileLoader),
path_mapping,
stable_id_to_filemap: RefCell::new(FxHashMap()),
doctest_offset: None,
}
}
@ -157,14 +162,16 @@ impl CodeMap {
}
pub fn with_file_loader(file_loader: Box<FileLoader>,
pub fn with_file_loader(file_loader: Box<FileLoader + Sync + Send>,
path_mapping: FilePathMapping)
-> CodeMap {
CodeMap {
files: RefCell::new(Vec::new()),
file_loader,
files: Lock::new(CodeMapFiles {
file_maps: Vec::new(),
stable_id_to_filemap: FxHashMap(),
}),
file_loader: file_loader,
path_mapping,
stable_id_to_filemap: RefCell::new(FxHashMap()),
doctest_offset: None,
}
}
@ -187,17 +194,16 @@ impl CodeMap {
Ok(self.new_filemap(filename, src))
}
pub fn files(&self) -> Ref<Vec<Lrc<FileMap>>> {
self.files.borrow()
pub fn files(&self) -> LockGuard<Vec<Lrc<FileMap>>> {
LockGuard::map(self.files.borrow(), |files| &mut files.file_maps)
}
pub fn filemap_by_stable_id(&self, stable_id: StableFilemapId) -> Option<Lrc<FileMap>> {
self.stable_id_to_filemap.borrow().get(&stable_id).map(|fm| fm.clone())
self.files.borrow().stable_id_to_filemap.get(&stable_id).map(|fm| fm.clone())
}
fn next_start_pos(&self) -> usize {
let files = self.files.borrow();
match files.last() {
match self.files.borrow().file_maps.last() {
None => 0,
// Add one so there is some space between files. This lets us distinguish
// positions in the codemap, even in the presence of zero-length files.
@ -207,9 +213,9 @@ impl CodeMap {
/// Creates a new filemap without setting its line information. If you don't
/// intend to set the line information yourself, you should use new_filemap_and_lines.
/// This does not ensure that only one FileMap exists per file name.
pub fn new_filemap(&self, filename: FileName, src: String) -> Lrc<FileMap> {
let start_pos = self.next_start_pos();
let mut files = self.files.borrow_mut();
// The path is used to determine the directory for loading submodules and
// include files, so it must be before remapping.
@ -233,16 +239,16 @@ impl CodeMap {
Pos::from_usize(start_pos),
));
files.push(filemap.clone());
let mut files = self.files.borrow_mut();
self.stable_id_to_filemap
.borrow_mut()
.insert(StableFilemapId::new(&filemap), filemap.clone());
files.file_maps.push(filemap.clone());
files.stable_id_to_filemap.insert(StableFilemapId::new(&filemap), filemap.clone());
filemap
}
/// Creates a new filemap and sets its line information.
/// This does not ensure that only one FileMap exists per file name.
pub fn new_filemap_and_lines(&self, filename: &Path, src: &str) -> Lrc<FileMap> {
let fm = self.new_filemap(filename.to_owned().into(), src.to_owned());
let mut byte_pos: u32 = fm.start_pos.0;
@ -273,7 +279,6 @@ impl CodeMap {
mut file_local_non_narrow_chars: Vec<NonNarrowChar>)
-> Lrc<FileMap> {
let start_pos = self.next_start_pos();
let mut files = self.files.borrow_mut();
let end_pos = Pos::from_usize(start_pos + source_len);
let start_pos = Pos::from_usize(start_pos);
@ -297,20 +302,19 @@ impl CodeMap {
crate_of_origin,
src: None,
src_hash,
external_src: RefCell::new(ExternalSource::AbsentOk),
external_src: Lock::new(ExternalSource::AbsentOk),
start_pos,
end_pos,
lines: RefCell::new(file_local_lines),
multibyte_chars: RefCell::new(file_local_multibyte_chars),
non_narrow_chars: RefCell::new(file_local_non_narrow_chars),
lines: Lock::new(file_local_lines),
multibyte_chars: Lock::new(file_local_multibyte_chars),
non_narrow_chars: Lock::new(file_local_non_narrow_chars),
name_hash,
});
files.push(filemap.clone());
let mut files = self.files.borrow_mut();
self.stable_id_to_filemap
.borrow_mut()
.insert(StableFilemapId::new(&filemap), filemap.clone());
files.file_maps.push(filemap.clone());
files.stable_id_to_filemap.insert(StableFilemapId::new(&filemap), filemap.clone());
filemap
}
@ -401,8 +405,7 @@ impl CodeMap {
pub fn lookup_line(&self, pos: BytePos) -> Result<FileMapAndLine, Lrc<FileMap>> {
let idx = self.lookup_filemap_idx(pos);
let files = self.files.borrow();
let f = (*files)[idx].clone();
let f = (*self.files.borrow().file_maps)[idx].clone();
match f.lookup_line(pos) {
Some(line) => Ok(FileMapAndLine { fm: f, line: line }),
@ -456,7 +459,7 @@ impl CodeMap {
}
pub fn span_to_string(&self, sp: Span) -> String {
if self.files.borrow().is_empty() && sp.source_equal(&DUMMY_SP) {
if self.files.borrow().file_maps.is_empty() && sp.source_equal(&DUMMY_SP) {
return "no-location".to_string();
}
@ -799,7 +802,7 @@ impl CodeMap {
}
pub fn get_filemap(&self, filename: &FileName) -> Option<Lrc<FileMap>> {
for fm in self.files.borrow().iter() {
for fm in self.files.borrow().file_maps.iter() {
if *filename == fm.name {
return Some(fm.clone());
}
@ -810,7 +813,7 @@ impl CodeMap {
/// For a global BytePos compute the local offset within the containing FileMap
pub fn lookup_byte_offset(&self, bpos: BytePos) -> FileMapAndBytePos {
let idx = self.lookup_filemap_idx(bpos);
let fm = (*self.files.borrow())[idx].clone();
let fm = (*self.files.borrow().file_maps)[idx].clone();
let offset = bpos - fm.start_pos;
FileMapAndBytePos {fm: fm, pos: offset}
}
@ -818,8 +821,7 @@ impl CodeMap {
/// Converts an absolute BytePos to a CharPos relative to the filemap.
pub fn bytepos_to_file_charpos(&self, bpos: BytePos) -> CharPos {
let idx = self.lookup_filemap_idx(bpos);
let files = self.files.borrow();
let map = &(*files)[idx];
let map = &(*self.files.borrow().file_maps)[idx];
// The number of extra bytes due to multibyte chars in the FileMap
let mut total_extra_bytes = 0;
@ -845,7 +847,7 @@ impl CodeMap {
// Return the index of the filemap (in self.files) which contains pos.
pub fn lookup_filemap_idx(&self, pos: BytePos) -> usize {
let files = self.files.borrow();
let files = &*files;
let files = &files.file_maps;
let count = files.len();
// Binary search for the filemap.