Address review comments.

This commit is contained in:
Nicholas Nethercote 2022-06-02 11:43:14 +10:00
parent 0b81d7cdc6
commit 72de7c4102
3 changed files with 70 additions and 51 deletions

View File

@ -5,7 +5,7 @@ use crate::ich::StableHashingContext;
use rustc_ast as ast; use rustc_ast as ast;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_span::{BytePos, NormalizedPos, SourceFile, SourceFileLines}; use rustc_span::{BytePos, NormalizedPos, SourceFile};
use std::assert_matches::assert_matches; use std::assert_matches::assert_matches;
use smallvec::SmallVec; use smallvec::SmallVec;
@ -60,7 +60,7 @@ impl<'ctx> rustc_ast::HashStableContext for StableHashingContext<'ctx> {
impl<'a> HashStable<StableHashingContext<'a>> for SourceFile { impl<'a> HashStable<StableHashingContext<'a>> for SourceFile {
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
let SourceFile { let SourceFile {
ref name, // We hash the smaller name_hash instead of this name: _, // We hash the smaller name_hash instead of this
name_hash, name_hash,
cnum, cnum,
// Do not hash the source as it is not encoded // Do not hash the source as it is not encoded
@ -69,7 +69,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for SourceFile {
external_src: _, external_src: _,
start_pos, start_pos,
end_pos: _, end_pos: _,
ref lines, lines: _,
ref multibyte_chars, ref multibyte_chars,
ref non_narrow_chars, ref non_narrow_chars,
ref normalized_pos, ref normalized_pos,
@ -79,18 +79,15 @@ impl<'a> HashStable<StableHashingContext<'a>> for SourceFile {
src_hash.hash_stable(hcx, hasher); src_hash.hash_stable(hcx, hasher);
// We only hash the relative position within this source_file // We are always in `Lines` form by the time we reach here.
match &*lines.borrow() { assert!(self.lines.borrow().is_lines());
SourceFileLines::Lines { lines } => { self.lines(|lines| {
lines.len().hash_stable(hcx, hasher); // We only hash the relative position within this source_file
for &line in lines.iter() { lines.len().hash_stable(hcx, hasher);
stable_byte_pos(line, start_pos).hash_stable(hcx, hasher); for &line in lines.iter() {
} stable_byte_pos(line, start_pos).hash_stable(hcx, hasher);
} }
SourceFileLines::Diffs { .. } => { });
panic!("called hash_stable on SourceFileLines::Diffs for {:?}", name);
}
}
// We only hash the relative position within this source_file // We only hash the relative position within this source_file
multibyte_chars.len().hash_stable(hcx, hasher); multibyte_chars.len().hash_stable(hcx, hasher);

View File

@ -1225,37 +1225,47 @@ impl DebuggerVisualizerFile {
#[derive(Clone)] #[derive(Clone)]
pub enum SourceFileLines { pub enum SourceFileLines {
/// The source file lines, in decoded (random-access) form. /// The source file lines, in decoded (random-access) form.
Lines { lines: Vec<BytePos> }, Lines(Vec<BytePos>),
/// The source file lines in difference list form. This matches the form /// The source file lines, in undecoded difference list form.
/// used within metadata, which saves space by exploiting the fact that the Diffs(SourceFileDiffs),
/// lines list is sorted and individual lines are usually not that long. }
///
/// We read it directly from metadata and only decode it into `Lines` form
/// when necessary. This is a significant performance win, especially for
/// small crates where very little of `std`'s metadata is used.
Diffs {
/// Position of the first line. Note that this is always encoded as a
/// `BytePos` because it is often much larger than any of the
/// differences.
line_start: BytePos,
/// Always 1, 2, or 4. Always as small as possible, while being big impl SourceFileLines {
/// enough to hold the length of the longest line in the source file. pub fn is_lines(&self) -> bool {
/// The 1 case is by far the most common. matches!(self, SourceFileLines::Lines(_))
bytes_per_diff: usize, }
}
/// The number of diffs encoded in `raw_diffs`. Always one less than /// The source file lines in difference list form. This matches the form
/// the number of lines in the source file. /// used within metadata, which saves space by exploiting the fact that the
num_diffs: usize, /// lines list is sorted and individual lines are usually not that long.
///
/// We read it directly from metadata and only decode it into `Lines` form
/// when necessary. This is a significant performance win, especially for
/// small crates where very little of `std`'s metadata is used.
#[derive(Clone)]
pub struct SourceFileDiffs {
/// Position of the first line. Note that this is always encoded as a
/// `BytePos` because it is often much larger than any of the
/// differences.
line_start: BytePos,
/// The diffs in "raw" form. Each segment of `bytes_per_diff` length /// Always 1, 2, or 4. Always as small as possible, while being big
/// encodes one little-endian diff. Note that they aren't LEB128 /// enough to hold the length of the longest line in the source file.
/// encoded. This makes for much faster decoding. Besides, the /// The 1 case is by far the most common.
/// bytes_per_diff==1 case is by far the most common, and LEB128 bytes_per_diff: usize,
/// encoding has no effect on that case.
raw_diffs: Vec<u8>, /// The number of diffs encoded in `raw_diffs`. Always one less than
}, /// the number of lines in the source file.
num_diffs: usize,
/// The diffs in "raw" form. Each segment of `bytes_per_diff` length
/// encodes one little-endian diff. Note that they aren't LEB128
/// encoded. This makes for much faster decoding. Besides, the
/// bytes_per_diff==1 case is by far the most common, and LEB128
/// encoding has no effect on that case.
raw_diffs: Vec<u8>,
} }
/// A single source in the [`SourceMap`]. /// A single source in the [`SourceMap`].
@ -1298,6 +1308,8 @@ impl<S: Encoder> Encodable<S> for SourceFile {
s.emit_struct_field("start_pos", false, |s| self.start_pos.encode(s))?; s.emit_struct_field("start_pos", false, |s| self.start_pos.encode(s))?;
s.emit_struct_field("end_pos", false, |s| self.end_pos.encode(s))?; s.emit_struct_field("end_pos", false, |s| self.end_pos.encode(s))?;
s.emit_struct_field("lines", false, |s| { s.emit_struct_field("lines", false, |s| {
// We are always in `Lines` form by the time we reach here.
assert!(self.lines.borrow().is_lines());
self.lines(|lines| { self.lines(|lines| {
// Store the length. // Store the length.
s.emit_u32(lines.len() as u32)?; s.emit_u32(lines.len() as u32)?;
@ -1384,9 +1396,14 @@ impl<D: Decoder> Decodable<D> for SourceFile {
// Read the difference list. // Read the difference list.
let num_diffs = num_lines as usize - 1; let num_diffs = num_lines as usize - 1;
let raw_diffs = d.read_raw_bytes(bytes_per_diff * num_diffs).to_vec(); let raw_diffs = d.read_raw_bytes(bytes_per_diff * num_diffs).to_vec();
SourceFileLines::Diffs { line_start, bytes_per_diff, num_diffs, raw_diffs } SourceFileLines::Diffs(SourceFileDiffs {
line_start,
bytes_per_diff,
num_diffs,
raw_diffs,
})
} else { } else {
SourceFileLines::Lines { lines: vec![] } SourceFileLines::Lines(vec![])
} }
}; };
let multibyte_chars: Vec<MultiByteChar> = Decodable::decode(d); let multibyte_chars: Vec<MultiByteChar> = Decodable::decode(d);
@ -1448,7 +1465,7 @@ impl SourceFile {
external_src: Lock::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: Lock::new(SourceFileLines::Lines { lines }), lines: Lock::new(SourceFileLines::Lines(lines)),
multibyte_chars, multibyte_chars,
non_narrow_chars, non_narrow_chars,
normalized_pos, normalized_pos,
@ -1457,14 +1474,19 @@ impl SourceFile {
} }
} }
pub fn lines<F, R>(&self, mut f: F) -> R pub fn lines<F, R>(&self, f: F) -> R
where where
F: FnMut(&[BytePos]) -> R, F: FnOnce(&[BytePos]) -> R,
{ {
let mut guard = self.lines.borrow_mut(); let mut guard = self.lines.borrow_mut();
match &*guard { match &*guard {
SourceFileLines::Lines { lines } => f(lines), SourceFileLines::Lines(lines) => f(lines),
SourceFileLines::Diffs { mut line_start, bytes_per_diff, num_diffs, raw_diffs } => { SourceFileLines::Diffs(SourceFileDiffs {
mut line_start,
bytes_per_diff,
num_diffs,
raw_diffs,
}) => {
// Convert from "diffs" form to "lines" form. // Convert from "diffs" form to "lines" form.
let num_lines = num_diffs + 1; let num_lines = num_diffs + 1;
let mut lines = Vec::with_capacity(num_lines); let mut lines = Vec::with_capacity(num_lines);
@ -1504,7 +1526,7 @@ impl SourceFile {
_ => unreachable!(), _ => unreachable!(),
} }
let res = f(&lines); let res = f(&lines);
*guard = SourceFileLines::Lines { lines }; *guard = SourceFileLines::Lines(lines);
res res
} }
} }

View File

@ -356,12 +356,12 @@ impl SourceMap {
// compiler backend can optimize away the repeated computations in a // compiler backend can optimize away the repeated computations in a
// way that won't trigger overflow checks. // way that won't trigger overflow checks.
match &mut *file_local_lines.borrow_mut() { match &mut *file_local_lines.borrow_mut() {
SourceFileLines::Lines { lines } => { SourceFileLines::Lines(lines) => {
for pos in lines { for pos in lines {
*pos = (*pos - original_start_pos) + start_pos; *pos = (*pos - original_start_pos) + start_pos;
} }
} }
SourceFileLines::Diffs { line_start, .. } => { SourceFileLines::Diffs(SourceFileDiffs { line_start, .. }) => {
*line_start = (*line_start - original_start_pos) + start_pos; *line_start = (*line_start - original_start_pos) + start_pos;
} }
} }