Make FileMap thread-safe

This commit is contained in:
John Kåre Alsaker 2018-03-10 06:40:17 +01:00
parent 26fe97f1f9
commit 426c51d6ea
2 changed files with 55 additions and 45 deletions

View File

@ -417,24 +417,27 @@ impl<'a> HashStable<StableHashingContext<'a>> for FileMap {
src_hash.hash_stable(hcx, hasher); src_hash.hash_stable(hcx, hasher);
// We only hash the relative position within this filemap // We only hash the relative position within this filemap
let lines = lines.borrow(); lines.with_lock(|lines| {
lines.len().hash_stable(hcx, hasher); lines.len().hash_stable(hcx, hasher);
for &line in lines.iter() { for &line in lines.iter() {
stable_byte_pos(line, start_pos).hash_stable(hcx, hasher); stable_byte_pos(line, start_pos).hash_stable(hcx, hasher);
} }
});
// We only hash the relative position within this filemap // We only hash the relative position within this filemap
let multibyte_chars = multibyte_chars.borrow(); multibyte_chars.with_lock(|multibyte_chars| {
multibyte_chars.len().hash_stable(hcx, hasher); multibyte_chars.len().hash_stable(hcx, hasher);
for &char_pos in multibyte_chars.iter() { for &char_pos in multibyte_chars.iter() {
stable_multibyte_char(char_pos, start_pos).hash_stable(hcx, hasher); stable_multibyte_char(char_pos, start_pos).hash_stable(hcx, hasher);
} }
});
let non_narrow_chars = non_narrow_chars.borrow(); non_narrow_chars.with_lock(|non_narrow_chars| {
non_narrow_chars.len().hash_stable(hcx, hasher); non_narrow_chars.len().hash_stable(hcx, hasher);
for &char_pos in non_narrow_chars.iter() { for &char_pos in non_narrow_chars.iter() {
stable_non_narrow_char(char_pos, start_pos).hash_stable(hcx, hasher); stable_non_narrow_char(char_pos, start_pos).hash_stable(hcx, hasher);
} }
});
} }
} }

View File

@ -27,7 +27,7 @@
#![feature(specialization)] #![feature(specialization)]
use std::borrow::Cow; use std::borrow::Cow;
use std::cell::{Cell, RefCell}; use std::cell::Cell;
use std::cmp::{self, Ordering}; use std::cmp::{self, Ordering};
use std::fmt; use std::fmt;
use std::hash::{Hasher, Hash}; use std::hash::{Hasher, Hash};
@ -699,17 +699,17 @@ pub struct FileMap {
pub src_hash: u128, pub src_hash: u128,
/// The external source code (used for external crates, which will have a `None` /// The external source code (used for external crates, which will have a `None`
/// value as `self.src`. /// value as `self.src`.
pub external_src: RefCell<ExternalSource>, pub external_src: Lock<ExternalSource>,
/// The start position of this source in the CodeMap /// The start position of this source in the CodeMap
pub start_pos: BytePos, pub start_pos: BytePos,
/// The end position of this source in the CodeMap /// The end position of this source in the CodeMap
pub end_pos: BytePos, pub end_pos: BytePos,
/// Locations of lines beginnings in the source code /// Locations of lines beginnings in the source code
pub lines: RefCell<Vec<BytePos>>, pub lines: Lock<Vec<BytePos>>,
/// Locations of multi-byte characters in the source code /// Locations of multi-byte characters in the source code
pub multibyte_chars: RefCell<Vec<MultiByteChar>>, pub multibyte_chars: Lock<Vec<MultiByteChar>>,
/// Width of characters that are not narrow in the source code /// Width of characters that are not narrow in the source code
pub non_narrow_chars: RefCell<Vec<NonNarrowChar>>, pub non_narrow_chars: Lock<Vec<NonNarrowChar>>,
/// A hash of the filename, used for speeding up the incr. comp. hashing. /// A hash of the filename, used for speeding up the incr. comp. hashing.
pub name_hash: u128, pub name_hash: u128,
} }
@ -839,10 +839,10 @@ impl Decodable for FileMap {
end_pos, end_pos,
src: None, src: None,
src_hash, src_hash,
external_src: RefCell::new(ExternalSource::AbsentOk), external_src: Lock::new(ExternalSource::AbsentOk),
lines: RefCell::new(lines), lines: Lock::new(lines),
multibyte_chars: RefCell::new(multibyte_chars), multibyte_chars: Lock::new(multibyte_chars),
non_narrow_chars: RefCell::new(non_narrow_chars), non_narrow_chars: Lock::new(non_narrow_chars),
name_hash, name_hash,
}) })
}) })
@ -882,12 +882,12 @@ impl FileMap {
crate_of_origin: 0, crate_of_origin: 0,
src: Some(Lrc::new(src)), src: Some(Lrc::new(src)),
src_hash, src_hash,
external_src: RefCell::new(ExternalSource::Unneeded), external_src: Lock::new(ExternalSource::Unneeded),
start_pos, start_pos,
end_pos: Pos::from_usize(end_pos), end_pos: Pos::from_usize(end_pos),
lines: RefCell::new(Vec::new()), lines: Lock::new(Vec::new()),
multibyte_chars: RefCell::new(Vec::new()), multibyte_chars: Lock::new(Vec::new()),
non_narrow_chars: RefCell::new(Vec::new()), non_narrow_chars: Lock::new(Vec::new()),
name_hash, name_hash,
} }
} }
@ -919,6 +919,8 @@ impl FileMap {
if *self.external_src.borrow() == ExternalSource::AbsentOk { if *self.external_src.borrow() == ExternalSource::AbsentOk {
let src = get_src(); let src = get_src();
let mut external_src = self.external_src.borrow_mut(); let mut external_src = self.external_src.borrow_mut();
// Check that no-one else have provided the source while we were getting it
if *external_src == ExternalSource::AbsentOk {
if let Some(src) = src { if let Some(src) = src {
let mut hasher: StableHasher<u128> = StableHasher::new(); let mut hasher: StableHasher<u128> = StableHasher::new();
hasher.write(src.as_bytes()); hasher.write(src.as_bytes());
@ -932,6 +934,9 @@ impl FileMap {
} }
false false
} else {
self.src.is_some() || external_src.get_source().is_some()
}
} else { } else {
self.src.is_some() || self.external_src.borrow().get_source().is_some() self.src.is_some() || self.external_src.borrow().get_source().is_some()
} }
@ -951,6 +956,7 @@ impl FileMap {
} }
} }
let begin = {
let lines = self.lines.borrow(); let lines = self.lines.borrow();
let line = if let Some(line) = lines.get(line_number) { let line = if let Some(line) = lines.get(line_number) {
line line
@ -958,7 +964,8 @@ impl FileMap {
return None; return None;
}; };
let begin: BytePos = *line - self.start_pos; let begin: BytePos = *line - self.start_pos;
let begin = begin.to_usize(); begin.to_usize()
};
if let Some(ref src) = self.src { if let Some(ref src) = self.src {
Some(Cow::from(get_until_newline(src, begin))) Some(Cow::from(get_until_newline(src, begin)))