Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Directly save a byte representation of the dep-graph and work-product index #83322

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 78 additions & 5 deletions compiler/rustc_incremental/src/persist/file_format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ use std::io::{self, Read};
use std::path::{Path, PathBuf};

use rustc_data_structures::memmap::Mmap;
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
use rustc_serialize::Encoder;
use rustc_serialize::{opaque, raw, Encoder};
use rustc_session::Session;

/// The first few bytes of files generated by incremental compilation.
Expand All @@ -30,7 +29,26 @@ const HEADER_FORMAT_VERSION: u16 = 0;
/// the Git commit hash.
const RUSTC_VERSION: Option<&str> = option_env!("CFG_VERSION");

pub(crate) fn write_file_header(stream: &mut FileEncoder, nightly_build: bool) -> FileEncodeResult {
pub(crate) fn write_file_header(
stream: &mut opaque::FileEncoder,
nightly_build: bool,
) -> opaque::FileEncodeResult {
stream.emit_raw_bytes(FILE_MAGIC)?;
stream.emit_raw_bytes(&[
(HEADER_FORMAT_VERSION >> 0) as u8,
(HEADER_FORMAT_VERSION >> 8) as u8,
])?;

let rustc_version = rustc_version(nightly_build);
assert_eq!(rustc_version.len(), (rustc_version.len() as u8) as usize);
stream.emit_raw_bytes(&[rustc_version.len() as u8])?;
cjgillot marked this conversation as resolved.
Show resolved Hide resolved
stream.emit_raw_bytes(rustc_version.as_bytes())
}

pub(crate) fn write_file_header_raw(
stream: &mut raw::FileEncoder,
nightly_build: bool,
) -> raw::FileEncodeResult {
stream.emit_raw_bytes(FILE_MAGIC)?;
stream.emit_raw_bytes(&[
(HEADER_FORMAT_VERSION >> 0) as u8,
Expand All @@ -45,7 +63,7 @@ pub(crate) fn write_file_header(stream: &mut FileEncoder, nightly_build: bool) -

pub(crate) fn save_in<F>(sess: &Session, path_buf: PathBuf, name: &str, encode: F)
where
F: FnOnce(&mut FileEncoder) -> FileEncodeResult,
F: FnOnce(&mut opaque::FileEncoder) -> opaque::FileEncodeResult,
{
debug!("save: storing data in {}", path_buf.display());

Expand All @@ -72,7 +90,7 @@ where
}
}

let mut encoder = match FileEncoder::new(&path_buf) {
let mut encoder = match opaque::FileEncoder::new(&path_buf) {
Ok(encoder) => encoder,
Err(err) => {
sess.err(&format!("failed to create {} at `{}`: {}", name, path_buf.display(), err));
Expand Down Expand Up @@ -104,6 +122,61 @@ where
debug!("save: data written to disk successfully");
}

pub(crate) fn save_in_raw<F>(sess: &Session, path_buf: PathBuf, name: &str, encode: F)
where
F: FnOnce(&mut raw::FileEncoder) -> raw::FileEncodeResult,
{
debug!("save: storing data in {}", path_buf.display());

// Delete the old file, if any.
// Note: It's important that we actually delete the old file and not just
// truncate and overwrite it, since it might be a shared hard-link, the
// underlying data of which we don't want to modify.
//
// We have to ensure we have dropped the memory maps to this file
// before performing this removal.
match fs::remove_file(&path_buf) {
Ok(()) => {
debug!("save: remove old file");
}
Err(err) if err.kind() == io::ErrorKind::NotFound => (),
Err(err) => {
sess.err(&format!(
"unable to delete old {} at `{}`: {}",
name,
path_buf.display(),
err
));
return;
}
}

let mut encoder = match raw::FileEncoder::new(&path_buf) {
Ok(encoder) => encoder,
Err(err) => {
sess.err(&format!("failed to create {} at `{}`: {}", name, path_buf.display(), err));
return;
}
};

if let Err(err) = write_file_header_raw(&mut encoder, sess.is_nightly_build()) {
sess.err(&format!("failed to write {} header to `{}`: {}", name, path_buf.display(), err));
return;
}

if let Err(err) = encode(&mut encoder) {
sess.err(&format!("failed to write {} to `{}`: {}", name, path_buf.display(), err));
return;
}

if let Err(err) = encoder.flush() {
sess.err(&format!("failed to flush {} to `{}`: {}", name, path_buf.display(), err));
return;
}

debug!("save: data written to disk successfully");
}

/// Reads the contents of a file with a file header as defined in this module.
///
/// - Returns `Ok(Some(data, pos))` if the file existed and was generated by a
Expand Down
7 changes: 3 additions & 4 deletions compiler/rustc_incremental/src/persist/load.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::memmap::Mmap;
use rustc_middle::dep_graph::{SerializedDepGraph, WorkProduct, WorkProductId};
use rustc_middle::ty::OnDiskCache;
use rustc_serialize::opaque::Decoder;
use rustc_serialize::Decodable;
use rustc_serialize::{raw, Decodable};
use rustc_session::config::IncrementalStateAssertion;
use rustc_session::Session;
use std::path::Path;
Expand Down Expand Up @@ -156,7 +155,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {

if let LoadResult::Ok { data: (work_products_data, start_pos) } = load_result {
// Decode the list of work_products
let mut work_product_decoder = Decoder::new(&work_products_data[..], start_pos);
let mut work_product_decoder = raw::Decoder::new(&work_products_data[..], start_pos);
let work_products: Vec<SerializedWorkProduct> =
Decodable::decode(&mut work_product_decoder);

Expand Down Expand Up @@ -195,7 +194,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
LoadResult::DataOutOfDate => LoadResult::DataOutOfDate,
LoadResult::Error { message } => LoadResult::Error { message },
LoadResult::Ok { data: (bytes, start_pos) } => {
let mut decoder = Decoder::new(&bytes, start_pos);
let mut decoder = raw::Decoder::new(&bytes, start_pos);
let prev_commandline_args_hash = u64::decode(&mut decoder);

if prev_commandline_args_hash != expected_hash {
Expand Down
18 changes: 11 additions & 7 deletions compiler/rustc_incremental/src/persist/save.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::join;
use rustc_middle::dep_graph::{DepGraph, SerializedDepGraph, WorkProduct, WorkProductId};
use rustc_middle::ty::TyCtxt;
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
use rustc_serialize::opaque;
use rustc_serialize::raw;
use rustc_serialize::Encodable as RustcEncodable;
use rustc_session::Session;
use std::fs;
Expand Down Expand Up @@ -96,7 +97,7 @@ pub fn save_work_product_index(
debug!("save_work_product_index()");
dep_graph.assert_ignored();
let path = work_products_path(sess);
file_format::save_in(sess, path, "work product index", |e| {
file_format::save_in_raw(sess, path, "work product index", |e| {
encode_work_product_index(&new_work_products, e)
});

Expand Down Expand Up @@ -127,8 +128,8 @@ pub fn save_work_product_index(

fn encode_work_product_index(
work_products: &FxHashMap<WorkProductId, WorkProduct>,
encoder: &mut FileEncoder,
) -> FileEncodeResult {
encoder: &mut raw::FileEncoder,
) -> raw::FileEncodeResult {
let serialized_products: Vec<_> = work_products
.iter()
.map(|(id, work_product)| SerializedWorkProduct {
Expand All @@ -140,7 +141,10 @@ fn encode_work_product_index(
serialized_products.encode(encoder)
}

fn encode_query_cache(tcx: TyCtxt<'_>, encoder: &mut FileEncoder) -> FileEncodeResult {
fn encode_query_cache(
tcx: TyCtxt<'_>,
encoder: &mut opaque::FileEncoder,
) -> opaque::FileEncodeResult {
tcx.sess.time("incr_comp_serialize_result_cache", || tcx.serialize_query_result_cache(encoder))
}

Expand All @@ -163,7 +167,7 @@ pub fn build_dep_graph(
// Stream the dep-graph to an alternate file, to avoid overwriting anything in case of errors.
let path_buf = staging_dep_graph_path(sess);

let mut encoder = match FileEncoder::new(&path_buf) {
let mut encoder = match raw::FileEncoder::new(&path_buf) {
Ok(encoder) => encoder,
Err(err) => {
sess.err(&format!(
Expand All @@ -175,7 +179,7 @@ pub fn build_dep_graph(
}
};

if let Err(err) = file_format::write_file_header(&mut encoder, sess.is_nightly_build()) {
if let Err(err) = file_format::write_file_header_raw(&mut encoder, sess.is_nightly_build()) {
sess.err(&format!(
"failed to write dependency graph header to `{}`: {}",
path_buf.display(),
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_query_impl/src/on_disk_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_query_system::dep_graph::DepContext;
use rustc_query_system::query::{QueryCache, QueryContext, QuerySideEffects};
use rustc_serialize::{
opaque::{self, FileEncodeResult, FileEncoder, IntEncodedWithFixedSize},
Decodable, Decoder, Encodable, Encoder,
opaque::{self, FileEncodeResult, FileEncoder},
Decodable, Decoder, Encodable, Encoder, IntEncodedWithFixedSize,
};
use rustc_session::Session;
use rustc_span::hygiene::{
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_query_system/src/dep_graph/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::steal::Steal;
use rustc_data_structures::sync::{AtomicU32, AtomicU64, Lock, Lrc, Ordering};
use rustc_index::vec::IndexVec;
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
use rustc_serialize::raw::{FileEncodeResult, FileEncoder};
use smallvec::{smallvec, SmallVec};
use std::assert_matches::assert_matches;
use std::collections::hash_map::Entry;
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_query_system/src/dep_graph/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub use serialized::{SerializedDepGraph, SerializedDepNodeIndex};

use crate::ich::StableHashingContext;
use rustc_data_structures::profiling::SelfProfilerRef;
use rustc_serialize::{opaque::FileEncoder, Encodable};
use rustc_serialize::{raw::FileEncoder, Encodable};
use rustc_session::Session;

use std::fmt;
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_query_system/src/dep_graph/serialized.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::profiling::SelfProfilerRef;
use rustc_data_structures::sync::Lock;
use rustc_index::vec::{Idx, IndexVec};
use rustc_serialize::opaque::{self, FileEncodeResult, FileEncoder, IntEncodedWithFixedSize};
use rustc_serialize::{Decodable, Decoder, Encodable};
use rustc_serialize::raw::{self, FileEncodeResult, FileEncoder};
use rustc_serialize::{Decodable, Decoder, Encodable, IntEncodedWithFixedSize};
use smallvec::SmallVec;
use std::convert::TryInto;

Expand Down Expand Up @@ -96,11 +96,11 @@ impl<K: DepKind> SerializedDepGraph<K> {
}
}

impl<'a, K: DepKind + Decodable<opaque::Decoder<'a>>> Decodable<opaque::Decoder<'a>>
impl<'a, K: DepKind + Decodable<raw::Decoder<'a>>> Decodable<raw::Decoder<'a>>
for SerializedDepGraph<K>
{
#[instrument(level = "debug", skip(d))]
fn decode(d: &mut opaque::Decoder<'a>) -> SerializedDepGraph<K> {
fn decode(d: &mut raw::Decoder<'a>) -> SerializedDepGraph<K> {
let start_position = d.position();

// The last 16 bytes are the node count and edge count.
Expand Down
81 changes: 81 additions & 0 deletions compiler/rustc_serialize/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ Core encoding and decoding interfaces.
#![cfg_attr(test, feature(test))]
#![allow(rustc::internal)]

use std::convert::TryInto;

pub use self::serialize::{Decodable, Decoder, Encodable, Encoder};

mod collection_impls;
Expand All @@ -29,3 +31,82 @@ pub mod json;

pub mod leb128;
pub mod opaque;

pub mod raw;

// An integer that will always encode to 8 bytes.
pub struct IntEncodedWithFixedSize(pub u64);

impl IntEncodedWithFixedSize {
pub const ENCODED_SIZE: usize = 8;
}

impl Encodable<opaque::Encoder> for IntEncodedWithFixedSize {
#[inline]
fn encode(&self, e: &mut opaque::Encoder) -> opaque::EncodeResult {
let _start_pos = e.position();
e.emit_raw_bytes(&self.0.to_le_bytes())?;
let _end_pos = e.position();
debug_assert_eq!((_end_pos - _start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);
Ok(())
}
}

impl Encodable<opaque::FileEncoder> for IntEncodedWithFixedSize {
#[inline]
fn encode(&self, e: &mut opaque::FileEncoder) -> opaque::FileEncodeResult {
let _start_pos = e.position();
e.emit_raw_bytes(&self.0.to_le_bytes())?;
let _end_pos = e.position();
debug_assert_eq!((_end_pos - _start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);
Ok(())
}
}

impl<'a> Decodable<opaque::Decoder<'a>> for IntEncodedWithFixedSize {
#[inline]
fn decode(decoder: &mut opaque::Decoder<'a>) -> IntEncodedWithFixedSize {
let _start_pos = decoder.position();
let bytes = decoder.read_raw_bytes(IntEncodedWithFixedSize::ENCODED_SIZE);
let value = u64::from_le_bytes(bytes.try_into().unwrap());
let _end_pos = decoder.position();
debug_assert_eq!((_end_pos - _start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);

IntEncodedWithFixedSize(value)
}
}

impl Encodable<raw::Encoder> for IntEncodedWithFixedSize {
#[inline]
fn encode(&self, e: &mut raw::Encoder) -> raw::EncodeResult {
let _start_pos = e.position();
e.emit_raw_bytes(&self.0.to_le_bytes())?;
let _end_pos = e.position();
debug_assert_eq!((_end_pos - _start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);
Ok(())
}
}

impl Encodable<raw::FileEncoder> for IntEncodedWithFixedSize {
#[inline]
fn encode(&self, e: &mut raw::FileEncoder) -> raw::FileEncodeResult {
let _start_pos = e.position();
e.emit_raw_bytes(&self.0.to_le_bytes())?;
let _end_pos = e.position();
debug_assert_eq!((_end_pos - _start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);
Ok(())
}
}

impl<'a> Decodable<raw::Decoder<'a>> for IntEncodedWithFixedSize {
#[inline]
fn decode(decoder: &mut raw::Decoder<'a>) -> IntEncodedWithFixedSize {
let _start_pos = decoder.position();
let bytes = decoder.read_raw_bytes(IntEncodedWithFixedSize::ENCODED_SIZE);
let _end_pos = decoder.position();
debug_assert_eq!((_end_pos - _start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);

let value = u64::from_le_bytes(bytes.try_into().unwrap());
IntEncodedWithFixedSize(value)
}
}
Loading